summaryrefslogtreecommitdiff
path: root/libjava/classpath/java/awt
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/java/awt')
-rw-r--r--libjava/classpath/java/awt/AWTError.java64
-rw-r--r--libjava/classpath/java/awt/AWTEvent.java399
-rw-r--r--libjava/classpath/java/awt/AWTEventMulticaster.java1210
-rw-r--r--libjava/classpath/java/awt/AWTException.java64
-rw-r--r--libjava/classpath/java/awt/AWTKeyStroke.java676
-rw-r--r--libjava/classpath/java/awt/AWTPermission.java121
-rw-r--r--libjava/classpath/java/awt/ActiveEvent.java61
-rw-r--r--libjava/classpath/java/awt/Adjustable.java171
-rw-r--r--libjava/classpath/java/awt/AlphaComposite.java215
-rw-r--r--libjava/classpath/java/awt/AttributeValue.java98
-rw-r--r--libjava/classpath/java/awt/BasicStroke.java902
-rw-r--r--libjava/classpath/java/awt/BorderLayout.java742
-rw-r--r--libjava/classpath/java/awt/BufferCapabilities.java253
-rw-r--r--libjava/classpath/java/awt/Button.java467
-rw-r--r--libjava/classpath/java/awt/Canvas.java354
-rw-r--r--libjava/classpath/java/awt/CardLayout.java501
-rw-r--r--libjava/classpath/java/awt/Checkbox.java665
-rw-r--r--libjava/classpath/java/awt/CheckboxGroup.java172
-rw-r--r--libjava/classpath/java/awt/CheckboxMenuItem.java376
-rw-r--r--libjava/classpath/java/awt/Choice.java569
-rw-r--r--libjava/classpath/java/awt/Color.java1025
-rw-r--r--libjava/classpath/java/awt/ColorPaintContext.java195
-rw-r--r--libjava/classpath/java/awt/Component.java7099
-rw-r--r--libjava/classpath/java/awt/ComponentOrientation.java215
-rw-r--r--libjava/classpath/java/awt/Composite.java73
-rw-r--r--libjava/classpath/java/awt/CompositeContext.java71
-rw-r--r--libjava/classpath/java/awt/Container.java2370
-rw-r--r--libjava/classpath/java/awt/ContainerOrderFocusTraversalPolicy.java482
-rw-r--r--libjava/classpath/java/awt/Cursor.java239
-rw-r--r--libjava/classpath/java/awt/DefaultFocusTraversalPolicy.java111
-rw-r--r--libjava/classpath/java/awt/DefaultKeyboardFocusManager.java566
-rw-r--r--libjava/classpath/java/awt/Desktop.java268
-rw-r--r--libjava/classpath/java/awt/Dialog.java570
-rw-r--r--libjava/classpath/java/awt/Dimension.java234
-rw-r--r--libjava/classpath/java/awt/DisplayMode.java164
-rw-r--r--libjava/classpath/java/awt/Event.java185
-rw-r--r--libjava/classpath/java/awt/EventDispatchThread.java107
-rw-r--r--libjava/classpath/java/awt/EventQueue.java658
-rw-r--r--libjava/classpath/java/awt/FileDialog.java395
-rw-r--r--libjava/classpath/java/awt/FlowLayout.java365
-rw-r--r--libjava/classpath/java/awt/FocusTraversalPolicy.java103
-rw-r--r--libjava/classpath/java/awt/Font.java1451
-rw-r--r--libjava/classpath/java/awt/FontFormatException.java65
-rw-r--r--libjava/classpath/java/awt/FontMetrics.java448
-rw-r--r--libjava/classpath/java/awt/Frame.java704
-rw-r--r--libjava/classpath/java/awt/GradientPaint.java229
-rw-r--r--libjava/classpath/java/awt/Graphics.java639
-rw-r--r--libjava/classpath/java/awt/Graphics2D.java358
-rw-r--r--libjava/classpath/java/awt/GraphicsConfigTemplate.java106
-rw-r--r--libjava/classpath/java/awt/GraphicsConfiguration.java275
-rw-r--r--libjava/classpath/java/awt/GraphicsDevice.java292
-rw-r--r--libjava/classpath/java/awt/GraphicsEnvironment.java244
-rw-r--r--libjava/classpath/java/awt/GridBagConstraints.java246
-rw-r--r--libjava/classpath/java/awt/GridBagLayout.java1114
-rw-r--r--libjava/classpath/java/awt/GridBagLayoutInfo.java70
-rw-r--r--libjava/classpath/java/awt/GridLayout.java354
-rw-r--r--libjava/classpath/java/awt/HeadlessException.java72
-rw-r--r--libjava/classpath/java/awt/IllegalComponentStateException.java71
-rw-r--r--libjava/classpath/java/awt/Image.java242
-rw-r--r--libjava/classpath/java/awt/ImageCapabilities.java107
-rw-r--r--libjava/classpath/java/awt/Insets.java177
-rw-r--r--libjava/classpath/java/awt/ItemSelectable.java75
-rw-r--r--libjava/classpath/java/awt/JobAttributes.java502
-rw-r--r--libjava/classpath/java/awt/KeyEventDispatcher.java82
-rw-r--r--libjava/classpath/java/awt/KeyEventPostProcessor.java81
-rw-r--r--libjava/classpath/java/awt/KeyboardFocusManager.java1479
-rw-r--r--libjava/classpath/java/awt/Label.java294
-rw-r--r--libjava/classpath/java/awt/LayoutManager.java92
-rw-r--r--libjava/classpath/java/awt/LayoutManager2.java100
-rw-r--r--libjava/classpath/java/awt/LightweightDispatcher.java362
-rw-r--r--libjava/classpath/java/awt/List.java1222
-rw-r--r--libjava/classpath/java/awt/MediaTracker.java698
-rw-r--r--libjava/classpath/java/awt/Menu.java444
-rw-r--r--libjava/classpath/java/awt/MenuBar.java390
-rw-r--r--libjava/classpath/java/awt/MenuComponent.java1302
-rw-r--r--libjava/classpath/java/awt/MenuContainer.java71
-rw-r--r--libjava/classpath/java/awt/MenuItem.java623
-rw-r--r--libjava/classpath/java/awt/MenuShortcut.java434
-rw-r--r--libjava/classpath/java/awt/MouseInfo.java102
-rw-r--r--libjava/classpath/java/awt/PageAttributes.java482
-rw-r--r--libjava/classpath/java/awt/Paint.java79
-rw-r--r--libjava/classpath/java/awt/PaintContext.java76
-rw-r--r--libjava/classpath/java/awt/Panel.java173
-rw-r--r--libjava/classpath/java/awt/Point.java250
-rw-r--r--libjava/classpath/java/awt/PointerInfo.java84
-rw-r--r--libjava/classpath/java/awt/Polygon.java611
-rw-r--r--libjava/classpath/java/awt/PopupMenu.java190
-rw-r--r--libjava/classpath/java/awt/PrintGraphics.java57
-rw-r--r--libjava/classpath/java/awt/PrintJob.java104
-rw-r--r--libjava/classpath/java/awt/Rectangle.java753
-rw-r--r--libjava/classpath/java/awt/RenderingHints.java804
-rw-r--r--libjava/classpath/java/awt/Robot.java423
-rw-r--r--libjava/classpath/java/awt/ScrollPane.java680
-rw-r--r--libjava/classpath/java/awt/ScrollPaneAdjustable.java241
-rw-r--r--libjava/classpath/java/awt/Scrollbar.java815
-rw-r--r--libjava/classpath/java/awt/Shape.java205
-rw-r--r--libjava/classpath/java/awt/Stroke.java65
-rw-r--r--libjava/classpath/java/awt/SystemColor.java462
-rw-r--r--libjava/classpath/java/awt/TextArea.java631
-rw-r--r--libjava/classpath/java/awt/TextComponent.java676
-rw-r--r--libjava/classpath/java/awt/TextField.java484
-rw-r--r--libjava/classpath/java/awt/TexturePaint.java118
-rw-r--r--libjava/classpath/java/awt/Toolkit.java1429
-rw-r--r--libjava/classpath/java/awt/Transparency.java67
-rw-r--r--libjava/classpath/java/awt/Window.java1286
-rw-r--r--libjava/classpath/java/awt/color/CMMException.java63
-rw-r--r--libjava/classpath/java/awt/color/ColorSpace.java183
-rw-r--r--libjava/classpath/java/awt/color/ICC_ColorSpace.java314
-rw-r--r--libjava/classpath/java/awt/color/ICC_Profile.java1249
-rw-r--r--libjava/classpath/java/awt/color/ICC_ProfileGray.java133
-rw-r--r--libjava/classpath/java/awt/color/ICC_ProfileRGB.java227
-rw-r--r--libjava/classpath/java/awt/color/ProfileDataException.java64
-rw-r--r--libjava/classpath/java/awt/color/package.html46
-rw-r--r--libjava/classpath/java/awt/datatransfer/Clipboard.java213
-rw-r--r--libjava/classpath/java/awt/datatransfer/ClipboardOwner.java56
-rw-r--r--libjava/classpath/java/awt/datatransfer/DataFlavor.java1026
-rw-r--r--libjava/classpath/java/awt/datatransfer/FlavorEvent.java57
-rw-r--r--libjava/classpath/java/awt/datatransfer/FlavorListener.java54
-rw-r--r--libjava/classpath/java/awt/datatransfer/FlavorMap.java75
-rw-r--r--libjava/classpath/java/awt/datatransfer/FlavorTable.java73
-rw-r--r--libjava/classpath/java/awt/datatransfer/MimeType.java283
-rw-r--r--libjava/classpath/java/awt/datatransfer/MimeTypeParseException.java70
-rw-r--r--libjava/classpath/java/awt/datatransfer/StringSelection.java157
-rw-r--r--libjava/classpath/java/awt/datatransfer/SystemFlavorMap.java561
-rw-r--r--libjava/classpath/java/awt/datatransfer/Transferable.java82
-rw-r--r--libjava/classpath/java/awt/datatransfer/UnsupportedFlavorException.java65
-rw-r--r--libjava/classpath/java/awt/datatransfer/package.html47
-rw-r--r--libjava/classpath/java/awt/dnd/Autoscroll.java69
-rw-r--r--libjava/classpath/java/awt/dnd/DnDConstants.java77
-rw-r--r--libjava/classpath/java/awt/dnd/DnDEventMulticaster.java74
-rw-r--r--libjava/classpath/java/awt/dnd/DragGestureEvent.java219
-rw-r--r--libjava/classpath/java/awt/dnd/DragGestureListener.java63
-rw-r--r--libjava/classpath/java/awt/dnd/DragGestureRecognizer.java191
-rw-r--r--libjava/classpath/java/awt/dnd/DragSource.java326
-rw-r--r--libjava/classpath/java/awt/dnd/DragSourceAdapter.java126
-rw-r--r--libjava/classpath/java/awt/dnd/DragSourceContext.java383
-rw-r--r--libjava/classpath/java/awt/dnd/DragSourceDragEvent.java102
-rw-r--r--libjava/classpath/java/awt/dnd/DragSourceDropEvent.java89
-rw-r--r--libjava/classpath/java/awt/dnd/DragSourceEvent.java93
-rw-r--r--libjava/classpath/java/awt/dnd/DragSourceListener.java97
-rw-r--r--libjava/classpath/java/awt/dnd/DragSourceMotionListener.java64
-rw-r--r--libjava/classpath/java/awt/dnd/DropTarget.java438
-rw-r--r--libjava/classpath/java/awt/dnd/DropTargetAdapter.java100
-rw-r--r--libjava/classpath/java/awt/dnd/DropTargetContext.java197
-rw-r--r--libjava/classpath/java/awt/dnd/DropTargetDragEvent.java152
-rw-r--r--libjava/classpath/java/awt/dnd/DropTargetDropEvent.java170
-rw-r--r--libjava/classpath/java/awt/dnd/DropTargetEvent.java62
-rw-r--r--libjava/classpath/java/awt/dnd/DropTargetListener.java89
-rw-r--r--libjava/classpath/java/awt/dnd/InvalidDnDOperationException.java74
-rw-r--r--libjava/classpath/java/awt/dnd/MouseDragGestureRecognizer.java131
-rw-r--r--libjava/classpath/java/awt/dnd/package.html46
-rw-r--r--libjava/classpath/java/awt/dnd/peer/DragSourceContextPeer.java57
-rw-r--r--libjava/classpath/java/awt/dnd/peer/DropTargetContextPeer.java68
-rw-r--r--libjava/classpath/java/awt/dnd/peer/DropTargetPeer.java48
-rw-r--r--libjava/classpath/java/awt/dnd/peer/package.html46
-rw-r--r--libjava/classpath/java/awt/doc-files/capjoin.pngbin0 -> 5325 bytes
-rw-r--r--libjava/classpath/java/awt/event/AWTEventListener.java65
-rw-r--r--libjava/classpath/java/awt/event/AWTEventListenerProxy.java95
-rw-r--r--libjava/classpath/java/awt/event/ActionEvent.java228
-rw-r--r--libjava/classpath/java/awt/event/ActionListener.java59
-rw-r--r--libjava/classpath/java/awt/event/AdjustmentEvent.java222
-rw-r--r--libjava/classpath/java/awt/event/AdjustmentListener.java58
-rw-r--r--libjava/classpath/java/awt/event/ComponentAdapter.java97
-rw-r--r--libjava/classpath/java/awt/event/ComponentEvent.java142
-rw-r--r--libjava/classpath/java/awt/event/ComponentListener.java84
-rw-r--r--libjava/classpath/java/awt/event/ContainerAdapter.java79
-rw-r--r--libjava/classpath/java/awt/event/ContainerEvent.java135
-rw-r--r--libjava/classpath/java/awt/event/ContainerListener.java70
-rw-r--r--libjava/classpath/java/awt/event/FocusAdapter.java79
-rw-r--r--libjava/classpath/java/awt/event/FocusEvent.java181
-rw-r--r--libjava/classpath/java/awt/event/FocusListener.java69
-rw-r--r--libjava/classpath/java/awt/event/HierarchyBoundsAdapter.java78
-rw-r--r--libjava/classpath/java/awt/event/HierarchyBoundsListener.java70
-rw-r--r--libjava/classpath/java/awt/event/HierarchyEvent.java255
-rw-r--r--libjava/classpath/java/awt/event/HierarchyListener.java62
-rw-r--r--libjava/classpath/java/awt/event/InputEvent.java399
-rw-r--r--libjava/classpath/java/awt/event/InputMethodEvent.java305
-rw-r--r--libjava/classpath/java/awt/event/InputMethodListener.java70
-rw-r--r--libjava/classpath/java/awt/event/InvocationEvent.java258
-rw-r--r--libjava/classpath/java/awt/event/ItemEvent.java155
-rw-r--r--libjava/classpath/java/awt/event/ItemListener.java62
-rw-r--r--libjava/classpath/java/awt/event/KeyAdapter.java88
-rw-r--r--libjava/classpath/java/awt/event/KeyEvent.java1762
-rw-r--r--libjava/classpath/java/awt/event/KeyListener.java77
-rw-r--r--libjava/classpath/java/awt/event/MouseAdapter.java106
-rw-r--r--libjava/classpath/java/awt/event/MouseEvent.java502
-rw-r--r--libjava/classpath/java/awt/event/MouseListener.java94
-rw-r--r--libjava/classpath/java/awt/event/MouseMotionAdapter.java79
-rw-r--r--libjava/classpath/java/awt/event/MouseMotionListener.java72
-rw-r--r--libjava/classpath/java/awt/event/MouseWheelEvent.java232
-rw-r--r--libjava/classpath/java/awt/event/MouseWheelListener.java60
-rw-r--r--libjava/classpath/java/awt/event/PaintEvent.java127
-rw-r--r--libjava/classpath/java/awt/event/TextEvent.java93
-rw-r--r--libjava/classpath/java/awt/event/TextListener.java60
-rw-r--r--libjava/classpath/java/awt/event/WindowAdapter.java156
-rw-r--r--libjava/classpath/java/awt/event/WindowEvent.java314
-rw-r--r--libjava/classpath/java/awt/event/WindowFocusListener.java68
-rw-r--r--libjava/classpath/java/awt/event/WindowListener.java109
-rw-r--r--libjava/classpath/java/awt/event/WindowStateListener.java62
-rw-r--r--libjava/classpath/java/awt/event/package.html46
-rw-r--r--libjava/classpath/java/awt/font/FontRenderContext.java137
-rw-r--r--libjava/classpath/java/awt/font/GlyphJustificationInfo.java77
-rw-r--r--libjava/classpath/java/awt/font/GlyphMetrics.java138
-rw-r--r--libjava/classpath/java/awt/font/GlyphVector.java174
-rw-r--r--libjava/classpath/java/awt/font/GraphicAttribute.java137
-rw-r--r--libjava/classpath/java/awt/font/ImageGraphicAttribute.java187
-rw-r--r--libjava/classpath/java/awt/font/LineBreakMeasurer.java148
-rw-r--r--libjava/classpath/java/awt/font/LineMetrics.java67
-rw-r--r--libjava/classpath/java/awt/font/MultipleMaster.java61
-rw-r--r--libjava/classpath/java/awt/font/NumericShaper.java425
-rw-r--r--libjava/classpath/java/awt/font/OpenType.java111
-rw-r--r--libjava/classpath/java/awt/font/ShapeGraphicAttribute.java185
-rw-r--r--libjava/classpath/java/awt/font/TextAttribute.java309
-rw-r--r--libjava/classpath/java/awt/font/TextHitInfo.java128
-rw-r--r--libjava/classpath/java/awt/font/TextLayout.java1420
-rw-r--r--libjava/classpath/java/awt/font/TextMeasurer.java190
-rw-r--r--libjava/classpath/java/awt/font/TransformAttribute.java100
-rw-r--r--libjava/classpath/java/awt/font/package.html46
-rw-r--r--libjava/classpath/java/awt/geom/AffineTransform.java1489
-rw-r--r--libjava/classpath/java/awt/geom/Arc2D.java1413
-rw-r--r--libjava/classpath/java/awt/geom/Area.java3312
-rw-r--r--libjava/classpath/java/awt/geom/CubicCurve2D.java1724
-rw-r--r--libjava/classpath/java/awt/geom/Dimension2D.java118
-rw-r--r--libjava/classpath/java/awt/geom/Ellipse2D.java413
-rw-r--r--libjava/classpath/java/awt/geom/FlatteningPathIterator.java579
-rw-r--r--libjava/classpath/java/awt/geom/GeneralPath.java992
-rw-r--r--libjava/classpath/java/awt/geom/IllegalPathStateException.java71
-rw-r--r--libjava/classpath/java/awt/geom/Line2D.java1182
-rw-r--r--libjava/classpath/java/awt/geom/NoninvertibleTransformException.java65
-rw-r--r--libjava/classpath/java/awt/geom/PathIterator.java189
-rw-r--r--libjava/classpath/java/awt/geom/Point2D.java396
-rw-r--r--libjava/classpath/java/awt/geom/QuadCurve2D.java1467
-rw-r--r--libjava/classpath/java/awt/geom/Rectangle2D.java992
-rw-r--r--libjava/classpath/java/awt/geom/RectangularShape.java382
-rw-r--r--libjava/classpath/java/awt/geom/RoundRectangle2D.java584
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/Area-1.pngbin0 -> 21447 bytes
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-1.pngbin0 -> 6280 bytes
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-2.pngbin0 -> 5791 bytes
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-3.pngbin0 -> 13168 bytes
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-4.pngbin0 -> 7839 bytes
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-5.pngbin0 -> 5112 bytes
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/Ellipse-1.pngbin0 -> 19426 bytes
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/FlatteningPathIterator-1.html481
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/GeneralPath-1.pngbin0 -> 13111 bytes
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-1.pngbin0 -> 6363 bytes
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-2.pngbin0 -> 5872 bytes
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-3.pngbin0 -> 12334 bytes
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-4.pngbin0 -> 7797 bytes
-rw-r--r--libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-5.pngbin0 -> 4757 bytes
-rw-r--r--libjava/classpath/java/awt/geom/package.html46
-rw-r--r--libjava/classpath/java/awt/im/InputContext.java438
-rw-r--r--libjava/classpath/java/awt/im/InputMethodHighlight.java189
-rw-r--r--libjava/classpath/java/awt/im/InputMethodRequests.java155
-rw-r--r--libjava/classpath/java/awt/im/InputSubset.java129
-rw-r--r--libjava/classpath/java/awt/im/package.html46
-rw-r--r--libjava/classpath/java/awt/im/spi/InputMethod.java244
-rw-r--r--libjava/classpath/java/awt/im/spi/InputMethodContext.java126
-rw-r--r--libjava/classpath/java/awt/im/spi/InputMethodDescriptor.java113
-rw-r--r--libjava/classpath/java/awt/im/spi/package.html46
-rw-r--r--libjava/classpath/java/awt/image/AffineTransformOp.java608
-rw-r--r--libjava/classpath/java/awt/image/AreaAveragingScaleFilter.java268
-rw-r--r--libjava/classpath/java/awt/image/BandCombineOp.java218
-rw-r--r--libjava/classpath/java/awt/image/BandedSampleModel.java759
-rw-r--r--libjava/classpath/java/awt/image/BufferStrategy.java124
-rw-r--r--libjava/classpath/java/awt/image/BufferedImage.java839
-rw-r--r--libjava/classpath/java/awt/image/BufferedImageFilter.java110
-rw-r--r--libjava/classpath/java/awt/image/BufferedImageOp.java107
-rw-r--r--libjava/classpath/java/awt/image/ByteLookupTable.java175
-rw-r--r--libjava/classpath/java/awt/image/ColorConvertOp.java537
-rw-r--r--libjava/classpath/java/awt/image/ColorModel.java794
-rw-r--r--libjava/classpath/java/awt/image/ComponentColorModel.java408
-rw-r--r--libjava/classpath/java/awt/image/ComponentSampleModel.java755
-rw-r--r--libjava/classpath/java/awt/image/ConvolveOp.java380
-rw-r--r--libjava/classpath/java/awt/image/CropImageFilter.java184
-rw-r--r--libjava/classpath/java/awt/image/DataBuffer.java437
-rw-r--r--libjava/classpath/java/awt/image/DataBufferByte.java245
-rw-r--r--libjava/classpath/java/awt/image/DataBufferDouble.java288
-rw-r--r--libjava/classpath/java/awt/image/DataBufferFloat.java286
-rw-r--r--libjava/classpath/java/awt/image/DataBufferInt.java244
-rw-r--r--libjava/classpath/java/awt/image/DataBufferShort.java245
-rw-r--r--libjava/classpath/java/awt/image/DataBufferUShort.java246
-rw-r--r--libjava/classpath/java/awt/image/DirectColorModel.java435
-rw-r--r--libjava/classpath/java/awt/image/FilteredImageSource.java124
-rw-r--r--libjava/classpath/java/awt/image/ImageConsumer.java216
-rw-r--r--libjava/classpath/java/awt/image/ImageFilter.java226
-rw-r--r--libjava/classpath/java/awt/image/ImageObserver.java129
-rw-r--r--libjava/classpath/java/awt/image/ImageProducer.java84
-rw-r--r--libjava/classpath/java/awt/image/ImagingOpException.java66
-rw-r--r--libjava/classpath/java/awt/image/IndexColorModel.java736
-rw-r--r--libjava/classpath/java/awt/image/Kernel.java171
-rw-r--r--libjava/classpath/java/awt/image/LookupOp.java307
-rw-r--r--libjava/classpath/java/awt/image/LookupTable.java109
-rw-r--r--libjava/classpath/java/awt/image/MemoryImageSource.java429
-rw-r--r--libjava/classpath/java/awt/image/MultiPixelPackedSampleModel.java603
-rw-r--r--libjava/classpath/java/awt/image/PackedColorModel.java188
-rw-r--r--libjava/classpath/java/awt/image/PixelGrabber.java631
-rw-r--r--libjava/classpath/java/awt/image/PixelInterleavedSampleModel.java123
-rw-r--r--libjava/classpath/java/awt/image/RGBImageFilter.java265
-rw-r--r--libjava/classpath/java/awt/image/Raster.java973
-rw-r--r--libjava/classpath/java/awt/image/RasterFormatException.java65
-rw-r--r--libjava/classpath/java/awt/image/RasterOp.java104
-rw-r--r--libjava/classpath/java/awt/image/RenderedImage.java70
-rw-r--r--libjava/classpath/java/awt/image/ReplicateScaleFilter.java257
-rw-r--r--libjava/classpath/java/awt/image/RescaleOp.java385
-rw-r--r--libjava/classpath/java/awt/image/SampleModel.java974
-rw-r--r--libjava/classpath/java/awt/image/ShortLookupTable.java177
-rw-r--r--libjava/classpath/java/awt/image/SinglePixelPackedSampleModel.java586
-rw-r--r--libjava/classpath/java/awt/image/TileObserver.java47
-rw-r--r--libjava/classpath/java/awt/image/VolatileImage.java253
-rw-r--r--libjava/classpath/java/awt/image/WritableRaster.java448
-rw-r--r--libjava/classpath/java/awt/image/WritableRenderedImage.java56
-rw-r--r--libjava/classpath/java/awt/image/package.html46
-rw-r--r--libjava/classpath/java/awt/image/renderable/ContextualRenderedImageFactory.java56
-rw-r--r--libjava/classpath/java/awt/image/renderable/ParameterBlock.java308
-rw-r--r--libjava/classpath/java/awt/image/renderable/RenderContext.java141
-rw-r--r--libjava/classpath/java/awt/image/renderable/RenderableImage.java61
-rw-r--r--libjava/classpath/java/awt/image/renderable/RenderableImageOp.java157
-rw-r--r--libjava/classpath/java/awt/image/renderable/RenderableImageProducer.java166
-rw-r--r--libjava/classpath/java/awt/image/renderable/RenderedImageFactory.java47
-rw-r--r--libjava/classpath/java/awt/image/renderable/package.html46
-rw-r--r--libjava/classpath/java/awt/package.html46
-rw-r--r--libjava/classpath/java/awt/peer/ButtonPeer.java45
-rw-r--r--libjava/classpath/java/awt/peer/CanvasPeer.java44
-rw-r--r--libjava/classpath/java/awt/peer/CheckboxMenuItemPeer.java45
-rw-r--r--libjava/classpath/java/awt/peer/CheckboxPeer.java51
-rw-r--r--libjava/classpath/java/awt/peer/ChoicePeer.java53
-rw-r--r--libjava/classpath/java/awt/peer/ComponentPeer.java532
-rw-r--r--libjava/classpath/java/awt/peer/ContainerPeer.java83
-rw-r--r--libjava/classpath/java/awt/peer/DesktopPeer.java64
-rw-r--r--libjava/classpath/java/awt/peer/DialogPeer.java47
-rw-r--r--libjava/classpath/java/awt/peer/FileDialogPeer.java51
-rw-r--r--libjava/classpath/java/awt/peer/FontPeer.java44
-rw-r--r--libjava/classpath/java/awt/peer/FramePeer.java77
-rw-r--r--libjava/classpath/java/awt/peer/LabelPeer.java45
-rw-r--r--libjava/classpath/java/awt/peer/LightweightPeer.java44
-rw-r--r--libjava/classpath/java/awt/peer/ListPeer.java60
-rw-r--r--libjava/classpath/java/awt/peer/MenuBarPeer.java48
-rw-r--r--libjava/classpath/java/awt/peer/MenuComponentPeer.java54
-rw-r--r--libjava/classpath/java/awt/peer/MenuItemPeer.java47
-rw-r--r--libjava/classpath/java/awt/peer/MenuPeer.java48
-rw-r--r--libjava/classpath/java/awt/peer/MouseInfoPeer.java61
-rw-r--r--libjava/classpath/java/awt/peer/PanelPeer.java44
-rw-r--r--libjava/classpath/java/awt/peer/PopupMenuPeer.java52
-rw-r--r--libjava/classpath/java/awt/peer/RobotPeer.java55
-rw-r--r--libjava/classpath/java/awt/peer/ScrollPanePeer.java51
-rw-r--r--libjava/classpath/java/awt/peer/ScrollbarPeer.java46
-rw-r--r--libjava/classpath/java/awt/peer/TextAreaPeer.java53
-rw-r--r--libjava/classpath/java/awt/peer/TextComponentPeer.java65
-rw-r--r--libjava/classpath/java/awt/peer/TextFieldPeer.java51
-rw-r--r--libjava/classpath/java/awt/peer/WindowPeer.java69
-rw-r--r--libjava/classpath/java/awt/peer/package.html46
-rw-r--r--libjava/classpath/java/awt/print/Book.java159
-rw-r--r--libjava/classpath/java/awt/print/NoPrinterJob.java124
-rw-r--r--libjava/classpath/java/awt/print/PageFormat.java233
-rw-r--r--libjava/classpath/java/awt/print/Pageable.java90
-rw-r--r--libjava/classpath/java/awt/print/Paper.java197
-rw-r--r--libjava/classpath/java/awt/print/Printable.java80
-rw-r--r--libjava/classpath/java/awt/print/PrinterAbortException.java71
-rw-r--r--libjava/classpath/java/awt/print/PrinterException.java71
-rw-r--r--libjava/classpath/java/awt/print/PrinterGraphics.java58
-rw-r--r--libjava/classpath/java/awt/print/PrinterIOException.java97
-rw-r--r--libjava/classpath/java/awt/print/PrinterJob.java300
-rw-r--r--libjava/classpath/java/awt/print/package.html46
363 files changed, 110260 insertions, 0 deletions
diff --git a/libjava/classpath/java/awt/AWTError.java b/libjava/classpath/java/awt/AWTError.java
new file mode 100644
index 000000000..80356eee4
--- /dev/null
+++ b/libjava/classpath/java/awt/AWTError.java
@@ -0,0 +1,64 @@
+/* AWTError.java -- A serious AWT error occurred.
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This error is thrown when a critical Abstract Window Toolkit (AWT) error
+ * occurs.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @status updated to 1.4
+ */
+public class AWTError extends Error
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -1819846354050686206L;
+
+ /**
+ * Create a new instance with the specified descriptive error message.
+ *
+ * @param message the descriptive error message
+ */
+ public AWTError(String message)
+ {
+ super(message);
+ }
+} // class AWTError
diff --git a/libjava/classpath/java/awt/AWTEvent.java b/libjava/classpath/java/awt/AWTEvent.java
new file mode 100644
index 000000000..c4f772827
--- /dev/null
+++ b/libjava/classpath/java/awt/AWTEvent.java
@@ -0,0 +1,399 @@
+
+/* AWTEvent.java -- the root event in AWT
+ Copyright (C) 1999, 2000, 2002, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.AdjustmentEvent;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ContainerEvent;
+import java.awt.event.FocusEvent;
+import java.awt.event.InputMethodEvent;
+import java.awt.event.InvocationEvent;
+import java.awt.event.ItemEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.PaintEvent;
+import java.awt.event.TextEvent;
+import java.awt.event.WindowEvent;
+import java.util.EventObject;
+
+/**
+ * AWTEvent is the root event class for all AWT events in the JDK 1.1 event
+ * model. It supersedes the Event class from JDK 1.0. Subclasses outside of
+ * the java.awt package should have IDs greater than RESERVED_ID_MAX.
+ *
+ * <p>Event masks defined here are used by components in
+ * <code>enableEvents</code> to select event types not selected by registered
+ * listeners. Event masks are appropriately set when registering on
+ * components.
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class AWTEvent extends EventObject
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -1825314779160409405L;
+
+ /**
+ * The ID of the event.
+ *
+ * @see #getID()
+ * @see #AWTEvent(Object, int)
+ * @serial the identifier number of this event
+ */
+ protected int id;
+
+ /**
+ * Indicates if the event has been consumed. False mean it is passed to
+ * the peer, true means it has already been processed. Semantic events
+ * generated by low-level events always have the value true.
+ *
+ * @see #consume()
+ * @see #isConsumed()
+ * @serial whether the event has been consumed
+ */
+ protected boolean consumed;
+
+ /**
+ * Used for implementing a simple linked list in EventQueue.
+ */
+ transient AWTEvent queueNext;
+
+ /**
+ * Who knows? It's in the serial version.
+ *
+ * @serial No idea what this is for.
+ */
+ byte[] bdata;
+
+ /**
+ * Indicates if this event is dispatched by the KeyboardFocusManager.
+ */
+ boolean isFocusManagerEvent = false;
+
+ /** Mask for selecting component events. */
+ public static final long COMPONENT_EVENT_MASK = 0x00001;
+
+ /** Mask for selecting container events. */
+ public static final long CONTAINER_EVENT_MASK = 0x00002;
+
+ /** Mask for selecting component focus events. */
+ public static final long FOCUS_EVENT_MASK = 0x00004;
+
+ /** Mask for selecting keyboard events. */
+ public static final long KEY_EVENT_MASK = 0x00008;
+
+ /** Mask for mouse button events. */
+ public static final long MOUSE_EVENT_MASK = 0x00010;
+
+ /** Mask for mouse motion events. */
+ public static final long MOUSE_MOTION_EVENT_MASK = 0x00020;
+
+ /** Mask for window events. */
+ public static final long WINDOW_EVENT_MASK = 0x00040;
+
+ /** Mask for action events. */
+ public static final long ACTION_EVENT_MASK = 0x00080;
+
+ /** Mask for adjustment events. */
+ public static final long ADJUSTMENT_EVENT_MASK = 0x00100;
+
+ /** Mask for item events. */
+ public static final long ITEM_EVENT_MASK = 0x00200;
+
+ /** Mask for text events. */
+ public static final long TEXT_EVENT_MASK = 0x00400;
+
+ /**
+ * Mask for input method events.
+ * @since 1.3
+ */
+ public static final long INPUT_METHOD_EVENT_MASK = 0x00800;
+
+ /**
+ * Mask if input methods are enabled. Package visible only.
+ */
+ static final long INPUT_ENABLED_EVENT_MASK = 0x01000;
+
+ /**
+ * Mask for paint events.
+ * @since 1.3
+ */
+ public static final long PAINT_EVENT_MASK = 0x02000;
+
+ /**
+ * Mask for invocation events.
+ * @since 1.3
+ */
+ public static final long INVOCATION_EVENT_MASK = 0x04000;
+
+ /**
+ * Mask for hierarchy events.
+ * @since 1.3
+ */
+ public static final long HIERARCHY_EVENT_MASK = 0x08000;
+
+ /**
+ * Mask for hierarchy bounds events.
+ * @since 1.3
+ */
+ public static final long HIERARCHY_BOUNDS_EVENT_MASK = 0x10000;
+
+ /**
+ * Mask for mouse wheel events.
+ * @since 1.4
+ */
+ public static final long MOUSE_WHEEL_EVENT_MASK = 0x20000;
+
+ /**
+ * Mask for window state events.
+ * @since 1.4
+ */
+ public static final long WINDOW_STATE_EVENT_MASK = 0x40000;
+
+ /**
+ * Mask for window focus events.
+ * @since 1.4
+ */
+ public static final long WINDOW_FOCUS_EVENT_MASK = 0x80000;
+
+ /**
+ * This is the highest number for event ids that are reserved for use by
+ * the AWT system itself. Subclasses outside of java.awt should use higher
+ * ids.
+ */
+ public static final int RESERVED_ID_MAX = 1999;
+
+
+ /**
+ * Initializes a new AWTEvent from the old Java 1.0 event object.
+ *
+ * @param event the old-style event
+ * @throws NullPointerException if event is null
+ */
+ public AWTEvent(Event event)
+ {
+ this(event.target, event.id);
+ consumed = event.consumed;
+ }
+
+ /**
+ * Create an event on the specified source object and id.
+ *
+ * @param source the object that caused the event
+ * @param id the event id
+ * @throws IllegalArgumentException if source is null
+ */
+ public AWTEvent(Object source, int id)
+ {
+ super(source);
+ this.id = id;
+ }
+
+ /**
+ * Retarget the event, such as converting a heavyweight component to a
+ * lightweight child of the original. This is not for general use, but
+ * is for event targeting systems like KeyboardFocusManager.
+ *
+ * @param source the new source
+ */
+ public void setSource(Object source)
+ {
+ this.source = source;
+ }
+
+ /**
+ * Returns the event type id.
+ *
+ * @return the id number of this event
+ */
+ public int getID()
+ {
+ return id;
+ }
+
+ /**
+ * Create a string that represents this event in the format
+ * <code>classname[eventstring] on sourcecomponentname</code>.
+ *
+ * @return a string representing this event
+ */
+ public String toString ()
+ {
+ String src;
+ if (source instanceof Component)
+ src = ((Component) source).getName();
+ else if (source instanceof MenuComponent)
+ src = ((MenuComponent) source).getName();
+ else if (source != null)
+ src = source.toString();
+ else
+ src = "null";
+ String string = getClass ().getName () + "[" + paramString () + "] on "
+ + src;
+ return string;
+ }
+
+ /**
+ * Returns a string representation of the state of this event. It may be
+ * empty, but must not be null; it is implementation defined.
+ *
+ * @return a string representation of this event
+ */
+ public String paramString()
+ {
+ return "";
+ }
+
+ /**
+ * Consumes this event so that it will not be processed in the default
+ * manner.
+ */
+ protected void consume()
+ {
+ consumed = true;
+ }
+
+ /**
+ * Tests whether not not this event has been consumed. A consumed event
+ * is not processed in the default manner.
+ *
+ * @return true if this event has been consumed
+ */
+ protected boolean isConsumed()
+ {
+ return consumed;
+ }
+
+ /**
+ * Converts an event id to the appropriate event mask.
+ *
+ * @param id the event id
+ *
+ * @return the event mask for the specified id
+ */
+ static long eventIdToMask(int id)
+ {
+ long mask = 0;
+ switch (id)
+ {
+ case ActionEvent.ACTION_PERFORMED:
+ mask = ACTION_EVENT_MASK;
+ break;
+ case AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED:
+ mask = ADJUSTMENT_EVENT_MASK;
+ break;
+ case ComponentEvent.COMPONENT_MOVED:
+ case ComponentEvent.COMPONENT_RESIZED:
+ case ComponentEvent.COMPONENT_SHOWN:
+ case ComponentEvent.COMPONENT_HIDDEN:
+ mask = COMPONENT_EVENT_MASK;
+ break;
+ case ContainerEvent.COMPONENT_ADDED:
+ case ContainerEvent.COMPONENT_REMOVED:
+ mask = CONTAINER_EVENT_MASK;
+ break;
+ case FocusEvent.FOCUS_GAINED:
+ case FocusEvent.FOCUS_LOST:
+ mask = FOCUS_EVENT_MASK;
+ break;
+ case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED:
+ case InputMethodEvent.CARET_POSITION_CHANGED:
+ mask = INPUT_METHOD_EVENT_MASK;
+ break;
+ case InvocationEvent.INVOCATION_DEFAULT:
+ mask = INVOCATION_EVENT_MASK;
+ break;
+ case ItemEvent.ITEM_STATE_CHANGED:
+ mask = ITEM_EVENT_MASK;
+ break;
+ case KeyEvent.KEY_TYPED:
+ case KeyEvent.KEY_PRESSED:
+ case KeyEvent.KEY_RELEASED:
+ mask = KEY_EVENT_MASK;
+ break;
+ case MouseEvent.MOUSE_CLICKED:
+ case MouseEvent.MOUSE_PRESSED:
+ case MouseEvent.MOUSE_RELEASED:
+ mask = MOUSE_EVENT_MASK;
+ break;
+ case MouseEvent.MOUSE_MOVED:
+ case MouseEvent.MOUSE_ENTERED:
+ case MouseEvent.MOUSE_EXITED:
+ case MouseEvent.MOUSE_DRAGGED:
+ mask = MOUSE_MOTION_EVENT_MASK;
+ break;
+ case MouseEvent.MOUSE_WHEEL:
+ mask = MOUSE_WHEEL_EVENT_MASK;
+ break;
+ case PaintEvent.PAINT:
+ case PaintEvent.UPDATE:
+ mask = PAINT_EVENT_MASK;
+ break;
+ case TextEvent.TEXT_VALUE_CHANGED:
+ mask = TEXT_EVENT_MASK;
+ break;
+ case WindowEvent.WINDOW_OPENED:
+ case WindowEvent.WINDOW_CLOSING:
+ case WindowEvent.WINDOW_CLOSED:
+ case WindowEvent.WINDOW_ICONIFIED:
+ case WindowEvent.WINDOW_DEICONIFIED:
+ case WindowEvent.WINDOW_ACTIVATED:
+ case WindowEvent.WINDOW_DEACTIVATED:
+ mask = WINDOW_EVENT_MASK;
+ break;
+ case WindowEvent.WINDOW_GAINED_FOCUS:
+ case WindowEvent.WINDOW_LOST_FOCUS:
+ mask = WINDOW_FOCUS_EVENT_MASK;
+ break;
+ case WindowEvent.WINDOW_STATE_CHANGED:
+ mask = WINDOW_STATE_EVENT_MASK;
+ break;
+ default:
+ mask = 0;
+ }
+ return mask;
+ }
+} // class AWTEvent
diff --git a/libjava/classpath/java/awt/AWTEventMulticaster.java b/libjava/classpath/java/awt/AWTEventMulticaster.java
new file mode 100644
index 000000000..722dc752d
--- /dev/null
+++ b/libjava/classpath/java/awt/AWTEventMulticaster.java
@@ -0,0 +1,1210 @@
+/* AWTEventMulticaster.java -- allows multicast chaining of listeners
+ Copyright (C) 1999, 2000, 2002 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.AdjustmentEvent;
+import java.awt.event.AdjustmentListener;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+import java.awt.event.ContainerEvent;
+import java.awt.event.ContainerListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.HierarchyBoundsListener;
+import java.awt.event.HierarchyEvent;
+import java.awt.event.HierarchyListener;
+import java.awt.event.InputMethodEvent;
+import java.awt.event.InputMethodListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.event.MouseWheelEvent;
+import java.awt.event.MouseWheelListener;
+import java.awt.event.TextEvent;
+import java.awt.event.TextListener;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowFocusListener;
+import java.awt.event.WindowListener;
+import java.awt.event.WindowStateListener;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.EventListener;
+
+/**
+ * This class is used to implement a chain of event handlers. Dispatching
+ * using this class is thread safe. Here is a quick example of how to
+ * add and delete listeners using this class. For this example, we will
+ * assume are firing <code>AdjustmentEvent</code>'s. However, this
+ * same approach is useful for all events in the <code>java.awt.event</code>
+ * package, and more if this class is subclassed.
+ *
+ * <p><code>
+ * AdjustmentListener al;
+ * public void addAdjustmentListener(AdjustmentListener listener)
+ * {
+ * al = AWTEventMulticaster.add(al, listener);
+ * }
+ * public void removeAdjustmentListener(AdjustmentListener listener)
+ * {
+ * al = AWTEventMulticaster.remove(al, listener);
+ * }
+ * </code>
+ *
+ * <p>When it come time to process an event, simply call <code>al</code>,
+ * assuming it is not <code>null</code>, and all listeners in the chain will
+ * be fired.
+ *
+ * <p>The first time <code>add</code> is called it is passed
+ * <code>null</code> and <code>listener</code> as its arguments. This
+ * starts building the chain. This class returns <code>listener</code>
+ * which becomes the new <code>al</code>. The next time, <code>add</code>
+ * is called with <code>al</code> and <code>listener</code> and the
+ * new listener is then chained to the old.
+ *
+ * @author Bryce McKinlay
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class AWTEventMulticaster
+ implements ComponentListener, ContainerListener, FocusListener, KeyListener,
+ MouseListener, MouseMotionListener, WindowListener,
+ WindowFocusListener, WindowStateListener, ActionListener,
+ ItemListener, AdjustmentListener, TextListener,
+ InputMethodListener, HierarchyListener, HierarchyBoundsListener,
+ MouseWheelListener
+{
+ /**
+ * A variable in the event chain.
+ */
+ protected final EventListener a;
+
+ /**
+ * A variable in the event chain.
+ */
+ protected final EventListener b;
+
+ /**
+ * Initializes a new instance of <code>AWTEventMulticaster</code> with
+ * the specified event listener parameters. The parameters should not be
+ * null, although it is not required to enforce this with a
+ * NullPointerException.
+ *
+ * @param a the "a" listener object
+ * @param b the "b" listener object
+ */
+ protected AWTEventMulticaster(EventListener a, EventListener b)
+ {
+ this.a = a;
+ this.b = b;
+ }
+
+ /**
+ * Removes one instance of the specified listener from this multicaster
+ * chain. This descends recursively if either child is a multicaster, and
+ * returns a multicaster chain with the old listener removed.
+ *
+ * @param oldl the object to remove from this multicaster
+ * @return the resulting multicaster with the specified listener removed
+ */
+ protected EventListener remove(EventListener oldl)
+ {
+ // If oldl is an immediate child, return the other child.
+ if (a == oldl)
+ return b;
+ if (b == oldl)
+ return a;
+ // If a and/or b are Multicaster's, search them recursively.
+ if (a instanceof AWTEventMulticaster)
+ {
+ EventListener newa = ((AWTEventMulticaster) a).remove(oldl);
+ if (newa != a)
+ return new AWTEventMulticaster(newa, b);
+ }
+ if (b instanceof AWTEventMulticaster)
+ {
+ EventListener newb = ((AWTEventMulticaster) b).remove(oldl);
+ if (newb != b)
+ return new AWTEventMulticaster(a, newb);
+ }
+ // oldl was not found.
+ return this;
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void componentResized(ComponentEvent e)
+ {
+ ((ComponentListener) a).componentResized(e);
+ ((ComponentListener) b).componentResized(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void componentMoved(ComponentEvent e)
+ {
+ ((ComponentListener) a).componentMoved(e);
+ ((ComponentListener) b).componentMoved(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void componentShown(ComponentEvent e)
+ {
+ ((ComponentListener) a).componentShown(e);
+ ((ComponentListener) b).componentShown(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void componentHidden(ComponentEvent e)
+ {
+ ((ComponentListener) a).componentHidden(e);
+ ((ComponentListener) b).componentHidden(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void componentAdded(ContainerEvent e)
+ {
+ ((ContainerListener) a).componentAdded(e);
+ ((ContainerListener) b).componentAdded(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void componentRemoved(ContainerEvent e)
+ {
+ ((ContainerListener) a).componentRemoved(e);
+ ((ContainerListener) b).componentRemoved(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void focusGained(FocusEvent e)
+ {
+ ((FocusListener) a).focusGained(e);
+ ((FocusListener) b).focusGained(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void focusLost(FocusEvent e)
+ {
+ ((FocusListener) a).focusLost(e);
+ ((FocusListener) b).focusLost(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void keyTyped(KeyEvent e)
+ {
+ ((KeyListener) a).keyTyped(e);
+ ((KeyListener) b).keyTyped(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void keyPressed(KeyEvent e)
+ {
+ ((KeyListener) a).keyPressed(e);
+ ((KeyListener) b).keyPressed(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void keyReleased(KeyEvent e)
+ {
+ ((KeyListener) a).keyReleased(e);
+ ((KeyListener) b).keyReleased(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void mouseClicked(MouseEvent e)
+ {
+ ((MouseListener) a).mouseClicked(e);
+ ((MouseListener) b).mouseClicked(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void mousePressed(MouseEvent e)
+ {
+ ((MouseListener) a).mousePressed(e);
+ ((MouseListener) b).mousePressed(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void mouseReleased(MouseEvent e)
+ {
+ ((MouseListener) a).mouseReleased(e);
+ ((MouseListener) b).mouseReleased(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void mouseEntered(MouseEvent e)
+ {
+ ((MouseListener) a).mouseEntered(e);
+ ((MouseListener) b).mouseEntered(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void mouseExited(MouseEvent e)
+ {
+ ((MouseListener) a).mouseExited(e);
+ ((MouseListener) b).mouseExited(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void mouseDragged(MouseEvent e)
+ {
+ ((MouseMotionListener) a).mouseDragged(e);
+ ((MouseMotionListener) b).mouseDragged(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void mouseMoved(MouseEvent e)
+ {
+ ((MouseMotionListener) a).mouseMoved(e);
+ ((MouseMotionListener) b).mouseMoved(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void windowOpened(WindowEvent e)
+ {
+ ((WindowListener) a).windowOpened(e);
+ ((WindowListener) b).windowOpened(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void windowClosing(WindowEvent e)
+ {
+ ((WindowListener) a).windowClosing(e);
+ ((WindowListener) b).windowClosing(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void windowClosed(WindowEvent e)
+ {
+ ((WindowListener) a).windowClosed(e);
+ ((WindowListener) b).windowClosed(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void windowIconified(WindowEvent e)
+ {
+ ((WindowListener) a).windowIconified(e);
+ ((WindowListener) b).windowIconified(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void windowDeiconified(WindowEvent e)
+ {
+ ((WindowListener) a).windowDeiconified(e);
+ ((WindowListener) b).windowDeiconified(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void windowActivated(WindowEvent e)
+ {
+ ((WindowListener) a).windowActivated(e);
+ ((WindowListener) b).windowActivated(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void windowDeactivated(WindowEvent e)
+ {
+ ((WindowListener) a).windowDeactivated(e);
+ ((WindowListener) b).windowDeactivated(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ * @since 1.4
+ */
+ public void windowStateChanged(WindowEvent e)
+ {
+ ((WindowStateListener) a).windowStateChanged(e);
+ ((WindowStateListener) b).windowStateChanged(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ * @since 1.4
+ */
+ public void windowGainedFocus(WindowEvent e)
+ {
+ ((WindowFocusListener) a).windowGainedFocus(e);
+ ((WindowFocusListener) b).windowGainedFocus(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ * @since 1.4
+ */
+ public void windowLostFocus(WindowEvent e)
+ {
+ ((WindowFocusListener) a).windowLostFocus(e);
+ ((WindowFocusListener) b).windowLostFocus(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void actionPerformed(ActionEvent e)
+ {
+ ((ActionListener) a).actionPerformed(e);
+ ((ActionListener) b).actionPerformed(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void itemStateChanged(ItemEvent e)
+ {
+ ((ItemListener) a).itemStateChanged(e);
+ ((ItemListener) b).itemStateChanged(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void adjustmentValueChanged(AdjustmentEvent e)
+ {
+ ((AdjustmentListener) a).adjustmentValueChanged(e);
+ ((AdjustmentListener) b).adjustmentValueChanged(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ */
+ public void textValueChanged(TextEvent e)
+ {
+ ((TextListener) a).textValueChanged(e);
+ ((TextListener) b).textValueChanged(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ * @since 1.2
+ */
+ public void inputMethodTextChanged(InputMethodEvent e)
+ {
+ ((InputMethodListener) a).inputMethodTextChanged(e);
+ ((InputMethodListener) b).inputMethodTextChanged(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ * @since 1.2
+ */
+ public void caretPositionChanged(InputMethodEvent e)
+ {
+ ((InputMethodListener) a).caretPositionChanged(e);
+ ((InputMethodListener) b).caretPositionChanged(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ * @since 1.3
+ */
+ public void hierarchyChanged(HierarchyEvent e)
+ {
+ ((HierarchyListener) a).hierarchyChanged(e);
+ ((HierarchyListener) b).hierarchyChanged(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ * @since 1.3
+ */
+ public void ancestorMoved(HierarchyEvent e)
+ {
+ ((HierarchyBoundsListener) a).ancestorMoved(e);
+ ((HierarchyBoundsListener) b).ancestorMoved(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ * @since 1.3
+ */
+ public void ancestorResized(HierarchyEvent e)
+ {
+ ((HierarchyBoundsListener) a).ancestorResized(e);
+ ((HierarchyBoundsListener) b).ancestorResized(e);
+ }
+
+ /**
+ * Handles this event by dispatching it to the "a" and "b" listener
+ * instances.
+ *
+ * @param e the event to handle
+ * @since 1.4
+ */
+ public void mouseWheelMoved(MouseWheelEvent e)
+ {
+ ((MouseWheelListener) a).mouseWheelMoved(e);
+ ((MouseWheelListener) b).mouseWheelMoved(e);
+ }
+
+ /**
+ * Chain <code>ComponentListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ */
+ public static ComponentListener add(ComponentListener a, ComponentListener b)
+ {
+ return (ComponentListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>ContainerListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ */
+ public static ContainerListener add(ContainerListener a, ContainerListener b)
+ {
+ return (ContainerListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>FocusListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ */
+ public static FocusListener add(FocusListener a, FocusListener b)
+ {
+ return (FocusListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>KeyListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ */
+ public static KeyListener add(KeyListener a, KeyListener b)
+ {
+ return (KeyListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>MouseListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ */
+ public static MouseListener add(MouseListener a, MouseListener b)
+ {
+ return (MouseListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>MouseMotionListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ */
+ public static MouseMotionListener add(MouseMotionListener a,
+ MouseMotionListener b)
+ {
+ return (MouseMotionListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>WindowListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ */
+ public static WindowListener add(WindowListener a, WindowListener b)
+ {
+ return (WindowListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>WindowStateListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ * @since 1.4
+ */
+ public static WindowStateListener add(WindowStateListener a,
+ WindowStateListener b)
+ {
+ return (WindowStateListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>WindowFocusListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ * @since 1.4
+ */
+ public static WindowFocusListener add(WindowFocusListener a,
+ WindowFocusListener b)
+ {
+ return (WindowFocusListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>ActionListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ */
+ public static ActionListener add(ActionListener a, ActionListener b)
+ {
+ return (ActionListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>ItemListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ */
+ public static ItemListener add(ItemListener a, ItemListener b)
+ {
+ return (ItemListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>AdjustmentListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ */
+ public static AdjustmentListener add(AdjustmentListener a,
+ AdjustmentListener b)
+ {
+ return (AdjustmentListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>AdjustmentListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ */
+ public static TextListener add(TextListener a, TextListener b)
+ {
+ return (TextListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>InputMethodListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ * @since 1.2
+ */
+ public static InputMethodListener add(InputMethodListener a,
+ InputMethodListener b)
+ {
+ return (InputMethodListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>HierarchyListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ * @since 1.3
+ */
+ public static HierarchyListener add(HierarchyListener a, HierarchyListener b)
+ {
+ return (HierarchyListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>HierarchyBoundsListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ * @since 1.3
+ */
+ public static HierarchyBoundsListener add(HierarchyBoundsListener a,
+ HierarchyBoundsListener b)
+ {
+ return (HierarchyBoundsListener) addInternal(a, b);
+ }
+
+ /**
+ * Chain <code>MouseWheelListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ * @since 1.4
+ */
+ public static MouseWheelListener add(MouseWheelListener a,
+ MouseWheelListener b)
+ {
+ return (MouseWheelListener) addInternal(a, b);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ */
+ public static ComponentListener remove(ComponentListener l,
+ ComponentListener oldl)
+ {
+ return (ComponentListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ */
+ public static ContainerListener remove(ContainerListener l,
+ ContainerListener oldl)
+ {
+ return (ContainerListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ */
+ public static FocusListener remove(FocusListener l, FocusListener oldl)
+ {
+ return (FocusListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ */
+ public static KeyListener remove(KeyListener l, KeyListener oldl)
+ {
+ return (KeyListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ */
+ public static MouseListener remove(MouseListener l, MouseListener oldl)
+ {
+ return (MouseListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ */
+ public static MouseMotionListener remove(MouseMotionListener l,
+ MouseMotionListener oldl)
+ {
+ return (MouseMotionListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ */
+ public static WindowListener remove(WindowListener l, WindowListener oldl)
+ {
+ return (WindowListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ * @since 1.4
+ */
+ public static WindowStateListener remove(WindowStateListener l,
+ WindowStateListener oldl)
+ {
+ return (WindowStateListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ * @since 1.4
+ */
+ public static WindowFocusListener remove(WindowFocusListener l,
+ WindowFocusListener oldl)
+ {
+ return (WindowFocusListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ */
+ public static ActionListener remove(ActionListener l, ActionListener oldl)
+ {
+ return (ActionListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ */
+ public static ItemListener remove(ItemListener l, ItemListener oldl)
+ {
+ return (ItemListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ */
+ public static AdjustmentListener remove(AdjustmentListener l,
+ AdjustmentListener oldl)
+ {
+ return (AdjustmentListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ */
+ public static TextListener remove(TextListener l, TextListener oldl)
+ {
+ return (TextListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ * @since 1.2
+ */
+ public static InputMethodListener remove(InputMethodListener l,
+ InputMethodListener oldl)
+ {
+ return (InputMethodListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ * @since 1.3
+ */
+ public static HierarchyListener remove(HierarchyListener l,
+ HierarchyListener oldl)
+ {
+ return (HierarchyListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ * @since 1.3
+ */
+ public static HierarchyBoundsListener remove(HierarchyBoundsListener l,
+ HierarchyBoundsListener oldl)
+ {
+ return (HierarchyBoundsListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ * @since 1.4
+ */
+ public static MouseWheelListener remove(MouseWheelListener l,
+ MouseWheelListener oldl)
+ {
+ return (MouseWheelListener) removeInternal(l, oldl);
+ }
+
+ /**
+ * Chain <code>EventListener</code> a and b.
+ *
+ * @param a the "a" listener, may be null
+ * @param b the "b" listener, may be null
+ * @return latest entry in the chain
+ */
+ protected static EventListener addInternal(EventListener a, EventListener b)
+ {
+ if (a == null)
+ return b;
+ if (b == null)
+ return a;
+ return new AWTEventMulticaster(a, b);
+ }
+
+ /**
+ * Removes the listener <code>oldl</code> from the listener <code>l</code>.
+ *
+ * @param l the listener chain to reduce
+ * @param oldl the listener to remove
+ * @return the resulting listener chain
+ */
+ protected static EventListener removeInternal(EventListener l,
+ EventListener oldl)
+ {
+ if (l == oldl)
+ return null;
+ if (l instanceof AWTEventMulticaster)
+ return ((AWTEventMulticaster) l).remove(oldl);
+ return l;
+ }
+
+ /**
+ * Saves all Serializable listeners to a serialization stream.
+ *
+ * @param s the stream to save to
+ * @param k a prefix stream put before each serializable listener
+ * @throws IOException if serialization fails
+ */
+ protected void saveInternal(ObjectOutputStream s, String k)
+ throws IOException
+ {
+ // This is not documented by Sun, but I think it is correct.
+ if (a instanceof AWTEventMulticaster)
+ ((AWTEventMulticaster) a).saveInternal(s, k);
+ else if (a instanceof Serializable)
+ {
+ s.writeObject(k);
+ s.writeObject(a);
+ }
+ if (b instanceof AWTEventMulticaster)
+ ((AWTEventMulticaster) b).saveInternal(s, k);
+ else if (b instanceof Serializable)
+ {
+ s.writeObject(k);
+ s.writeObject(b);
+ }
+ }
+
+ /**
+ * Saves a Serializable listener chain to a serialization stream.
+ *
+ * @param s the stream to save to
+ * @param k a prefix stream put before each serializable listener
+ * @param l the listener chain to save
+ * @throws IOException if serialization fails
+ */
+ protected static void save(ObjectOutputStream s, String k, EventListener l)
+ throws IOException
+ {
+ // This is not documented by Sun, but I think it is correct.
+ if (l instanceof AWTEventMulticaster)
+ ((AWTEventMulticaster) l).saveInternal(s, k);
+ else if (l instanceof Serializable)
+ {
+ s.writeObject(k);
+ s.writeObject(l);
+ }
+ }
+
+ /**
+ * Returns an array of all chained listeners of the specified type in the
+ * given chain. A null listener returns an empty array, and a listener
+ * which is not an AWTEventMulticaster returns an array of one element. If
+ * no listeners in the chain are of the specified type, an empty array is
+ * returned.
+ *
+ * @param l the listener chain to convert to an array
+ * @param type the type of listeners to collect
+ * @return an array of the listeners of that type in the chain
+ * @throws ClassCastException if type is not assignable from EventListener
+ * @throws NullPointerException if type is null
+ * @throws IllegalArgumentException if type is Void.TYPE
+ * @since 1.4
+ */
+ public static <T extends EventListener> T[] getListeners(EventListener l,
+ Class<T> type)
+ {
+ ArrayList<EventListener> list = new ArrayList<EventListener>();
+ if (l instanceof AWTEventMulticaster)
+ ((AWTEventMulticaster) l).getListeners(list, type);
+ else if (type.isInstance(l))
+ list.add(l);
+ EventListener[] r = (EventListener[]) Array.newInstance(type, list.size());
+ list.toArray(r);
+ return (T[]) r;
+ }
+
+ /**
+ * Collects all instances of the given type in the chain into the list.
+ *
+ * @param l the list to collect into
+ * @param type the type of listeners to collect
+ * @throws NullPointerException if type is null
+ * @see #getListeners(EventListener, Class)
+ */
+ private void getListeners(ArrayList l, Class type)
+ {
+ if (a instanceof AWTEventMulticaster)
+ ((AWTEventMulticaster) a).getListeners(l, type);
+ else if (type.isInstance(a))
+ l.add(a);
+ if (b instanceof AWTEventMulticaster)
+ ((AWTEventMulticaster) b).getListeners(l, type);
+ else if (type.isInstance(b))
+ l.add(b);
+ }
+} // class AWTEventMulticaster
diff --git a/libjava/classpath/java/awt/AWTException.java b/libjava/classpath/java/awt/AWTException.java
new file mode 100644
index 000000000..2df3dd801
--- /dev/null
+++ b/libjava/classpath/java/awt/AWTException.java
@@ -0,0 +1,64 @@
+/* AWTException.java -- Generic AWT exception
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This is a generic exception that indicates an exception occurred in the
+ * Abstract Window Toolkit (AWT) system.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @status updated to 1.4
+ */
+public class AWTException extends Exception
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -1900414231151323879L;
+
+ /**
+ * Create a new instance with the specified detailed error message.
+ *
+ * @param message the detailed error message
+ */
+ public AWTException(String message)
+ {
+ super(message);
+ }
+} // class AWTException
diff --git a/libjava/classpath/java/awt/AWTKeyStroke.java b/libjava/classpath/java/awt/AWTKeyStroke.java
new file mode 100644
index 000000000..bdccbf0d7
--- /dev/null
+++ b/libjava/classpath/java/awt/AWTKeyStroke.java
@@ -0,0 +1,676 @@
+/* AWTKeyStroke.java -- an immutable key stroke
+ Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+/**
+ * This class mirrors KeyEvents, representing both low-level key presses and
+ * key releases, and high level key typed inputs. However, this class forms
+ * immutable strokes, and can be efficiently reused via the factory methods
+ * for creating them.
+ *
+ * <p>For backwards compatibility with Swing, this supports a way to build
+ * instances of a subclass, using reflection, provided the subclass has a
+ * no-arg constructor (of any accessibility).
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @see #getAWTKeyStroke(char)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public class AWTKeyStroke implements Serializable
+{
+ /**
+ * Compatible with JDK 1.4+.
+ */
+ private static final long serialVersionUID = -6430539691155161871L;
+
+ /** The mask for modifiers. */
+ private static final int MODIFIERS_MASK = 0x3fef;
+
+ /**
+ * The cache of recently created keystrokes. This maps KeyStrokes to
+ * KeyStrokes in a cache which removes the least recently accessed entry,
+ * under the assumption that garbage collection of a new keystroke is
+ * easy when we find the old one that it matches in the cache.
+ */
+ private static final LinkedHashMap<AWTKeyStroke,AWTKeyStroke> cache =
+ new LinkedHashMap<AWTKeyStroke,AWTKeyStroke>(11, 0.75f, true)
+ {
+ /** The largest the keystroke cache can grow. */
+ private static final int MAX_CACHE_SIZE = 2048;
+
+ /** Prune stale entries. */
+ protected boolean removeEldestEntry(Map.Entry<AWTKeyStroke,AWTKeyStroke>
+ eldest)
+ {
+ return size() > MAX_CACHE_SIZE;
+ }
+ };
+
+ /** The most recently generated keystroke, or null. */
+ private static AWTKeyStroke recent;
+
+ /**
+ * The no-arg constructor of a subclass, or null to use AWTKeyStroke. Note
+ * that this will be left accessible, to get around private access; but
+ * it should not be a security risk as it is highly unlikely that creating
+ * protected instances of the subclass via reflection will do much damage.
+ */
+ private static Constructor ctor;
+
+ /**
+ * A table of keyCode names to values. This is package-private to
+ * avoid an accessor method.
+ *
+ * @see #getAWTKeyStroke(String)
+ */
+ static final HashMap<String,Object> vktable = new HashMap<String,Object>();
+ static
+ {
+ // Using reflection saves the hassle of keeping this in sync with KeyEvent,
+ // at the price of an expensive initialization.
+ AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ Field[] fields = KeyEvent.class.getFields();
+ int i = fields.length;
+ try
+ {
+ while (--i >= 0)
+ {
+ Field f = fields[i];
+ String name = f.getName();
+ if (name.startsWith("VK_"))
+ vktable.put(name.substring(3), f.get(null));
+ }
+ }
+ catch (Exception e)
+ {
+ throw (Error) new InternalError().initCause(e);
+ }
+ return null;
+ }
+ });
+ }
+
+ /**
+ * The typed character, or CHAR_UNDEFINED for key presses and releases.
+ *
+ * @serial the keyChar
+ */
+ private char keyChar;
+
+ /**
+ * The virtual key code, or VK_UNDEFINED for key typed. Package visible for
+ * use by Component.
+ *
+ * @serial the keyCode
+ */
+ int keyCode;
+
+ /**
+ * The modifiers in effect. To match Sun, this stores the old style masks
+ * for shift, control, alt, meta, and alt-graph (but not button1); as well
+ * as the new style of extended modifiers for all modifiers.
+ *
+ * @serial bitwise or of the *_DOWN_MASK modifiers
+ */
+ private int modifiers;
+
+ /**
+ * True if this is a key release; should only be true if keyChar is
+ * CHAR_UNDEFINED.
+ *
+ * @serial true to distinguish key pressed from key released
+ */
+ private boolean onKeyRelease;
+
+ /**
+ * Construct a keystroke with default values: it will be interpreted as a
+ * key typed event with an invalid character and no modifiers. Client code
+ * should use the factory methods instead.
+ *
+ * @see #getAWTKeyStroke(char)
+ * @see #getAWTKeyStroke(Character, int)
+ * @see #getAWTKeyStroke(int, int, boolean)
+ * @see #getAWTKeyStroke(int, int)
+ * @see #getAWTKeyStrokeForEvent(KeyEvent)
+ * @see #getAWTKeyStroke(String)
+ */
+ protected AWTKeyStroke()
+ {
+ keyChar = KeyEvent.CHAR_UNDEFINED;
+ }
+
+ /**
+ * Construct a keystroke with the given values. Client code should use the
+ * factory methods instead.
+ *
+ * @param keyChar the character entered, if this is a key typed
+ * @param keyCode the key pressed or released, or VK_UNDEFINED for key typed
+ * @param modifiers the modifier keys for the keystroke, in old or new style
+ * @param onKeyRelease true if this is a key release instead of a press
+ * @see #getAWTKeyStroke(char)
+ * @see #getAWTKeyStroke(Character, int)
+ * @see #getAWTKeyStroke(int, int, boolean)
+ * @see #getAWTKeyStroke(int, int)
+ * @see #getAWTKeyStrokeForEvent(KeyEvent)
+ * @see #getAWTKeyStroke(String)
+ */
+ protected AWTKeyStroke(char keyChar, int keyCode, int modifiers,
+ boolean onKeyRelease)
+ {
+ this.keyChar = keyChar;
+ this.keyCode = keyCode;
+ // No need to call extend(), as only trusted code calls this constructor.
+ this.modifiers = modifiers;
+ this.onKeyRelease = onKeyRelease;
+ }
+
+ /**
+ * Registers a new subclass as being the type of keystrokes to generate in
+ * the factory methods. This operation flushes the cache of stored keystrokes
+ * if the class differs from the current one. The new class must be
+ * AWTKeyStroke or a subclass, and must have a no-arg constructor (which may
+ * be private).
+ *
+ * @param subclass the new runtime type of generated keystrokes
+ * @throws IllegalArgumentException subclass doesn't have no-arg constructor
+ * @throws ClassCastException subclass doesn't extend AWTKeyStroke
+ */
+ protected static void registerSubclass(final Class<?> subclass)
+ {
+ if (subclass == null)
+ throw new IllegalArgumentException();
+ if (subclass.equals(ctor == null ? AWTKeyStroke.class
+ : ctor.getDeclaringClass()))
+ return;
+ if (subclass.equals(AWTKeyStroke.class))
+ {
+ cache.clear();
+ recent = null;
+ ctor = null;
+ return;
+ }
+ try
+ {
+ ctor = (Constructor) AccessController.doPrivileged
+ (new PrivilegedExceptionAction()
+ {
+ public Object run()
+ throws NoSuchMethodException, InstantiationException,
+ IllegalAccessException, InvocationTargetException
+ {
+ Constructor<?> c =
+ subclass.getDeclaredConstructor((Class<?>[])null);
+ c.setAccessible(true);
+ // Create a new instance, to make sure that we can, and
+ // to cause any ClassCastException.
+ AWTKeyStroke dummy = (AWTKeyStroke) c.newInstance();
+ return c;
+ }
+ });
+ }
+ catch (PrivilegedActionException e)
+ {
+ // e.getCause() will not ever be ClassCastException; that should
+ // escape on its own.
+ throw (RuntimeException)
+ new IllegalArgumentException().initCause(e.getCause());
+ }
+ cache.clear();
+ recent = null;
+ }
+
+ /**
+ * Returns a keystroke representing a typed character.
+ *
+ * @param keyChar the typed character
+ * @return the specified keystroke
+ */
+ public static AWTKeyStroke getAWTKeyStroke(char keyChar)
+ {
+ return getAWTKeyStroke(keyChar, KeyEvent.VK_UNDEFINED, 0, false);
+ }
+
+ /**
+ * Returns a keystroke representing a typed character with the given
+ * modifiers. Note that keyChar is a <code>Character</code> instead of a
+ * <code>char</code> to avoid accidental ambiguity with
+ * <code>getAWTKeyStroke(int, int)</code>. The modifiers are the bitwise
+ * or of the masks found in {@link InputEvent}; the new style (*_DOWN_MASK)
+ * is preferred, but the old style will work.
+ *
+ * @param keyChar the typed character
+ * @param modifiers the modifiers, or 0
+ * @return the specified keystroke
+ * @throws IllegalArgumentException if keyChar is null
+ */
+ public static AWTKeyStroke getAWTKeyStroke(Character keyChar, int modifiers)
+ {
+ if (keyChar == null)
+ throw new IllegalArgumentException();
+ return getAWTKeyStroke(keyChar.charValue(), KeyEvent.VK_UNDEFINED,
+ extend(modifiers), false);
+ }
+
+ /**
+ * Returns a keystroke representing a pressed or released key event, with
+ * the given modifiers. The "virtual key" should be one of the VK_*
+ * constants in {@link KeyEvent}. The modifiers are the bitwise or of the
+ * masks found in {@link InputEvent}; the new style (*_DOWN_MASK) is
+ * preferred, but the old style will work.
+ *
+ * @param keyCode the virtual key
+ * @param modifiers the modifiers, or 0
+ * @param release true if this is a key release instead of a key press
+ * @return the specified keystroke
+ */
+ public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers,
+ boolean release)
+ {
+ return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, keyCode,
+ extend(modifiers), release);
+ }
+
+ /**
+ * Returns a keystroke representing a pressed key event, with the given
+ * modifiers. The "virtual key" should be one of the VK_* constants in
+ * {@link KeyEvent}. The modifiers are the bitwise or of the masks found
+ * in {@link InputEvent}; the new style (*_DOWN_MASK) is preferred, but the
+ * old style will work.
+ *
+ * @param keyCode the virtual key
+ * @param modifiers the modifiers, or 0
+ * @return the specified keystroke
+ */
+ public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers)
+ {
+ return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, keyCode,
+ extend(modifiers), false);
+ }
+
+ /**
+ * Returns a keystroke representing what caused the key event.
+ *
+ * @param event the key event to convert
+ * @return the specified keystroke, or null if the event is invalid
+ * @throws NullPointerException if event is null
+ */
+ public static AWTKeyStroke getAWTKeyStrokeForEvent(KeyEvent event)
+ {
+ switch (event.id)
+ {
+ case KeyEvent.KEY_TYPED:
+ return getAWTKeyStroke(event.getKeyChar(), KeyEvent.VK_UNDEFINED,
+ extend(event.getModifiersEx()), false);
+ case KeyEvent.KEY_PRESSED:
+ return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, event.getKeyCode(),
+ extend(event.getModifiersEx()), false);
+ case KeyEvent.KEY_RELEASED:
+ return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, event.getKeyCode(),
+ extend(event.getModifiersEx()), true);
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Parses a string and returns the keystroke that it represents. The syntax
+ * for keystrokes is listed below, with tokens separated by an arbitrary
+ * number of spaces:
+ * <pre>
+ * keyStroke := &lt;modifiers&gt;* ( &lt;typedID&gt; | &lt;codeID&gt; )
+ * modifiers := ( shift | control | ctrl | meta | alt
+ * | button1 | button2 | button3 )
+ * typedID := typed &lt;single Unicode character&gt;
+ * codeID := ( pressed | released )? &lt;name&gt;
+ * name := &lt;the KeyEvent field name less the leading "VK_"&gt;
+ * </pre>
+ *
+ * <p>Note that the grammar is rather weak, and not all valid keystrokes
+ * can be generated in this manner (for example, a typed space, or anything
+ * with the alt-graph modifier!). The output of AWTKeyStroke.toString()
+ * will not meet the grammar. If pressed or released is not specified,
+ * pressed is assumed. Examples:<br>
+ * <code>
+ * "INSERT" =&gt; getAWTKeyStroke(KeyEvent.VK_INSERT, 0);<br>
+ * "control DELETE" =&gt;
+ * getAWTKeyStroke(KeyEvent.VK_DELETE, InputEvent.CTRL_MASK);<br>
+ * "alt shift X" =&gt; getAWTKeyStroke(KeyEvent.VK_X,
+ * InputEvent.ALT_MASK | InputEvent.SHIFT_MASK);<br>
+ * "alt shift released X" =&gt; getAWTKeyStroke(KeyEvent.VK_X,
+ * InputEvent.ALT_MASK | InputEvent.SHIFT_MASK, true);<br>
+ * "typed a" =&gt; getAWTKeyStroke('a');
+ * </code>
+ *
+ * @param s the string to parse
+ * @throws IllegalArgumentException if s is null or cannot be parsed
+ * @return the specified keystroke
+ */
+ public static AWTKeyStroke getAWTKeyStroke(String s)
+ {
+ if (s == null)
+ throw new IllegalArgumentException("null argument");
+ StringTokenizer t = new StringTokenizer(s, " ");
+ if (! t.hasMoreTokens())
+ throw new IllegalArgumentException("no tokens '" + s + "'");
+ int modifiers = 0;
+ boolean released = false;
+ String token = null;
+ do
+ {
+ token = t.nextToken();
+ if ("shift".equals(token))
+ {
+ modifiers |= KeyEvent.SHIFT_MASK;
+ modifiers |= KeyEvent.SHIFT_DOWN_MASK;
+ }
+ else if ("ctrl".equals(token) || "control".equals(token))
+ {
+ modifiers |= KeyEvent.CTRL_MASK;
+ modifiers |= KeyEvent.CTRL_DOWN_MASK;
+ }
+ else if ("meta".equals(token))
+ {
+ modifiers |= KeyEvent.META_MASK;
+ modifiers |= KeyEvent.META_DOWN_MASK;
+ }
+ else if ("alt".equals(token))
+ {
+ modifiers |= KeyEvent.ALT_MASK;
+ modifiers |= KeyEvent.ALT_DOWN_MASK;
+ }
+ else if ("button1".equals(token))
+ modifiers |= KeyEvent.BUTTON1_DOWN_MASK;
+ else if ("button2".equals(token))
+ modifiers |= KeyEvent.BUTTON2_DOWN_MASK;
+ else if ("button3".equals(token))
+ modifiers |= KeyEvent.BUTTON3_DOWN_MASK;
+ else if ("typed".equals(token))
+ {
+ if (t.hasMoreTokens())
+ {
+ token = t.nextToken();
+ if (! t.hasMoreTokens() && token.length() == 1)
+ return getAWTKeyStroke(token.charAt(0),
+ KeyEvent.VK_UNDEFINED, modifiers,
+ false);
+ }
+ throw new IllegalArgumentException("Invalid 'typed' argument '"
+ + s + "'");
+ }
+ else if ("pressed".equals(token))
+ {
+ if (t.hasMoreTokens())
+ token = t.nextToken();
+ break;
+ }
+ else if ("released".equals(token))
+ {
+ released = true;
+ if (t.hasMoreTokens())
+ token = t.nextToken();
+ break;
+ }
+ else
+ break;
+ }
+ while (t.hasMoreTokens());
+ // Now token contains the VK name we must parse.
+ Integer code = (Integer) vktable.get(token);
+ if (code == null)
+ throw new IllegalArgumentException("Unknown token '" + token
+ + "' in '" + s + "'");
+ if (t.hasMoreTokens())
+ throw new IllegalArgumentException("Too many tokens: " + s);
+ return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, code.intValue(),
+ modifiers, released);
+ }
+
+ /**
+ * Returns the character of this keystroke, if it was typed.
+ *
+ * @return the character value, or CHAR_UNDEFINED
+ * @see #getAWTKeyStroke(char)
+ */
+ public final char getKeyChar()
+ {
+ return keyChar;
+ }
+
+ /**
+ * Returns the virtual key code of this keystroke, if it was pressed or
+ * released. This will be a VK_* constant from KeyEvent.
+ *
+ * @return the virtual key code value, or VK_UNDEFINED
+ * @see #getAWTKeyStroke(int, int)
+ */
+ public final int getKeyCode()
+ {
+ return keyCode;
+ }
+
+ /**
+ * Returns the modifiers for this keystroke. This will be a bitwise or of
+ * constants from InputEvent; it includes the old style masks for shift,
+ * control, alt, meta, and alt-graph (but not button1); as well as the new
+ * style of extended modifiers for all modifiers.
+ *
+ * @return the modifiers
+ * @see #getAWTKeyStroke(Character, int)
+ * @see #getAWTKeyStroke(int, int)
+ */
+ public final int getModifiers()
+ {
+ return modifiers;
+ }
+
+ /**
+ * Tests if this keystroke is a key release.
+ *
+ * @return true if this is a key release
+ * @see #getAWTKeyStroke(int, int, boolean)
+ */
+ public final boolean isOnKeyRelease()
+ {
+ return onKeyRelease;
+ }
+
+ /**
+ * Returns the AWT event type of this keystroke. This is one of
+ * {@link KeyEvent#KEY_TYPED}, {@link KeyEvent#KEY_PRESSED}, or
+ * {@link KeyEvent#KEY_RELEASED}.
+ *
+ * @return the key event type
+ */
+ public final int getKeyEventType()
+ {
+ return keyCode == KeyEvent.VK_UNDEFINED ? KeyEvent.KEY_TYPED
+ : onKeyRelease ? KeyEvent.KEY_RELEASED : KeyEvent.KEY_PRESSED;
+ }
+
+ /**
+ * Returns a hashcode for this key event. It is not documented, but appears
+ * to be: <code>(getKeyChar() + 1) * (getKeyCode() + 1)
+ * * (getModifiers() + 1) * 2 + (isOnKeyRelease() ? 1 : 2)</code>.
+ *
+ * @return the hashcode
+ */
+ public int hashCode()
+ {
+ return (keyChar + 1) * (keyCode + 1) * (modifiers + 1) * 2
+ + (onKeyRelease ? 1 : 2);
+ }
+
+ /**
+ * Tests two keystrokes for equality.
+ *
+ * @param o the object to test
+ * @return true if it is equal
+ */
+ public final boolean equals(Object o)
+ {
+ if (! (o instanceof AWTKeyStroke))
+ return false;
+ AWTKeyStroke s = (AWTKeyStroke) o;
+ return this == o || (keyChar == s.keyChar && keyCode == s.keyCode
+ && modifiers == s.modifiers
+ && onKeyRelease == s.onKeyRelease);
+ }
+
+ /**
+ * Returns a string representation of this keystroke. For typed keystrokes,
+ * this is <code>"keyChar " + KeyEvent.getKeyModifiersText(getModifiers())
+ + getKeyChar()</code>; for pressed and released keystrokes, this is
+ * <code>"keyCode " + KeyEvent.getKeyModifiersText(getModifiers())
+ * + KeyEvent.getKeyText(getKeyCode())
+ * + (isOnKeyRelease() ? "-R" : "-P")</code>.
+ *
+ * @return a string representation
+ */
+ public String toString()
+ {
+ if (keyCode == KeyEvent.VK_UNDEFINED)
+ return "keyChar " + KeyEvent.getKeyModifiersText(modifiers) + keyChar;
+ return "keyCode " + KeyEvent.getKeyModifiersText(modifiers)
+ + KeyEvent.getKeyText(keyCode) + (onKeyRelease ? "-R" : "-P");
+ }
+
+ /**
+ * Returns a cached version of the deserialized keystroke, if available.
+ *
+ * @return a cached replacement
+ * @throws ObjectStreamException if something goes wrong
+ */
+ protected Object readResolve() throws ObjectStreamException
+ {
+ AWTKeyStroke s = cache.get(this);
+ if (s != null)
+ return s;
+ cache.put(this, this);
+ return this;
+ }
+
+ /**
+ * Gets the appropriate keystroke, creating one if necessary.
+ *
+ * @param keyChar the keyChar
+ * @param keyCode the keyCode
+ * @param modifiers the modifiers
+ * @param release true for key release
+ * @return the specified keystroke
+ */
+ private static AWTKeyStroke getAWTKeyStroke(char keyChar, int keyCode,
+ int modifiers, boolean release)
+ {
+ // Check level 0 cache.
+ AWTKeyStroke stroke = recent; // Avoid thread races.
+ if (stroke != null && stroke.keyChar == keyChar
+ && stroke.keyCode == keyCode && stroke.modifiers == modifiers
+ && stroke.onKeyRelease == release)
+ return stroke;
+ // Create a new object, on the assumption that if it has a match in the
+ // cache, the VM can easily garbage collect it as it is temporary.
+ Constructor c = ctor; // Avoid thread races.
+ if (c == null)
+ stroke = new AWTKeyStroke(keyChar, keyCode, modifiers, release);
+ else
+ try
+ {
+ stroke = (AWTKeyStroke) c.newInstance();
+ stroke.keyChar = keyChar;
+ stroke.keyCode = keyCode;
+ stroke.modifiers = modifiers;
+ stroke.onKeyRelease = release;
+ }
+ catch (Exception e)
+ {
+ throw (Error) new InternalError().initCause(e);
+ }
+ // Check level 1 cache.
+ AWTKeyStroke cached = cache.get(stroke);
+ if (cached == null)
+ cache.put(stroke, stroke);
+ else
+ stroke = cached;
+ return recent = stroke;
+ }
+
+ /**
+ * Converts the modifiers to the appropriate format.
+ *
+ * @param mod the modifiers to convert
+ * @return the adjusted modifiers
+ */
+ private static int extend(int mod)
+ {
+ if ((mod & (KeyEvent.SHIFT_MASK | KeyEvent.SHIFT_DOWN_MASK)) != 0)
+ mod |= KeyEvent.SHIFT_MASK | KeyEvent.SHIFT_DOWN_MASK;
+ if ((mod & (KeyEvent.CTRL_MASK | KeyEvent.CTRL_DOWN_MASK)) != 0)
+ mod |= KeyEvent.CTRL_MASK | KeyEvent.CTRL_DOWN_MASK;
+ if ((mod & (KeyEvent.META_MASK | KeyEvent.META_DOWN_MASK)) != 0)
+ mod |= KeyEvent.META_MASK | KeyEvent.META_DOWN_MASK;
+ if ((mod & (KeyEvent.ALT_MASK | KeyEvent.ALT_DOWN_MASK)) != 0)
+ mod |= KeyEvent.ALT_MASK | KeyEvent.ALT_DOWN_MASK;
+ if ((mod & (KeyEvent.ALT_GRAPH_MASK | KeyEvent.ALT_GRAPH_DOWN_MASK)) != 0)
+ mod |= KeyEvent.ALT_GRAPH_MASK | KeyEvent.ALT_GRAPH_DOWN_MASK;
+ if ((mod & KeyEvent.BUTTON1_MASK) != 0)
+ mod |= KeyEvent.BUTTON1_DOWN_MASK;
+ return mod & MODIFIERS_MASK;
+ }
+} // class AWTKeyStroke
diff --git a/libjava/classpath/java/awt/AWTPermission.java b/libjava/classpath/java/awt/AWTPermission.java
new file mode 100644
index 000000000..3e50c059f
--- /dev/null
+++ b/libjava/classpath/java/awt/AWTPermission.java
@@ -0,0 +1,121 @@
+/* AWTPermission.java -- AWT related permissions
+ Copyright (C) 2000, 2002 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.security.BasicPermission;
+
+/**
+ * This class implements permissions for AWT. This is a named
+ * permission. No actions are defined.
+ *
+ * <p>The following table provides a list of all the possible AWTPermission
+ * permission names with a description of what that permission allows.<br>
+ * <table border=1>
+ * <tr><th>Permission Name</th><th>Permission Allows</th><th>Risks</th</tr>
+ * <tr>
+ * <td><code>accessClipboard</code></td>
+ * <td>posting and reading the AWT clipboard</td>
+ * <td>the clipboard may contain sensitive data</td></tr>
+ * <tr>
+ * <td><code>accessEventQueue</code></td>
+ * <td>access to the AWT event queue</td>
+ * <td>malicious code could remove real events and replace them with bogus
+ * ones, including simulating the user granting permission</td></tr>
+ * <tr>
+ * <td><code>listenToAllAWTEvents</code></td>
+ * <td>listen to system-wide AWT events</td>
+ * <td>malicious code can read passwords entered in an AWT event, and in
+ * combination with accessEventQueue, could fake system events</td></tr>
+ * <tr>
+ * <td><code>showWindowWithoutWarningBanner</code></td>
+ * <td>display a window without a banner notification of insecurity</td>
+ * <td>malicious code could install a Trojan horse applet that looks like
+ * a normal window, and thus steal data like passwords</td></tr>
+ * <tr>
+ * <td><code>readDisplayPixels</code></td>
+ * <td>read back pixels from the display screen</td>
+ * <td>malicious code could snoop on the user's actions</td></tr>
+ * <tr>
+ * <td><code>createRobot</code></td>
+ * <td>create an instance of java.awt.Robot</td>
+ * <td>these objects can generate events as though they were the user; so
+ * malicious code could control the system</td></tr>
+ * <tr>
+ * <td><code>fullScreenExclusive</code></td>
+ * <td>enter full-screen exclusive mode</td>
+ * <td>malicious code could masquerade as a trusted program</td></tr>
+ * </table>
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public final class AWTPermission extends BasicPermission
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 8890392402588814465L;
+
+ /**
+ * Construct a AWTPermission with the given name.
+ *
+ * @param name the permission name
+ * @throws NullPointerException if name is null
+ * @throws IllegalArgumentException if name is invalid
+ */
+ public AWTPermission(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Create a new permission with the specified name. The actions argument
+ * is ignored, as AWT permissions have no actions.
+ *
+ * @param name the permission name
+ * @param actions ignored
+ * @throws NullPointerException if name is null
+ * @throws IllegalArgumentException if name is invalid
+ */
+ public AWTPermission(String name, String actions)
+ {
+ super(name);
+ }
+} // class AWTPermission
diff --git a/libjava/classpath/java/awt/ActiveEvent.java b/libjava/classpath/java/awt/ActiveEvent.java
new file mode 100644
index 000000000..e42959fe3
--- /dev/null
+++ b/libjava/classpath/java/awt/ActiveEvent.java
@@ -0,0 +1,61 @@
+/* ActiveEvent.java -- a self-dispatching event
+ Copyright (C) 2000, 2002 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * An interface for events which can dispatch themselves in another thread.
+ * This has two uses: first, if your code is in a critical section, calling a
+ * synchronized method might deadlock. But by using an ActiveEvent to call
+ * the second section, it will not obtain the lock until you have left the
+ * critical section, avoiding deadlock. The second use is for calling
+ * untrusted code. For example, system code should use an ActiveEvent to
+ * invoke user code securely.
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface ActiveEvent
+{
+ /**
+ * Dispatch the event, according to what the event needs done. Invoked
+ * automatically if this is placed on the <code>EventDispatchQueue</code>.
+ */
+ void dispatch();
+} // interface ActiveEvent
diff --git a/libjava/classpath/java/awt/Adjustable.java b/libjava/classpath/java/awt/Adjustable.java
new file mode 100644
index 000000000..8f633e91a
--- /dev/null
+++ b/libjava/classpath/java/awt/Adjustable.java
@@ -0,0 +1,171 @@
+/* Adjustable.java -- Objects with a numeric adjustment scale
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.AdjustmentListener;
+
+/**
+ * This interface is for objects that take a numeric value that can be
+ * adjusted within a bounded range. For example, a scroll bar.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public interface Adjustable
+{
+ /** Constant for an adjustable object with horizontal orientation. */
+ int HORIZONTAL = 0;
+
+ /** Constant for an adjustable object with vertical orientation. */
+ int VERTICAL = 1;
+
+ /** Constant for an adjustable object with no orientation. */
+ int NO_ORIENTATION = 2;
+
+ /**
+ * Returns a constant representing the orientation of the object.
+ *
+ * @return the orientation of this object
+ * @see #HORIZONTAL
+ * @see #VERTICAL
+ * @see #NO_ORIENTATION
+ */
+ int getOrientation();
+
+ /**
+ * Sets the minimum value this object can have.
+ *
+ * @param minimum the new minimum value
+ */
+ void setMinimum(int minimum);
+
+ /**
+ * Returns the minimum value this object can have.
+ *
+ * @return the minimum value
+ */
+ int getMinimum();
+
+ /**
+ * Sets the maximum value this object can have.
+ *
+ * @param maximum the new maximum value
+ */
+ void setMaximum(int maximum);
+
+ /**
+ * Returns the maximum value this object can have.
+ *
+ * @return the maximum value
+ */
+ int getMaximum();
+
+ /**
+ * Sets the increment value for incrementing the value by units.
+ *
+ * @param increment the unit increment value
+ */
+ void setUnitIncrement(int increment);
+
+ /**
+ * Returns the increment value for incrementing the value by units.
+ *
+ * @return the unit increment value
+ */
+ int getUnitIncrement();
+
+ /**
+ * Sets the increment value for incrementing the value by blocks.
+ *
+ * @param increment the block increment value
+ */
+ void setBlockIncrement(int increment);
+
+ /**
+ * Returns the increment value for incrementing the value by blocks.
+ *
+ * @return the block increment value
+ */
+ int getBlockIncrement();
+
+ /**
+ * Sets the length of the indicator for this object to the specified value.
+ *
+ * @param length the indicator length
+ */
+ void setVisibleAmount(int length);
+
+ /**
+ * Returns the length of the indicator for this object.
+ *
+ * @return the indicator length
+ */
+ int getVisibleAmount();
+
+ /**
+ * Sets the current value of the object.
+ *
+ * @param value the new value
+ */
+ void setValue(int value);
+
+ /**
+ * Returns the current value of the object.
+ *
+ * @return the current value
+ */
+ int getValue();
+
+ /**
+ * Adds a listener that will receive adjustment events for this object.
+ *
+ * @param listener the adjustment listener to add
+ * @see java.awt.event.AdjustmentEvent
+ */
+ void addAdjustmentListener(AdjustmentListener listener);
+
+ /**
+ * Removes an adjustment listener from this object.
+ *
+ * @param listener the adjustment listener to remove
+ * @see java.awt.event.AdjustmentEvent
+ */
+ void removeAdjustmentListener(AdjustmentListener listener);
+} // interface Adjustable
diff --git a/libjava/classpath/java/awt/AlphaComposite.java b/libjava/classpath/java/awt/AlphaComposite.java
new file mode 100644
index 000000000..d6c43d139
--- /dev/null
+++ b/libjava/classpath/java/awt/AlphaComposite.java
@@ -0,0 +1,215 @@
+/* AlphaComposite.java -- provides a context for performing alpha compositing
+ Copyright (C) 2002, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import gnu.java.awt.java2d.AlphaCompositeContext;
+
+import java.awt.image.ColorModel;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Composite
+ * @see CompositeContext
+ * @since 1.3
+ * @status updated to 1.4 except for createContext, needs documentation
+ */
+public final class AlphaComposite implements Composite
+{
+ /** Map Long to AlphaComposites. See getInstance for details. */
+ private static final LinkedHashMap cache = new LinkedHashMap(11, 0.75f, true)
+ {
+ /** The largest the alpha composite cache can grow. */
+ private static final int MAX_CACHE_SIZE = 2048;
+
+ /** Prune stale entries. */
+ protected boolean removeEldestEntry(Map.Entry eldest)
+ {
+ return size() > MAX_CACHE_SIZE;
+ }
+ };
+
+ public static final int CLEAR = 1;
+ public static final int SRC = 2;
+ public static final int DST = 9;
+ public static final int SRC_OVER = 3;
+ public static final int DST_OVER = 4;
+ public static final int SRC_IN = 5;
+ public static final int DST_IN = 6;
+ public static final int SRC_OUT = 7;
+ public static final int DST_OUT = 8;
+ public static final int SRC_ATOP = 10;
+ public static final int DST_ATOP = 11;
+ public static final int XOR = 12;
+ public static final AlphaComposite Clear = getInstance(CLEAR);
+ public static final AlphaComposite Src = getInstance(SRC);
+ public static final AlphaComposite Dst = getInstance(DST);
+ public static final AlphaComposite SrcOver = getInstance(SRC_OVER);
+ public static final AlphaComposite DstOver = getInstance(DST_OVER);
+ public static final AlphaComposite SrcIn = getInstance(SRC_IN);
+ public static final AlphaComposite DstIn = getInstance(DST_IN);
+ public static final AlphaComposite SrcOut = getInstance(SRC_OUT);
+ public static final AlphaComposite DstOut = getInstance(DST_OUT);
+ public static final AlphaComposite SrcAtop = getInstance(SRC_ATOP);
+ public static final AlphaComposite DstAtop = getInstance(DST_ATOP);
+ public static final AlphaComposite Xor = getInstance(XOR);
+
+ private final int rule;
+ private final float alpha;
+ private AlphaComposite(int rule, float alpha)
+ {
+ this.rule = rule;
+ this.alpha = alpha;
+ }
+
+ /**
+ * Creates an AlphaComposite object with the specified rule.
+ *
+ * @param rule The compositing rule.
+ *
+ * @exception IllegalArgumentException If rule is not one of the following:
+ * CLEAR, SRC, DST, SRC_OVER, DST_OVER, SRC_IN, DST_IN, SRC_OUT, DST_OUT,
+ * SRC_ATOP, DST_ATOP, or XOR.
+ */
+ public static AlphaComposite getInstance(int rule)
+ {
+ return getInstance(rule, 1);
+ }
+
+ /**
+ * Creates an AlphaComposite object with the specified rule and the constant
+ * alpha to multiply with the alpha of the source. The source is multiplied
+ * with the specified alpha before being composited with the destination.
+ *
+ * @param rule The compositing rule.
+ *
+ * @exception IllegalArgumentException If rule is not one of the following:
+ * CLEAR, SRC, DST, SRC_OVER, DST_OVER, SRC_IN, DST_IN, SRC_OUT, DST_OUT,
+ * SRC_ATOP, DST_ATOP, or XOR.
+ */
+ public static AlphaComposite getInstance(int rule, float alpha)
+ {
+ if (rule < CLEAR || rule > XOR || ! (alpha >= 0 && alpha <= 1))
+ throw new IllegalArgumentException();
+ // This long is guaranteed unique for all valid alpha composites.
+ Long l = new Long(rule + Double.doubleToLongBits(alpha));
+ AlphaComposite a = (AlphaComposite) cache.get(l);
+ if (a == null)
+ {
+ a = new AlphaComposite(rule, alpha);
+ cache.put(l, a);
+ }
+ return a;
+ }
+
+ /**
+ * Creates a {@link CompositeContext} that can be used to perform
+ * compositing operations according to this AlphaComposite settings.
+ *
+ * @param srcColorModel the color model of the source raster
+ * @param dstColorModel the color model of the destination raster
+ * @param hints the rendering hints to use
+ *
+ * @return a {@link CompositeContext} that can be used to perform
+ * compositing operations according to this AlphaComposite settings
+ */
+ public CompositeContext createContext(ColorModel srcColorModel,
+ ColorModel dstColorModel,
+ RenderingHints hints)
+ {
+ return new AlphaCompositeContext(this, srcColorModel, dstColorModel);
+ }
+
+ /**
+ * Return an <code>AlphaComposite</code> similar to <code>this</code>,
+ * that uses the specified rule. If <code>rule</code> is the same as
+ * <code>this.rule</code>, then <code>this</code> is returned.
+ *
+ * @since 1.6
+ */
+ public AlphaComposite derive(int rule)
+ {
+ if (this.rule == rule)
+ return this;
+ else
+ return AlphaComposite.getInstance(rule, this.getAlpha());
+ }
+
+ /**
+ * Return an <code>AlphaComposite</code> similar to <code>this</code>,
+ * that uses the specified <code>alpha</code>.
+ *
+ * If <code>alph</code> is the same as <code>this.alpha</code>,
+ * then <code>this</code> is returned.
+ *
+ * @since 1.6
+ */
+ public AlphaComposite derive(float alpha)
+ {
+ if (this.getAlpha() == alpha)
+ return this;
+ else
+ return AlphaComposite.getInstance(this.getRule(), alpha);
+ }
+
+ public float getAlpha()
+ {
+ return alpha;
+ }
+
+ public int getRule()
+ {
+ return rule;
+ }
+
+ public int hashCode()
+ {
+ return 31 * Float.floatToIntBits(alpha) + rule;
+ }
+
+ public boolean equals(Object o)
+ {
+ if (! (o instanceof AlphaComposite))
+ return false;
+ AlphaComposite a = (AlphaComposite) o;
+ return rule == a.rule && alpha == a.alpha;
+ }
+} // class AlphaComposite
diff --git a/libjava/classpath/java/awt/AttributeValue.java b/libjava/classpath/java/awt/AttributeValue.java
new file mode 100644
index 000000000..080e92e22
--- /dev/null
+++ b/libjava/classpath/java/awt/AttributeValue.java
@@ -0,0 +1,98 @@
+/* AttributeValue.java -- parent of type-safe enums of attributes
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This class is undocumented by Sun, but it is the parent of several other
+ * classes, all of which are type-safe enumerations. This takes care of
+ * <code>equals</code>, <code>toString</code>, and <code>hashCode</code>, so
+ * that you don't have to (although hashCode is commonly overridden).
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+class AttributeValue
+{
+ /** The value of the enumeration. Package visible for speed. */
+ final int value;
+
+ /** The list of enumeration names for the given subclass. */
+ private final String[] names;
+
+ /**
+ * Construct a type-safe enumeration element. For example,<br>
+ * <pre>
+ * class Foo extends AttributeValue
+ * {
+ * private static final String[] names = { "one", "two" }
+ * public static final Foo ONE = new Foo(0);
+ * public static final Foo TWO = new Foo(1);
+ * private Foo(int value) { super(value, names); }
+ * }
+ * </pre>
+ *
+ * @param value the position of this enumeration element, consecutive from 0
+ * @param names the constant list of enumeration names for the subclass
+ */
+ AttributeValue(int value, String[] names)
+ {
+ this.value = value;
+ this.names = names;
+ }
+
+ /**
+ * Returns the hashcode of this element. This is the index of the element
+ * in the enumeration. Note that equals defaults to the == relation.
+ *
+ * @return the hashcode
+ */
+ public int hashCode()
+ {
+ return value;
+ }
+
+ /**
+ * Returns the name of this enumeration element.
+ *
+ * @return the element name
+ */
+ public String toString()
+ {
+ return names[value];
+ }
+} // class AttributeValue
diff --git a/libjava/classpath/java/awt/BasicStroke.java b/libjava/classpath/java/awt/BasicStroke.java
new file mode 100644
index 000000000..eac69d986
--- /dev/null
+++ b/libjava/classpath/java/awt/BasicStroke.java
@@ -0,0 +1,902 @@
+/* BasicStroke.java --
+ Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import gnu.java.awt.java2d.CubicSegment;
+import gnu.java.awt.java2d.LineSegment;
+import gnu.java.awt.java2d.QuadSegment;
+import gnu.java.awt.java2d.Segment;
+
+import java.awt.geom.FlatteningPathIterator;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Point2D;
+import java.util.Arrays;
+
+/**
+ * A general purpose {@link Stroke} implementation that can represent a wide
+ * variety of line styles for use with subclasses of {@link Graphics2D}.
+ * <p>
+ * The line cap and join styles can be set using the options illustrated
+ * here:
+ * <p>
+ * <img src="doc-files/capjoin.png" width="350" height="180"
+ * alt="Illustration of line cap and join styles" />
+ * <p>
+ * A dash array can be used to specify lines with alternating opaque and
+ * transparent sections.
+ */
+public class BasicStroke implements Stroke
+{
+ /**
+ * Indicates a mitered line join style. See the class overview for an
+ * illustration.
+ */
+ public static final int JOIN_MITER = 0;
+
+ /**
+ * Indicates a rounded line join style. See the class overview for an
+ * illustration.
+ */
+ public static final int JOIN_ROUND = 1;
+
+ /**
+ * Indicates a bevelled line join style. See the class overview for an
+ * illustration.
+ */
+ public static final int JOIN_BEVEL = 2;
+
+ /**
+ * Indicates a flat line cap style. See the class overview for an
+ * illustration.
+ */
+ public static final int CAP_BUTT = 0;
+
+ /**
+ * Indicates a rounded line cap style. See the class overview for an
+ * illustration.
+ */
+ public static final int CAP_ROUND = 1;
+
+ /**
+ * Indicates a square line cap style. See the class overview for an
+ * illustration.
+ */
+ public static final int CAP_SQUARE = 2;
+
+ /** The stroke width. */
+ private final float width;
+
+ /** The line cap style. */
+ private final int cap;
+
+ /** The line join style. */
+ private final int join;
+
+ /** The miter limit. */
+ private final float limit;
+
+ /** The dash array. */
+ private final float[] dash;
+
+ /** The dash phase. */
+ private final float phase;
+
+ // The inner and outer paths of the stroke
+ private Segment start, end;
+
+ /**
+ * Creates a new <code>BasicStroke</code> instance with the given attributes.
+ *
+ * @param width the line width (>= 0.0f).
+ * @param cap the line cap style (one of {@link #CAP_BUTT},
+ * {@link #CAP_ROUND} or {@link #CAP_SQUARE}).
+ * @param join the line join style (one of {@link #JOIN_ROUND},
+ * {@link #JOIN_BEVEL}, or {@link #JOIN_MITER}).
+ * @param miterlimit the limit to trim the miter join. The miterlimit must be
+ * greater than or equal to 1.0f.
+ * @param dash The array representing the dashing pattern. There must be at
+ * least one non-zero entry.
+ * @param dashPhase is negative and dash is not null.
+ *
+ * @throws IllegalArgumentException If one input parameter doesn't meet
+ * its needs.
+ */
+ public BasicStroke(float width, int cap, int join, float miterlimit,
+ float[] dash, float dashPhase)
+ {
+ if (width < 0.0f )
+ throw new IllegalArgumentException("width " + width + " < 0");
+ else if (cap < CAP_BUTT || cap > CAP_SQUARE)
+ throw new IllegalArgumentException("cap " + cap + " out of range ["
+ + CAP_BUTT + ".." + CAP_SQUARE + "]");
+ else if (miterlimit < 1.0f && join == JOIN_MITER)
+ throw new IllegalArgumentException("miterlimit " + miterlimit
+ + " < 1.0f while join == JOIN_MITER");
+ else if (join < JOIN_MITER || join > JOIN_BEVEL)
+ throw new IllegalArgumentException("join " + join + " out of range ["
+ + JOIN_MITER + ".." + JOIN_BEVEL
+ + "]");
+ else if (dashPhase < 0.0f && dash != null)
+ throw new IllegalArgumentException("dashPhase " + dashPhase
+ + " < 0.0f while dash != null");
+ else if (dash != null)
+ if (dash.length == 0)
+ throw new IllegalArgumentException("dash.length is 0");
+ else
+ {
+ boolean allZero = true;
+
+ for ( int i = 0; i < dash.length; ++i)
+ {
+ if (dash[i] != 0.0f)
+ {
+ allZero = false;
+ break;
+ }
+ }
+
+ if (allZero)
+ throw new IllegalArgumentException("all dashes are 0.0f");
+ }
+
+ this.width = width;
+ this.cap = cap;
+ this.join = join;
+ limit = miterlimit;
+ this.dash = dash == null ? null : (float[]) dash.clone();
+ phase = dashPhase;
+ }
+
+ /**
+ * Creates a new <code>BasicStroke</code> instance with the given attributes.
+ *
+ * @param width the line width (>= 0.0f).
+ * @param cap the line cap style (one of {@link #CAP_BUTT},
+ * {@link #CAP_ROUND} or {@link #CAP_SQUARE}).
+ * @param join the line join style (one of {@link #JOIN_ROUND},
+ * {@link #JOIN_BEVEL}, or {@link #JOIN_MITER}).
+ * @param miterlimit the limit to trim the miter join. The miterlimit must be
+ * greater than or equal to 1.0f.
+ *
+ * @throws IllegalArgumentException If one input parameter doesn't meet
+ * its needs.
+ */
+ public BasicStroke(float width, int cap, int join, float miterlimit)
+ {
+ this(width, cap, join, miterlimit, null, 0);
+ }
+
+ /**
+ * Creates a new <code>BasicStroke</code> instance with the given attributes.
+ * The miter limit defaults to <code>10.0</code>.
+ *
+ * @param width the line width (>= 0.0f).
+ * @param cap the line cap style (one of {@link #CAP_BUTT},
+ * {@link #CAP_ROUND} or {@link #CAP_SQUARE}).
+ * @param join the line join style (one of {@link #JOIN_ROUND},
+ * {@link #JOIN_BEVEL}, or {@link #JOIN_MITER}).
+ *
+ * @throws IllegalArgumentException If one input parameter doesn't meet
+ * its needs.
+ */
+ public BasicStroke(float width, int cap, int join)
+ {
+ this(width, cap, join, 10, null, 0);
+ }
+
+ /**
+ * Creates a new <code>BasicStroke</code> instance with the given line
+ * width. The default values are:
+ * <ul>
+ * <li>line cap style: {@link #CAP_SQUARE};</li>
+ * <li>line join style: {@link #JOIN_MITER};</li>
+ * <li>miter limit: <code>10.0f</code>.
+ * </ul>
+ *
+ * @param width the line width (>= 0.0f).
+ *
+ * @throws IllegalArgumentException If <code>width</code> is negative.
+ */
+ public BasicStroke(float width)
+ {
+ this(width, CAP_SQUARE, JOIN_MITER, 10, null, 0);
+ }
+
+ /**
+ * Creates a new <code>BasicStroke</code> instance. The default values are:
+ * <ul>
+ * <li>line width: <code>1.0f</code>;</li>
+ * <li>line cap style: {@link #CAP_SQUARE};</li>
+ * <li>line join style: {@link #JOIN_MITER};</li>
+ * <li>miter limit: <code>10.0f</code>.
+ * </ul>
+ */
+ public BasicStroke()
+ {
+ this(1, CAP_SQUARE, JOIN_MITER, 10, null, 0);
+ }
+
+ /**
+ * Creates a shape representing the stroked outline of the given shape.
+ * THIS METHOD IS NOT YET IMPLEMENTED.
+ *
+ * @param s the shape.
+ */
+ public Shape createStrokedShape(Shape s)
+ {
+ PathIterator pi = s.getPathIterator(null);
+
+ if( dash == null )
+ return solidStroke( pi );
+
+ return dashedStroke( pi );
+ }
+
+ /**
+ * Returns the line width.
+ *
+ * @return The line width.
+ */
+ public float getLineWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Returns a code indicating the line cap style (one of {@link #CAP_BUTT},
+ * {@link #CAP_ROUND}, {@link #CAP_SQUARE}).
+ *
+ * @return A code indicating the line cap style.
+ */
+ public int getEndCap()
+ {
+ return cap;
+ }
+
+ /**
+ * Returns a code indicating the line join style (one of {@link #JOIN_BEVEL},
+ * {@link #JOIN_MITER} or {@link #JOIN_ROUND}).
+ *
+ * @return A code indicating the line join style.
+ */
+ public int getLineJoin()
+ {
+ return join;
+ }
+
+ /**
+ * Returns the miter limit.
+ *
+ * @return The miter limit.
+ */
+ public float getMiterLimit()
+ {
+ return limit;
+ }
+
+ /**
+ * Returns the dash array, which defines the length of alternate opaque and
+ * transparent sections in lines drawn with this stroke. If
+ * <code>null</code>, a continuous line will be drawn.
+ *
+ * @return The dash array (possibly <code>null</code>).
+ */
+ public float[] getDashArray()
+ {
+ return dash;
+ }
+
+ /**
+ * Returns the dash phase for the stroke. This is the offset from the start
+ * of a path at which the pattern defined by {@link #getDashArray()} is
+ * rendered.
+ *
+ * @return The dash phase.
+ */
+ public float getDashPhase()
+ {
+ return phase;
+ }
+
+ /**
+ * Returns the hash code for this object. The hash is calculated by
+ * xoring the hash, cap, join, limit, dash array and phase values
+ * (converted to <code>int</code> first with
+ * <code>Float.floatToIntBits()</code> if the value is a
+ * <code>float</code>).
+ *
+ * @return The hash code.
+ */
+ public int hashCode()
+ {
+ int hash = Float.floatToIntBits(width);
+ hash ^= cap;
+ hash ^= join;
+ hash ^= Float.floatToIntBits(limit);
+
+ if (dash != null)
+ for (int i = 0; i < dash.length; i++)
+ hash ^= Float.floatToIntBits(dash[i]);
+
+ hash ^= Float.floatToIntBits(phase);
+
+ return hash;
+ }
+
+ /**
+ * Compares this <code>BasicStroke</code> for equality with an arbitrary
+ * object. This method returns <code>true</code> if and only if:
+ * <ul>
+ * <li><code>o</code> is an instanceof <code>BasicStroke</code>;</li>
+ * <li>this object has the same width, line cap style, line join style,
+ * miter limit, dash array and dash phase as <code>o</code>.</li>
+ * </ul>
+ *
+ * @param o the object (<code>null</code> permitted).
+ *
+ * @return <code>true</code> if this stroke is equal to <code>o</code> and
+ * <code>false</code> otherwise.
+ */
+ public boolean equals(Object o)
+ {
+ if (! (o instanceof BasicStroke))
+ return false;
+ BasicStroke s = (BasicStroke) o;
+ return width == s.width && cap == s.cap && join == s.join
+ && limit == s.limit && Arrays.equals(dash, s.dash) && phase == s.phase;
+ }
+
+ private Shape solidStroke(PathIterator pi)
+ {
+ double[] coords = new double[6];
+ double x, y, x0, y0;
+ boolean pathOpen = false;
+ GeneralPath output = new GeneralPath( );
+ Segment[] p;
+ x = x0 = y = y0 = 0;
+
+ while( !pi.isDone() )
+ {
+ switch( pi.currentSegment(coords) )
+ {
+ case PathIterator.SEG_MOVETO:
+ x0 = x = coords[0];
+ y0 = y = coords[1];
+ if( pathOpen )
+ {
+ capEnds();
+ convertPath(output, start);
+ start = end = null;
+ pathOpen = false;
+ }
+ break;
+
+ case PathIterator.SEG_LINETO:
+ p = (new LineSegment(x, y, coords[0], coords[1])).
+ getDisplacedSegments(width/2.0);
+ if( !pathOpen )
+ {
+ start = p[0];
+ end = p[1];
+ pathOpen = true;
+ }
+ else
+ addSegments(p);
+
+ x = coords[0];
+ y = coords[1];
+ break;
+
+ case PathIterator.SEG_QUADTO:
+ p = (new QuadSegment(x, y, coords[0], coords[1], coords[2],
+ coords[3])).getDisplacedSegments(width/2.0);
+ if( !pathOpen )
+ {
+ start = p[0];
+ end = p[1];
+ pathOpen = true;
+ }
+ else
+ addSegments(p);
+
+ x = coords[2];
+ y = coords[3];
+ break;
+
+ case PathIterator.SEG_CUBICTO:
+ p = new CubicSegment(x, y, coords[0], coords[1],
+ coords[2], coords[3],
+ coords[4], coords[5]).getDisplacedSegments(width/2.0);
+ if( !pathOpen )
+ {
+ start = p[0];
+ end = p[1];
+ pathOpen = true;
+ }
+ else
+ addSegments(p);
+
+ x = coords[4];
+ y = coords[5];
+ break;
+
+ case PathIterator.SEG_CLOSE:
+ if (x == x0 && y == y0)
+ {
+ joinSegments(new Segment[] { start.first, end.first });
+ }
+ else
+ {
+ p = (new LineSegment(x, y, x0, y0)).getDisplacedSegments(width / 2.0);
+ addSegments(p);
+ }
+ convertPath(output, start);
+ convertPath(output, end);
+ start = end = null;
+ pathOpen = false;
+ output.setWindingRule(GeneralPath.WIND_EVEN_ODD);
+ break;
+ }
+ pi.next();
+ }
+
+ if( pathOpen )
+ {
+ capEnds();
+ convertPath(output, start);
+ }
+ return output;
+ }
+
+ private Shape dashedStroke(PathIterator pi)
+ {
+ // The choice of (flatnessSq == width / 3) is made to be consistent with
+ // the flattening in CubicSegment.getDisplacedSegments
+ FlatteningPathIterator flat = new FlatteningPathIterator(pi,
+ Math.sqrt(width / 3));
+
+ // Holds the endpoint of the current segment (or piece of a segment)
+ double[] coords = new double[2];
+
+ // Holds end of the last segment
+ double x, y, x0, y0;
+ x = x0 = y = y0 = 0;
+
+ // Various useful flags
+ boolean pathOpen = false;
+ boolean dashOn = true;
+ boolean offsetting = (phase != 0);
+
+ // How far we are into the current dash
+ double distance = 0;
+ int dashIndex = 0;
+
+ // And variables to hold the final output
+ GeneralPath output = new GeneralPath();
+ Segment[] p;
+
+ // Iterate over the FlatteningPathIterator
+ while (! flat.isDone())
+ {
+ switch (flat.currentSegment(coords))
+ {
+ case PathIterator.SEG_MOVETO:
+ x0 = x = coords[0];
+ y0 = y = coords[1];
+
+ if (pathOpen)
+ {
+ capEnds();
+ convertPath(output, start);
+ start = end = null;
+ pathOpen = false;
+ }
+
+ break;
+
+ case PathIterator.SEG_LINETO:
+ boolean segmentConsumed = false;
+
+ while (! segmentConsumed)
+ {
+ // Find the total remaining length of this segment
+ double segLength = Math.sqrt((x - coords[0]) * (x - coords[0])
+ + (y - coords[1])
+ * (y - coords[1]));
+ boolean spanBoundary = true;
+ double[] segmentEnd = null;
+
+ // The current segment fits entirely inside the current dash
+ if ((offsetting && distance + segLength <= phase)
+ || distance + segLength <= dash[dashIndex])
+ {
+ spanBoundary = false;
+ }
+
+ // Otherwise, we need to split the segment in two, as this
+ // segment spans a dash boundry
+ else
+ {
+ segmentEnd = (double[]) coords.clone();
+
+ // Calculate the remaining distance in this dash,
+ // and coordinates of the dash boundary
+ double reqLength;
+ if (offsetting)
+ reqLength = phase - distance;
+ else
+ reqLength = dash[dashIndex] - distance;
+
+ coords[0] = x + ((coords[0] - x) * reqLength / segLength);
+ coords[1] = y + ((coords[1] - y) * reqLength / segLength);
+ }
+
+ if (offsetting || ! dashOn)
+ {
+ // Dash is off, or we are in offset - treat this as a
+ // moveTo
+ x0 = x = coords[0];
+ y0 = y = coords[1];
+
+ if (pathOpen)
+ {
+ capEnds();
+ convertPath(output, start);
+ start = end = null;
+ pathOpen = false;
+ }
+ }
+ else
+ {
+ // Dash is on - treat this as a lineTo
+ p = (new LineSegment(x, y, coords[0], coords[1])).getDisplacedSegments(width / 2.0);
+
+ if (! pathOpen)
+ {
+ start = p[0];
+ end = p[1];
+ pathOpen = true;
+ }
+ else
+ addSegments(p);
+
+ x = coords[0];
+ y = coords[1];
+ }
+
+ // Update variables depending on whether we spanned a
+ // dash boundary or not
+ if (! spanBoundary)
+ {
+ distance += segLength;
+ segmentConsumed = true;
+ }
+ else
+ {
+ if (offsetting)
+ offsetting = false;
+ dashOn = ! dashOn;
+ distance = 0;
+ coords = segmentEnd;
+
+ if (dashIndex + 1 == dash.length)
+ dashIndex = 0;
+ else
+ dashIndex++;
+
+ // Since the value of segmentConsumed is still false,
+ // the next run of the while loop will complete the segment
+ }
+ }
+ break;
+
+ // This is a flattened path, so we don't need to deal with curves
+ }
+ flat.next();
+ }
+
+ if (pathOpen)
+ {
+ capEnds();
+ convertPath(output, start);
+ }
+ return output;
+ }
+
+ /**
+ * Cap the ends of the path (joining the start and end list of segments)
+ */
+ private void capEnds()
+ {
+ Segment returnPath = end.last;
+
+ end.reverseAll(); // reverse the path.
+ end = null;
+ capEnd(start, returnPath);
+ start.last = returnPath.last;
+ end = null;
+
+ capEnd(start, start);
+ }
+
+ /**
+ * Append the Segments in s to the GeneralPath p
+ */
+ private void convertPath(GeneralPath p, Segment s)
+ {
+ Segment v = s;
+ p.moveTo((float)s.P1.getX(), (float)s.P1.getY());
+
+ do
+ {
+ if(v instanceof LineSegment)
+ p.lineTo((float)v.P2.getX(), (float)v.P2.getY());
+ else if(v instanceof QuadSegment)
+ p.quadTo((float)((QuadSegment)v).cp.getX(),
+ (float)((QuadSegment)v).cp.getY(),
+ (float)v.P2.getX(),
+ (float)v.P2.getY());
+ else if(v instanceof CubicSegment)
+ p.curveTo((float)((CubicSegment)v).cp1.getX(),
+ (float)((CubicSegment)v).cp1.getY(),
+ (float)((CubicSegment)v).cp2.getX(),
+ (float)((CubicSegment)v).cp2.getY(),
+ (float)v.P2.getX(),
+ (float)v.P2.getY());
+ v = v.next;
+ } while(v != s && v != null);
+
+ p.closePath();
+ }
+
+ /**
+ * Add the segments to start and end (the inner and outer edges of the stroke)
+ */
+ private void addSegments(Segment[] segments)
+ {
+ joinSegments(segments);
+ start.add(segments[0]);
+ end.add(segments[1]);
+ }
+
+ private void joinSegments(Segment[] segments)
+ {
+ double[] p0 = start.last.cp2();
+ double[] p1 = new double[]{start.last.P2.getX(), start.last.P2.getY()};
+ double[] p2 = new double[]{segments[0].first.P1.getX(), segments[0].first.P1.getY()};
+ double[] p3 = segments[0].cp1();
+ Point2D p;
+
+ p = lineIntersection(p0[0],p0[1],p1[0],p1[1],
+ p2[0],p2[1],p3[0],p3[1], false);
+
+ double det = (p1[0] - p0[0])*(p3[1] - p2[1]) -
+ (p3[0] - p2[0])*(p1[1] - p0[1]);
+
+ if( det > 0 )
+ {
+ // start and segment[0] form the 'inner' part of a join,
+ // connect the overlapping segments
+ joinInnerSegments(start, segments[0], p);
+ joinOuterSegments(end, segments[1], p);
+ }
+ else
+ {
+ // end and segment[1] form the 'inner' part
+ joinInnerSegments(end, segments[1], p);
+ joinOuterSegments(start, segments[0], p);
+ }
+ }
+
+ /**
+ * Make a cap between a and b segments,
+ * where a-->b is the direction of iteration.
+ */
+ private void capEnd(Segment a, Segment b)
+ {
+ double[] p0, p1;
+ double dx, dy, l;
+ Point2D c1,c2;
+
+ switch( cap )
+ {
+ case CAP_BUTT:
+ a.add(new LineSegment(a.last.P2, b.P1));
+ break;
+
+ case CAP_SQUARE:
+ p0 = a.last.cp2();
+ p1 = new double[]{a.last.P2.getX(), a.last.P2.getY()};
+ dx = p1[0] - p0[0];
+ dy = p1[1] - p0[1];
+ l = Math.sqrt(dx * dx + dy * dy);
+ dx = 0.5*width*dx/l;
+ dy = 0.5*width*dy/l;
+ c1 = new Point2D.Double(p1[0] + dx, p1[1] + dy);
+ c2 = new Point2D.Double(b.P1.getX() + dx, b.P1.getY() + dy);
+ a.add(new LineSegment(a.last.P2, c1));
+ a.add(new LineSegment(c1, c2));
+ a.add(new LineSegment(c2, b.P1));
+ break;
+
+ case CAP_ROUND:
+ p0 = a.last.cp2();
+ p1 = new double[]{a.last.P2.getX(), a.last.P2.getY()};
+ dx = p1[0] - p0[0];
+ dy = p1[1] - p0[1];
+ if (dx != 0 && dy != 0)
+ {
+ l = Math.sqrt(dx * dx + dy * dy);
+ dx = (2.0/3.0)*width*dx/l;
+ dy = (2.0/3.0)*width*dy/l;
+ }
+
+ c1 = new Point2D.Double(p1[0] + dx, p1[1] + dy);
+ c2 = new Point2D.Double(b.P1.getX() + dx, b.P1.getY() + dy);
+ a.add(new CubicSegment(a.last.P2, c1, c2, b.P1));
+ break;
+ }
+ a.add(b);
+ }
+
+ /**
+ * Returns the intersection of two lines, or null if there isn't one.
+ * @param infinite - true if the lines should be regarded as infinite, false
+ * if the intersection must be within the given segments.
+ * @return a Point2D or null.
+ */
+ private Point2D lineIntersection(double X1, double Y1,
+ double X2, double Y2,
+ double X3, double Y3,
+ double X4, double Y4,
+ boolean infinite)
+ {
+ double x1 = X1;
+ double y1 = Y1;
+ double rx = X2 - x1;
+ double ry = Y2 - y1;
+
+ double x2 = X3;
+ double y2 = Y3;
+ double sx = X4 - x2;
+ double sy = Y4 - y2;
+
+ double determinant = sx * ry - sy * rx;
+ double nom = (sx * (y2 - y1) + sy * (x1 - x2));
+
+ // lines can be considered parallel.
+ if (Math.abs(determinant) < 1E-6)
+ return null;
+
+ nom = nom / determinant;
+
+ // check if lines are within the bounds
+ if(!infinite && (nom > 1.0 || nom < 0.0))
+ return null;
+
+ return new Point2D.Double(x1 + nom * rx, y1 + nom * ry);
+ }
+
+ /**
+ * Join a and b segments, where a-->b is the direction of iteration.
+ *
+ * insideP is the inside intersection point of the join, needed for
+ * calculating miter lengths.
+ */
+ private void joinOuterSegments(Segment a, Segment b, Point2D insideP)
+ {
+ double[] p0, p1;
+ double dx, dy, l;
+ Point2D c1,c2;
+
+ switch( join )
+ {
+ case JOIN_MITER:
+ p0 = a.last.cp2();
+ p1 = new double[]{a.last.P2.getX(), a.last.P2.getY()};
+ double[] p2 = new double[]{b.P1.getX(), b.P1.getY()};
+ double[] p3 = b.cp1();
+ Point2D p = lineIntersection(p0[0],p0[1],p1[0],p1[1],p2[0],p2[1],p3[0],p3[1], true);
+ if( p == null || insideP == null )
+ a.add(new LineSegment(a.last.P2, b.P1));
+ else if((p.distance(insideP)/width) < limit)
+ {
+ a.add(new LineSegment(a.last.P2, p));
+ a.add(new LineSegment(p, b.P1));
+ }
+ else
+ {
+ // outside miter limit, do a bevel join.
+ a.add(new LineSegment(a.last.P2, b.P1));
+ }
+ break;
+
+ case JOIN_ROUND:
+ p0 = a.last.cp2();
+ p1 = new double[]{a.last.P2.getX(), a.last.P2.getY()};
+ dx = p1[0] - p0[0];
+ dy = p1[1] - p0[1];
+ l = Math.sqrt(dx * dx + dy * dy);
+ dx = 0.5*width*dx/l;
+ dy = 0.5*width*dy/l;
+ c1 = new Point2D.Double(p1[0] + dx, p1[1] + dy);
+
+ p0 = new double[]{b.P1.getX(), b.P1.getY()};
+ p1 = b.cp1();
+
+ dx = p0[0] - p1[0]; // backwards direction.
+ dy = p0[1] - p1[1];
+ l = Math.sqrt(dx * dx + dy * dy);
+ dx = 0.5*width*dx/l;
+ dy = 0.5*width*dy/l;
+ c2 = new Point2D.Double(p0[0] + dx, p0[1] + dy);
+ a.add(new CubicSegment(a.last.P2, c1, c2, b.P1));
+ break;
+
+ case JOIN_BEVEL:
+ a.add(new LineSegment(a.last.P2, b.P1));
+ break;
+ }
+ }
+
+ /**
+ * Join a and b segments, removing any overlap
+ */
+ private void joinInnerSegments(Segment a, Segment b, Point2D p)
+ {
+ double[] p0 = a.last.cp2();
+ double[] p1 = new double[] { a.last.P2.getX(), a.last.P2.getY() };
+ double[] p2 = new double[] { b.P1.getX(), b.P1.getY() };
+ double[] p3 = b.cp1();
+
+ if (p == null)
+ {
+ // Dodgy.
+ a.add(new LineSegment(a.last.P2, b.P1));
+ p = new Point2D.Double((b.P1.getX() + a.last.P2.getX()) / 2.0,
+ (b.P1.getY() + a.last.P2.getY()) / 2.0);
+ }
+ else
+ // This assumes segments a and b are single segments, which is
+ // incorrect - if they are a linked list of segments (ie, passed in
+ // from a flattening operation), this produces strange results!!
+ a.last.P2 = b.P1 = p;
+ }
+}
diff --git a/libjava/classpath/java/awt/BorderLayout.java b/libjava/classpath/java/awt/BorderLayout.java
new file mode 100644
index 000000000..c06eb834b
--- /dev/null
+++ b/libjava/classpath/java/awt/BorderLayout.java
@@ -0,0 +1,742 @@
+/* BorderLayout.java -- A layout manager class
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+
+/**
+ * This class implements a layout manager that positions components
+ * in certain sectors of the parent container.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public class BorderLayout implements LayoutManager2, java.io.Serializable
+{
+
+ /**
+ * Constant indicating the top of the container
+ */
+ public static final String NORTH = "North";
+
+ /**
+ * Constant indicating the bottom of the container
+ */
+ public static final String SOUTH = "South";
+
+ /**
+ * Constant indicating the right side of the container
+ */
+ public static final String EAST = "East";
+
+ /**
+ * Constant indicating the left side of the container
+ */
+ public static final String WEST = "West";
+
+ /**
+ * Constant indicating the center of the container
+ */
+ public static final String CENTER = "Center";
+
+
+ /**
+ * The constant indicating the position before the first line of the
+ * layout. The exact position depends on the writing system: For a
+ * top-to-bottom orientation, it is the same as {@link #NORTH}, for
+ * a bottom-to-top orientation, it is the same as {@link #SOUTH}.
+ *
+ * <p>This constant is an older name for {@link #PAGE_START} which
+ * has exactly the same value.
+ *
+ * @since 1.2
+ */
+ public static final String BEFORE_FIRST_LINE = "First";
+
+ /**
+ * The constant indicating the position after the last line of the
+ * layout. The exact position depends on the writing system: For a
+ * top-to-bottom orientation, it is the same as {@link #SOUTH}, for
+ * a bottom-to-top orientation, it is the same as {@link #NORTH}.
+ *
+ * <p>This constant is an older name for {@link #PAGE_END} which
+ * has exactly the same value.
+ *
+ * @since 1.2
+ */
+ public static final String AFTER_LAST_LINE = "Last";
+
+ /**
+ * The constant indicating the position before the first item of the
+ * layout. The exact position depends on the writing system: For a
+ * left-to-right orientation, it is the same as {@link #WEST}, for
+ * a right-to-left orientation, it is the same as {@link #EAST}.
+ *
+ * <p>This constant is an older name for {@link #LINE_START} which
+ * has exactly the same value.
+ *
+ * @since 1.2
+ */
+ public static final String BEFORE_LINE_BEGINS = "Before";
+
+ /**
+ * The constant indicating the position after the last item of the
+ * layout. The exact position depends on the writing system: For a
+ * left-to-right orientation, it is the same as {@link #EAST}, for
+ * a right-to-left orientation, it is the same as {@link #WEST}.
+ *
+ * <p>This constant is an older name for {@link #LINE_END} which
+ * has exactly the same value.
+ *
+ * @since 1.2
+ */
+ public static final String AFTER_LINE_ENDS = "After";
+
+ /**
+ * The constant indicating the position before the first line of the
+ * layout. The exact position depends on the writing system: For a
+ * top-to-bottom orientation, it is the same as {@link #NORTH}, for
+ * a bottom-to-top orientation, it is the same as {@link #SOUTH}.
+ *
+ * @since 1.4
+ */
+ public static final String PAGE_START = BEFORE_FIRST_LINE;
+
+ /**
+ * The constant indicating the position after the last line of the
+ * layout. The exact position depends on the writing system: For a
+ * top-to-bottom orientation, it is the same as {@link #SOUTH}, for
+ * a bottom-to-top orientation, it is the same as {@link #NORTH}.
+ *
+ * @since 1.4
+ */
+ public static final String PAGE_END = AFTER_LAST_LINE;
+
+ /**
+ * The constant indicating the position before the first item of the
+ * layout. The exact position depends on the writing system: For a
+ * left-to-right orientation, it is the same as {@link #WEST}, for
+ * a right-to-left orientation, it is the same as {@link #EAST}.
+ *
+ * @since 1.4
+ */
+ public static final String LINE_START = BEFORE_LINE_BEGINS;
+
+ /**
+ * The constant indicating the position after the last item of the
+ * layout. The exact position depends on the writing system: For a
+ * left-to-right orientation, it is the same as {@link #EAST}, for
+ * a right-to-left orientation, it is the same as {@link #WEST}.
+ *
+ * @since 1.4
+ */
+ public static final String LINE_END = AFTER_LINE_ENDS;
+
+
+ /**
+ * Serialization constant.
+ */
+ private static final long serialVersionUID = -8658291919501921765L;
+
+
+ /**
+ * @serial
+ */
+ private Component north;
+
+ /**
+ * @serial
+ */
+ private Component south;
+
+ /**
+ * @serial
+ */
+ private Component east;
+
+ /**
+ * @serial
+ */
+ private Component west;
+
+ /**
+ * @serial
+ */
+ private Component center;
+
+ /**
+ * @serial
+ */
+ private Component firstLine;
+
+ /**
+ * @serial
+ */
+ private Component lastLine;
+
+ /**
+ * @serial
+ */
+ private Component firstItem;
+
+ /**
+ * @serial
+ */
+ private Component lastItem;
+
+ /**
+ * @serial The horizontal gap between components
+ */
+ private int hgap;
+
+ /**
+ * @serial The vertical gap between components
+ */
+ private int vgap;
+
+
+ // Some constants for use with calcSize().
+ private static final int MIN = 0;
+ private static final int MAX = 1;
+ private static final int PREF = 2;
+
+
+ /**
+ * Initializes a new instance of <code>BorderLayout</code> with no
+ * horiztonal or vertical gaps between components.
+ */
+ public BorderLayout()
+ {
+ this(0,0);
+ }
+
+ /**
+ * Initializes a new instance of <code>BorderLayout</code> with the
+ * specified horiztonal and vertical gaps between components.
+ *
+ * @param hgap The horizontal gap between components.
+ * @param vgap The vertical gap between components.
+ */
+ public BorderLayout(int hgap, int vgap)
+ {
+ this.hgap = hgap;
+ this.vgap = vgap;
+ }
+
+ /**
+ * Returns the horitzontal gap value.
+ *
+ * @return The horitzontal gap value.
+ */
+ public int getHgap()
+ {
+ return(hgap);
+ }
+
+ /**
+ * Sets the horizontal gap to the specified value.
+ *
+ * @param hgap The new horizontal gap.
+ */
+ public void setHgap(int hgap)
+ {
+ this.hgap = hgap;
+ }
+
+ /**
+ * Returns the vertical gap value.
+ *
+ * @return The vertical gap value.
+ */
+ public int getVgap()
+ {
+ return(vgap);
+ }
+
+ /**
+ * Sets the vertical gap to the specified value.
+ *
+ * @param vgap The new vertical gap value.
+ */
+ public void setVgap(int vgap)
+ {
+ this.vgap = vgap;
+ }
+
+ /**
+ * Adds a component to the layout in the specified constraint position,
+ * which must be one of the string constants defined in this class.
+ *
+ * @param component The component to add.
+ * @param constraints The constraint string.
+ *
+ * @exception IllegalArgumentException If the constraint object is not
+ * a string, or is not one of the specified constants in this class.
+ */
+ public void addLayoutComponent(Component component, Object constraints)
+ {
+ if (constraints != null && ! (constraints instanceof String))
+ throw new IllegalArgumentException("Constraint must be a string");
+
+ addLayoutComponent((String) constraints, component);
+ }
+
+ /**
+ * Adds a component to the layout in the specified constraint position,
+ * which must be one of the string constants defined in this class.
+ *
+ * @param constraints The constraint string.
+ * @param component The component to add.
+ *
+ * @exception IllegalArgumentException If the constraint object is not
+ * one of the specified constants in this class.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>addLayoutComponent(Component, Object)</code>.
+ */
+ public void addLayoutComponent(String constraints, Component component)
+ {
+ String str = constraints;
+
+ if (str == null || str.equals(CENTER))
+ center = component;
+ else if (str.equals(NORTH))
+ north = component;
+ else if (str.equals(SOUTH))
+ south = component;
+ else if (str.equals(EAST))
+ east = component;
+ else if (str.equals(WEST))
+ west = component;
+ else if (str.equals(BEFORE_FIRST_LINE))
+ firstLine = component;
+ else if (str.equals(AFTER_LAST_LINE))
+ lastLine = component;
+ else if (str.equals(BEFORE_LINE_BEGINS))
+ firstItem = component;
+ else if (str.equals(AFTER_LINE_ENDS))
+ lastItem = component;
+ else
+ throw new IllegalArgumentException("Constraint value not valid: " + str);
+ }
+
+ /**
+ * Removes the specified component from the layout.
+ *
+ * @param component The component to remove from the layout.
+ */
+ public void removeLayoutComponent(Component component)
+ {
+ if (north == component)
+ north = null;
+ if (south == component)
+ south = null;
+ if (east == component)
+ east = null;
+ if (west == component)
+ west = null;
+ if (center == component)
+ center = null;
+ if (firstItem == component)
+ firstItem = null;
+ if (lastItem == component)
+ lastItem = null;
+ if (firstLine == component)
+ firstLine = null;
+ if (lastLine == component)
+ lastLine = null;
+ }
+
+ /**
+ * Returns the minimum size of the specified container using this layout.
+ *
+ * @param target The container to calculate the minimum size for.
+ *
+ * @return The minimum size of the container
+ */
+ public Dimension minimumLayoutSize(Container target)
+ {
+ return calcSize(target, MIN);
+ }
+
+ /**
+ * Returns the preferred size of the specified container using this layout.
+ *
+ * @param target The container to calculate the preferred size for.
+ *
+ * @return The preferred size of the container
+ */
+ public Dimension preferredLayoutSize(Container target)
+ {
+ return calcSize(target, PREF);
+ }
+
+ /**
+ * Returns the maximum size of the specified container using this layout.
+ *
+ * @param target The container to calculate the maximum size for.
+ *
+ * @return The maximum size of the container
+ */
+ public Dimension maximumLayoutSize(Container target)
+ {
+ return new Dimension (Integer.MAX_VALUE, Integer.MAX_VALUE);
+ }
+
+ /**
+ * Returns the X axis alignment, which is a <code>float</code> indicating
+ * where along the X axis this container wishs to position its layout.
+ * 0 indicates align to the left, 1 indicates align to the right, and 0.5
+ * indicates align to the center.
+ *
+ * @param parent The parent container.
+ *
+ * @return The X alignment value.
+ */
+ public float getLayoutAlignmentX(Container parent)
+ {
+ return 0.5F;
+ }
+
+ /**
+ * Returns the Y axis alignment, which is a <code>float</code> indicating
+ * where along the Y axis this container wishs to position its layout.
+ * 0 indicates align to the top, 1 indicates align to the bottom, and 0.5
+ * indicates align to the center.
+ *
+ * @param parent The parent container.
+ *
+ * @return The Y alignment value.
+ */
+ public float getLayoutAlignmentY(Container parent)
+ {
+ return 0.5F;
+ }
+
+ /**
+ * Instructs this object to discard any layout information it might
+ * have cached.
+ *
+ * @param parent The parent container.
+ */
+ public void invalidateLayout(Container parent)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Lays out the specified container according to the constraints in this
+ * object.
+ *
+ * @param target The container to lay out.
+ */
+ public void layoutContainer(Container target)
+ {
+ synchronized (target.getTreeLock())
+ {
+ Insets i = target.getInsets();
+ int top = i.top;
+ int bottom = target.height - i.bottom;
+ int left = i.left;
+ int right = target.width - i.right;
+
+ boolean left_to_right = target.getComponentOrientation().isLeftToRight();
+
+ Component my_north = north;
+ Component my_east = east;
+ Component my_south = south;
+ Component my_west = west;
+
+ // Note that we currently don't handle vertical layouts.
+ // Neither does JDK 1.3.
+ if (firstLine != null)
+ my_north = firstLine;
+ if (lastLine != null)
+ my_south = lastLine;
+ if (firstItem != null)
+ {
+ if (left_to_right)
+ my_west = firstItem;
+ else
+ my_east = firstItem;
+ }
+ if (lastItem != null)
+ {
+ if (left_to_right)
+ my_east = lastItem;
+ else
+ my_west = lastItem;
+ }
+
+ if (my_north != null)
+ {
+ Dimension n = calcCompSize(my_north, PREF);
+ my_north.setBounds(left, top, right - left, n.height);
+ top += n.height + vgap;
+ }
+
+ if (my_south != null)
+ {
+ Dimension s = calcCompSize(my_south, PREF);
+ my_south.setBounds(left, bottom - s.height, right - left, s.height);
+ bottom -= s.height + vgap;
+ }
+
+ if (my_east != null)
+ {
+ Dimension e = calcCompSize(my_east, PREF);
+ my_east.setBounds(right - e.width, top, e.width, bottom - top);
+ right -= e.width + hgap;
+ }
+
+ if (my_west != null)
+ {
+ Dimension w = calcCompSize(my_west, PREF);
+ my_west.setBounds(left, top, w.width, bottom - top);
+ left += w.width + hgap;
+ }
+
+ if (center != null)
+ center.setBounds(left, top, right - left, bottom - top);
+ }
+ }
+
+ /**
+ * Returns a string representation of this layout manager.
+ *
+ * @return A string representation of this object.
+ */
+ public String toString()
+ {
+ return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + "]";
+ }
+
+ private Dimension calcCompSize(Component comp, int what)
+ {
+ if (comp == null || ! comp.isVisible())
+ return new Dimension(0, 0);
+ if (what == MIN)
+ return comp.getMinimumSize();
+ else if (what == MAX)
+ return comp.getMaximumSize();
+ return comp.getPreferredSize();
+ }
+
+ /**
+ * This is a helper function used to compute the various sizes for this
+ * layout.
+ */
+ private Dimension calcSize(Container target, int what)
+ {
+ synchronized (target.getTreeLock())
+ {
+ Insets ins = target.getInsets();
+
+ ComponentOrientation orient = target.getComponentOrientation ();
+ boolean left_to_right = orient.isLeftToRight ();
+
+ Component my_north = north;
+ Component my_east = east;
+ Component my_south = south;
+ Component my_west = west;
+
+ // Note that we currently don't handle vertical layouts. Neither
+ // does JDK 1.3.
+ if (firstLine != null)
+ my_north = firstLine;
+ if (lastLine != null)
+ my_south = lastLine;
+ if (firstItem != null)
+ {
+ if (left_to_right)
+ my_west = firstItem;
+ else
+ my_east = firstItem;
+ }
+ if (lastItem != null)
+ {
+ if (left_to_right)
+ my_east = lastItem;
+ else
+ my_west = lastItem;
+ }
+
+ Dimension ndim = calcCompSize(my_north, what);
+ Dimension sdim = calcCompSize(my_south, what);
+ Dimension edim = calcCompSize(my_east, what);
+ Dimension wdim = calcCompSize(my_west, what);
+ Dimension cdim = calcCompSize(center, what);
+
+ int width = edim.width + cdim.width + wdim.width + (hgap * 2);
+ // Check for overflow.
+ if (width < edim.width || width < cdim.width || width < cdim.width)
+ width = Integer.MAX_VALUE;
+
+ if (ndim.width > width)
+ width = ndim.width;
+ if (sdim.width > width)
+ width = sdim.width;
+
+ width += (ins.left + ins.right);
+
+ int height = edim.height;
+ if (cdim.height > height)
+ height = cdim.height;
+ if (wdim.height > height)
+ height = wdim.height;
+
+ int addedHeight = height + (ndim.height + sdim.height + (vgap * 2)
+ + ins.top + ins.bottom);
+ // Check for overflow.
+ if (addedHeight < height)
+ height = Integer.MAX_VALUE;
+ else
+ height = addedHeight;
+
+ return(new Dimension(width, height));
+ }
+ }
+
+ /**
+ * Return the component at the indicated location, or null if no component
+ * is at that location. The constraints argument must be one of the
+ * location constants specified by this class.
+ * @param constraints the location
+ * @return the component at that location, or null
+ * @throws IllegalArgumentException if the constraints argument is not
+ * recognized
+ * @since 1.5
+ */
+ public Component getLayoutComponent(Object constraints)
+ {
+ if (constraints == CENTER)
+ return center;
+ if (constraints == NORTH)
+ return north;
+ if (constraints == EAST)
+ return east;
+ if (constraints == SOUTH)
+ return south;
+ if (constraints == WEST)
+ return west;
+ if (constraints == PAGE_START)
+ return firstLine;
+ if (constraints == PAGE_END)
+ return lastLine;
+ if (constraints == LINE_START)
+ return firstItem;
+ if (constraints == LINE_END)
+ return lastItem;
+ throw new IllegalArgumentException("constraint " + constraints
+ + " is not recognized");
+ }
+
+ /**
+ * Return the component at the specified location, which must be one
+ * of the absolute constants such as CENTER or SOUTH. The container's
+ * orientation is used to map this location to the correct corresponding
+ * component, so for instance in a right-to-left container, a request
+ * for the EAST component could return the LINE_END component. This will
+ * return null if no component is available at the given location.
+ * @param container the container whose orientation is used
+ * @param constraints the absolute location of the component
+ * @return the component at the location, or null
+ * @throws IllegalArgumentException if the constraint is not recognized
+ */
+ public Component getLayoutComponent(Container container, Object constraints)
+ {
+ ComponentOrientation orient = container.getComponentOrientation();
+ if (constraints == CENTER)
+ return center;
+ // Note that we don't support vertical layouts.
+ if (constraints == NORTH)
+ return north;
+ if (constraints == SOUTH)
+ return south;
+ if (constraints == WEST)
+ {
+ // Note that relative layout takes precedence.
+ if (orient.isLeftToRight())
+ return firstItem == null ? west : firstItem;
+ return lastItem == null ? west : lastItem;
+ }
+ if (constraints == EAST)
+ {
+ // Note that relative layout takes precedence.
+ if (orient.isLeftToRight())
+ return lastItem == null ? east : lastItem;
+ return firstItem == null ? east : firstItem;
+ }
+ throw new IllegalArgumentException("constraint " + constraints
+ + " is not recognized");
+ }
+
+ /**
+ * Return the constraint corresponding to a component in this layout.
+ * If the component is null, or is not in this layout, returns null.
+ * Otherwise, this will return one of the constraint constants defined
+ * in this class.
+ * @param c the component
+ * @return the constraint, or null
+ * @since 1.5
+ */
+ public Object getConstraints(Component c)
+ {
+ if (c == null)
+ return null;
+ if (c == center)
+ return CENTER;
+ if (c == north)
+ return NORTH;
+ if (c == east)
+ return EAST;
+ if (c == south)
+ return SOUTH;
+ if (c == west)
+ return WEST;
+ if (c == firstLine)
+ return PAGE_START;
+ if (c == lastLine)
+ return PAGE_END;
+ if (c == firstItem)
+ return LINE_START;
+ if (c == lastItem)
+ return LINE_END;
+ return null;
+ }
+}
diff --git a/libjava/classpath/java/awt/BufferCapabilities.java b/libjava/classpath/java/awt/BufferCapabilities.java
new file mode 100644
index 000000000..522fdf7f6
--- /dev/null
+++ b/libjava/classpath/java/awt/BufferCapabilities.java
@@ -0,0 +1,253 @@
+/* BufferCapabilities.java -- double-buffering capabilities descriptor
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.image.BufferStrategy;
+
+/**
+ * A double-buffering capability descriptor. This class exposes
+ * details about the double-buffering algorithms used by image
+ * buffers.
+ *
+ * BufferCapabilities represents algorithms that involve at least two
+ * buffers but it can also specify so-called "multi-buffer" schemes
+ * involving more than two buffers. This class describes the
+ * capabilities of the front and back buffers as well as the results
+ * of "flipping" -- that is, what happens when an image is transferred
+ * from the back buffer to the front buffer.
+ *
+ * Flipping may or may not be supported or may be supported only in
+ * fullscreen mode. If it is not supported then "blitting" is implied
+ * -- that is, the contents of the back buffer are copied using a fast
+ * block transfer operation from the back buffer to the front buffer.
+ *
+ * The front buffer is the one that is displayed.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ *
+ * @see BufferStrategy#getCapabilities()
+ * @see GraphicsConfiguration#getBufferCapabilities()
+ *
+ * @since 1.4
+ */
+public class BufferCapabilities implements Cloneable
+{
+ /**
+ * A type-safe enumeration of buffer flipping results.
+ *
+ * @see AttributeValue
+ */
+ public static final class FlipContents extends AttributeValue
+ {
+ /**
+ * The names of the different flipping results.
+ */
+ private static final String[] NAMES
+ = { "undefined", "background", "prior", "copied" };
+
+ /**
+ * The contents of the back buffer are undefined after flipping.
+ */
+ public static final FlipContents UNDEFINED = new FlipContents(0);
+
+ /**
+ * The back buffer is cleared with the background color after
+ * flipping.
+ */
+ public static final FlipContents BACKGROUND = new FlipContents(1);
+
+ /**
+ * The back buffer contains the pre-flipping contents of the front
+ * buffer after flipping. In other words a true "flip" has been
+ * performed.
+ */
+ public static final FlipContents PRIOR = new FlipContents(2);
+
+ /**
+ * The back buffer has the same contents as the front buffer after
+ * flipping.
+ */
+ public static final FlipContents COPIED = new FlipContents(3);
+
+ /**
+ * Create a new flipping result descriptor.
+ *
+ * @param value the enumeration value
+ */
+ private FlipContents(int value)
+ {
+ super(value, NAMES);
+ }
+ }
+
+ /**
+ * Front buffer capabilities descriptor.
+ */
+ private final ImageCapabilities front;
+
+ /**
+ * Back buffer capabilities descriptor.
+ */
+ private final ImageCapabilities back;
+
+ /**
+ * Describes the results of a "flip" operation.
+ */
+ private final FlipContents flip;
+
+ /**
+ * Creates a buffer capabilities object.
+ *
+ * @param frontCaps front buffer capabilities descriptor
+ * @param backCaps back buffer capabilities descriptor
+ * @param flip the results of a flip operation or null if
+ * flipping is not supported
+ *
+ * @exception IllegalArgumentException if frontCaps or backCaps is
+ * null
+ */
+ public BufferCapabilities(ImageCapabilities frontCaps,
+ ImageCapabilities backCaps,
+ FlipContents flip)
+ {
+ if (frontCaps == null || backCaps == null)
+ throw new IllegalArgumentException();
+ this.front = frontCaps;
+ this.back = backCaps;
+ this.flip = flip;
+ }
+
+ /**
+ * Retrieve the front buffer's image capabilities.
+ *
+ * @return the front buffer's image capabilities
+ */
+ public ImageCapabilities getFrontBufferCapabilities()
+ {
+ return front;
+ }
+
+ /**
+ * Retrieve the back buffer's image capabilities.
+ *
+ * @return the back buffer's image capabilities
+ */
+ public ImageCapabilities getBackBufferCapabilities()
+ {
+ return back;
+ }
+
+ /**
+ * Return whether or not flipping is supported.
+ *
+ * @return true if flipping is supported, false otherwise
+ */
+ public boolean isPageFlipping()
+ {
+ return flip != null;
+ }
+
+ /**
+ * Retrieve the result of a flipping operation. If this method
+ * returns null then flipping is not supported. This implies that
+ * "blitting", a fast block transfer, is used to copy the contents
+ * of the back buffer to the front buffer. Other possible return
+ * values are:
+ * <ul>
+ * <li><code>FlipContents.UNDEFINED</code> the contents of the
+ * back buffer are undefined after flipping.</li>
+ * <li><code>FlipContents.BACKGROUND</code> the contents of the
+ * back buffer are cleared to the background color after
+ * flipping.</li>
+ * <li><code>FlipContents.PRIOR</code> the back buffer contains
+ * the pre-flipping contents of the front * buffer after
+ * flipping.</li>
+ * <li><code>FlipContents.COPIED</code> the back buffer has the
+ * same contents as the front buffer after flipping.</li>
+ * </ul>
+ *
+ * @return the result of a flipping operation or null if flipping is
+ * not supported
+ */
+ public FlipContents getFlipContents()
+ {
+ return flip;
+ }
+
+ /**
+ * Returns true if flipping is only supported in fullscreen mode.
+ *
+ * @return true if flipping is only supported in fullscreen mode,
+ * false otherwise
+ */
+ public boolean isFullScreenRequired()
+ {
+ return true;
+ }
+
+ /**
+ * Returns true if flipping can involve more than two buffers. One
+ * or more intermediate buffers may be available in addition to the
+ * front and back buffers.
+ *
+ * @return true if there are more than two buffers available for
+ * flipping, false otherwise
+ */
+ public boolean isMultiBufferAvailable()
+ {
+ return false;
+ }
+
+ /**
+ * Clone this buffering capability descriptor.
+ *
+ * @return a clone of this buffer capability descriptor
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e);
+ }
+ }
+}
diff --git a/libjava/classpath/java/awt/Button.java b/libjava/classpath/java/awt/Button.java
new file mode 100644
index 000000000..458a45e53
--- /dev/null
+++ b/libjava/classpath/java/awt/Button.java
@@ -0,0 +1,467 @@
+/* Button.java -- AWT button widget
+ Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.peer.ButtonPeer;
+import java.lang.reflect.Array;
+import java.util.EventListener;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleAction;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleValue;
+
+/**
+ * This class provides a button widget for the AWT.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ */
+public class Button extends Component
+ implements java.io.Serializable, Accessible
+{
+
+/*
+ * Static Variables
+ */
+
+// FIXME: Need readObject/writeObject for serialization
+
+// Serialization version constant
+private static final long serialVersionUID = -8774683716313001058L;
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * @serial The action command name for this button.
+ * This is package-private to avoid an accessor method.
+ */
+String actionCommand;
+
+/**
+ * @serial The label for this button.
+ * This is package-private to avoid an accessor method.
+ */
+String label;
+
+// List of ActionListeners for this class.
+private transient ActionListener action_listeners;
+
+ /*
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_button_number;
+
+ protected class AccessibleAWTButton extends AccessibleAWTComponent
+ implements AccessibleAction, AccessibleValue
+ {
+ private static final long serialVersionUID = -5932203980244017102L;
+
+ protected AccessibleAWTButton()
+ {
+ // Do nothing here.
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleAction#getAccessibleActionCount()
+ */
+ public int getAccessibleActionCount()
+ {
+ // Only 1 action possible
+ return 1;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleAction#getAccessibleActionDescription(int)
+ */
+ public String getAccessibleActionDescription(int i)
+ {
+ // JDK 1.4.2 returns the string "click" for action 0. However, the API
+ // docs don't say what the string to be returned is, beyond being a
+ // description of the action. So we return the same thing for
+ // compatibility with 1.4.2.
+ if (i == 0)
+ return "click";
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleAction#doAccessibleAction(int)
+ */
+ public boolean doAccessibleAction(int i)
+ {
+ if (i != 0)
+ return false;
+ processActionEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, actionCommand));
+ return true;
+ }
+
+ public String getAccessibleName()
+ {
+ return label;
+ }
+
+ public AccessibleAction getAccessibleAction()
+ {
+ return this;
+ }
+
+ public AccessibleValue getAccessibleValue()
+ {
+ return this;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleValue#getCurrentAccessibleValue()
+ */
+ public Number getCurrentAccessibleValue()
+ {
+ // Docs say return 1 if selected, but buttons can't be selected, right?
+ return new Integer(0);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleValue#setCurrentAccessibleValue(java.lang.Number)
+ */
+ public boolean setCurrentAccessibleValue(Number number)
+ {
+ // Since there's no selection with buttons, we're ignoring this.
+ // TODO someone who knows shoulw check this.
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleValue#getMinimumAccessibleValue()
+ */
+ public Number getMinimumAccessibleValue()
+ {
+ return new Integer(0);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleValue#getMaximumAccessibleValue()
+ */
+ public Number getMaximumAccessibleValue()
+ {
+ return new Integer(0);
+ }
+
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.PUSH_BUTTON;
+ }
+ }
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * Initializes a new instance of <code>Button</code> with no label.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true
+ */
+public
+Button()
+{
+ this("");
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>Button</code> with the specified
+ * label. The action command name is also initialized to this value.
+ *
+ * @param label The label to display on the button.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true
+ */
+public
+Button(String label)
+{
+ this.label = label;
+ actionCommand = label;
+
+ if (GraphicsEnvironment.isHeadless ())
+ throw new HeadlessException ();
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * Returns the label for this button.
+ *
+ * @return The label for this button.
+ */
+public String
+getLabel()
+{
+ return(label);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the label for this button to the specified value.
+ *
+ * @param label The new label for this button.
+ */
+public synchronized void
+setLabel(String label)
+{
+ this.label = label;
+ actionCommand = label;
+ if (peer != null)
+ {
+ ButtonPeer bp = (ButtonPeer) peer;
+ bp.setLabel (label);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the action command name for this button.
+ *
+ * @return The action command name for this button.
+ */
+public String
+getActionCommand()
+{
+ return(actionCommand);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the action command name for this button to the specified value.
+ *
+ * @param actionCommand The new action command name.
+ */
+public void
+setActionCommand(String actionCommand)
+{
+ this.actionCommand = actionCommand == null ? label : actionCommand;
+}
+
+/*************************************************************************/
+
+/**
+ * Adds a new entry to the list of listeners that will receive
+ * action events from this button.
+ *
+ * @param listener The listener to add.
+ */
+public synchronized void
+addActionListener(ActionListener listener)
+{
+ action_listeners = AWTEventMulticaster.add(action_listeners, listener);
+}
+
+/*************************************************************************/
+
+/**
+ * Removes the specified listener from the list of listeners that will
+ * receive action events from this button.
+ *
+ * @param listener The listener to remove.
+ */
+public synchronized void
+removeActionListener(ActionListener listener)
+{
+ action_listeners = AWTEventMulticaster.remove(action_listeners, listener);
+}
+
+ /**
+ * Returns all added <code>ActionListener</code> objects.
+ *
+ * @return an array of listeners
+ *
+ * @since 1.4
+ */
+ public synchronized ActionListener[] getActionListeners()
+ {
+ return (ActionListener[])
+ AWTEventMulticaster.getListeners(action_listeners,
+ ActionListener.class);
+ }
+
+/**
+ * Returns all registered EventListers of the given listenerType.
+ * listenerType must be a subclass of EventListener, or a
+ * ClassClassException is thrown.
+ *
+ * @param listenerType the listener type to return
+ *
+ * @return an array of listeners
+ *
+ * @exception ClassCastException If listenerType doesn't specify a class or
+ * interface that implements @see java.util.EventListener.
+ *
+ * @since 1.3
+ */
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
+ {
+ if (listenerType == ActionListener.class)
+ return (T[]) getActionListeners();
+ return (T[]) Array.newInstance(listenerType, 0);
+ }
+
+/*************************************************************************/
+
+/**
+ * Notifies this button that it should create its native peer object.
+ */
+public void
+addNotify()
+{
+ if (peer == null)
+ peer = getToolkit ().createButton (this);
+ super.addNotify();
+}
+
+/*************************************************************************/
+
+/**
+ * Processes an event for this button. If the specified event is an
+ * instance of <code>ActionEvent</code>, then the
+ * <code>processActionEvent()</code> method is called to dispatch it
+ * to any registered listeners. Otherwise, the superclass method
+ * will be invoked. Note that this method will not be called at all
+ * unless <code>ActionEvent</code>'s are enabled. This will be done
+ * implicitly if any listeners are added.
+ *
+ * @param event The event to process.
+ */
+protected void
+processEvent(AWTEvent event)
+{
+ if (event instanceof ActionEvent)
+ processActionEvent((ActionEvent)event);
+ else
+ super.processEvent(event);
+}
+
+/*************************************************************************/
+
+/**
+ * This method dispatches an action event for this button to any
+ * registered listeners.
+ *
+ * @param event The event to process.
+ */
+protected void
+processActionEvent(ActionEvent event)
+{
+ if (action_listeners != null)
+ action_listeners.actionPerformed(event);
+}
+
+void
+dispatchEventImpl(AWTEvent e)
+{
+ if (e.id <= ActionEvent.ACTION_LAST
+ && e.id >= ActionEvent.ACTION_FIRST
+ && (action_listeners != null
+ || (eventMask & AWTEvent.ACTION_EVENT_MASK) != 0))
+ processEvent(e);
+ else
+ super.dispatchEventImpl(e);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a debugging string for this button.
+ *
+ * @return A debugging string for this button.
+ */
+protected String
+paramString()
+{
+ return getName () + "," + getX () + "," + getY () + ","
+ + getWidth () + "x" + getHeight () + ",label=" + getLabel ();
+}
+
+/**
+ * Gets the AccessibleContext associated with this <code>Button</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+public AccessibleContext getAccessibleContext()
+{
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTButton();
+ return accessibleContext;
+}
+
+ /**
+ * Generate a unique name for this button.
+ *
+ * @return A unique name for this button.
+ */
+ String generateName ()
+ {
+ return "button" + getUniqueLong ();
+ }
+
+ private static synchronized long getUniqueLong ()
+ {
+ return next_button_number++;
+ }
+
+} // class Button
diff --git a/libjava/classpath/java/awt/Canvas.java b/libjava/classpath/java/awt/Canvas.java
new file mode 100644
index 000000000..ab7a8e3fa
--- /dev/null
+++ b/libjava/classpath/java/awt/Canvas.java
@@ -0,0 +1,354 @@
+/* Canvas.java --
+ Copyright (C) 1999, 2000, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.image.BufferStrategy;
+import java.awt.peer.ComponentPeer;
+import java.io.Serializable;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+
+/**
+ * The <code>Canvas</code> component provides a blank rectangular
+ * area, which the client application can use for drawing and for
+ * capturing events. By overriding the <code>paint()</code> method,
+ * the canvas can be used for anything from simple line drawings to
+ * full-scale custom components.
+ *
+ * @author Original author unknown
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.0
+ */
+
+public class Canvas
+ extends Component
+ implements Serializable, Accessible
+{
+
+ /**
+ * Compatible with Sun's JDK.
+ */
+ private static final long serialVersionUID = -2284879212465893870L;
+
+ /**
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_canvas_number;
+
+ /**
+ * The buffer strategy associated with this canvas.
+ */
+ transient BufferStrategy bufferStrategy;
+
+ /**
+ * Initializes a new instance of <code>Canvas</code>.
+ */
+ public Canvas()
+ {
+ }
+
+ /**
+ * Initializes a new instance of <code>Canvas</code>
+ * with the supplied graphics configuration.
+ *
+ * @param graphicsConfiguration the graphics configuration to use
+ * for this particular canvas.
+ */
+ public Canvas(GraphicsConfiguration graphicsConfiguration)
+ {
+ this.graphicsConfig = graphicsConfiguration;
+ }
+
+ /**
+ * Creates the native peer for this object.
+ */
+ public void addNotify()
+ {
+ if (peer == null)
+ peer = (ComponentPeer) getToolkit().createCanvas(this);
+ super.addNotify();
+ }
+
+ /**
+ * Repaints the canvas window. This method should be overridden by
+ * a subclass to do something useful, as this method simply paints
+ * the window with the background color.
+ *
+ * @param gfx the <code>Graphics</code> to use for painting
+ */
+ public void paint(Graphics gfx)
+ {
+ /* This implementation doesn't make much sense since the filling
+ of background color is guaranteed for heavyweight components
+ such as this. But there's no need to worry, since paint() is
+ usually overridden anyway. */
+ gfx.setColor(getBackground());
+ Dimension size = getSize();
+ gfx.fillRect(0, 0, size.width, size.height);
+ }
+
+ /**
+ * This class provides accessibility support for the canvas.
+ */
+ protected class AccessibleAWTCanvas
+ extends AccessibleAWTComponent
+ {
+ /**
+ * For compatability with Sun's JDK
+ */
+ private static final long serialVersionUID = -6325592262103146699L;
+
+ /**
+ * Constructor for the accessible canvas.
+ */
+ protected AccessibleAWTCanvas()
+ {
+ }
+
+ /**
+ * Returns the accessible role for the canvas.
+ *
+ * @return an instance of <code>AccessibleRole</code>, describing
+ * the role of the canvas.
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.CANVAS;
+ }
+
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>Canvas</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTCanvas();
+ return accessibleContext;
+ }
+
+ /**
+ * A BltBufferStrategy for canvases.
+ */
+ private class CanvasBltBufferStrategy extends BltBufferStrategy
+ {
+ /**
+ * Creates a block transfer strategy for this canvas.
+ *
+ * @param numBuffers the number of buffers in this strategy
+ * @param accelerated true if the buffer should be accelerated,
+ * false otherwise
+ */
+ CanvasBltBufferStrategy(int numBuffers, boolean accelerated)
+ {
+ super(numBuffers,
+ new BufferCapabilities(new ImageCapabilities(accelerated),
+ new ImageCapabilities(accelerated),
+ BufferCapabilities.FlipContents.COPIED));
+ }
+ }
+
+ /**
+ * A FlipBufferStrategy for canvases.
+ */
+ private class CanvasFlipBufferStrategy extends FlipBufferStrategy
+ {
+ /**
+ * Creates a flip buffer strategy for this canvas.
+ *
+ * @param numBuffers the number of buffers in this strategy
+ *
+ * @throws AWTException if the requested number of buffers is not
+ * supported
+ */
+ CanvasFlipBufferStrategy(int numBuffers)
+ throws AWTException
+ {
+ super(numBuffers,
+ new BufferCapabilities(new ImageCapabilities(true),
+ new ImageCapabilities(true),
+ BufferCapabilities.FlipContents.COPIED));
+ }
+ }
+
+ /**
+ * Creates a buffering strategy that manages how this canvas is
+ * repainted. This method attempts to create the optimum strategy
+ * based on the desired number of buffers. Hardware or software
+ * acceleration may be used.
+ *
+ * createBufferStrategy attempts different levels of optimization,
+ * but guarantees that some strategy with the requested number of
+ * buffers will be created even if it is not optimal. First it
+ * attempts to create a page flipping strategy, then an accelerated
+ * blitting strategy, then an unaccelerated blitting strategy.
+ *
+ * Calling this method causes any existing buffer strategy to be
+ * destroyed.
+ *
+ * @param numBuffers the number of buffers in this strategy
+ *
+ * @throws IllegalArgumentException if requested number of buffers
+ * is less than one
+ * @throws IllegalStateException if this canvas is not displayable
+ *
+ * @since 1.4
+ */
+ public void createBufferStrategy(int numBuffers)
+ {
+ if (numBuffers < 1)
+ throw new IllegalArgumentException("Canvas.createBufferStrategy: number"
+ + " of buffers is less than one");
+
+ if (!isDisplayable())
+ throw new IllegalStateException("Canvas.createBufferStrategy: canvas is"
+ + " not displayable");
+
+ BufferStrategy newStrategy = null;
+
+ // try a flipping strategy
+ try
+ {
+ newStrategy = new CanvasFlipBufferStrategy(numBuffers);
+ }
+ catch (AWTException e)
+ {
+ }
+
+ // fall back to an accelerated blitting strategy
+ if (newStrategy == null)
+ newStrategy = new CanvasBltBufferStrategy(numBuffers, true);
+
+ bufferStrategy = newStrategy;
+ }
+
+ /**
+ * Creates a buffering strategy that manages how this canvas is
+ * repainted. This method attempts to create a strategy based on
+ * the specified capabilities and throws an exception if the
+ * requested strategy is not supported.
+ *
+ * Calling this method causes any existing buffer strategy to be
+ * destroyed.
+ *
+ * @param numBuffers the number of buffers in this strategy
+ * @param caps the requested buffering capabilities
+ *
+ * @throws AWTException if the requested capabilities are not
+ * supported
+ * @throws IllegalArgumentException if requested number of buffers
+ * is less than one or if caps is null
+ *
+ * @since 1.4
+ */
+ public void createBufferStrategy(int numBuffers, BufferCapabilities caps)
+ throws AWTException
+ {
+ if (numBuffers < 1)
+ throw new IllegalArgumentException("Canvas.createBufferStrategy: number"
+ + " of buffers is less than one");
+
+ if (caps == null)
+ throw new IllegalArgumentException("Canvas.createBufferStrategy:"
+ + " capabilities object is null");
+
+ // a flipping strategy was requested
+ if (caps.isPageFlipping())
+ bufferStrategy = new CanvasFlipBufferStrategy(numBuffers);
+ else
+ bufferStrategy = new CanvasBltBufferStrategy(numBuffers, true);
+ }
+
+ /**
+ * Returns the buffer strategy used by the canvas.
+ *
+ * @return the buffer strategy.
+ * @since 1.4
+ */
+ public BufferStrategy getBufferStrategy()
+ {
+ return bufferStrategy;
+ }
+
+ /**
+ * Updates the canvas in response to a request to
+ * <code>repaint()</code> it. The canvas is cleared
+ * with the current background colour, before <code>paint()</code>
+ * is called to add the new contents. Subclasses
+ * which override this method should either call this
+ * method via <code>super.update(graphics)</code> or re-implement
+ * this behaviour, so as to ensure that the canvas is
+ * clear before painting takes place.
+ *
+ * @param graphics the graphics context.
+ */
+ public void update(Graphics graphics)
+ {
+ Dimension size;
+
+ /* Clear the canvas */
+ size = getSize();
+ graphics.clearRect(0, 0, size.width, size.height);
+ /* Call the paint method */
+ paint(graphics);
+ }
+
+ /**
+ * Generate a unique name for this <code>Canvas</code>.
+ *
+ * @return A unique name for this <code>Canvas</code>.
+ */
+ String generateName()
+ {
+ return "canvas" + getUniqueLong();
+ }
+
+ private static synchronized long getUniqueLong()
+ {
+ return next_canvas_number++;
+ }
+}
diff --git a/libjava/classpath/java/awt/CardLayout.java b/libjava/classpath/java/awt/CardLayout.java
new file mode 100644
index 000000000..c36daf482
--- /dev/null
+++ b/libjava/classpath/java/awt/CardLayout.java
@@ -0,0 +1,501 @@
+/* CardLayout.java -- Card-based layout engine
+ Copyright (C) 1999, 2000, 2002, 2003, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.io.Serializable;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+/**
+ * This class implements a card-based layout scheme. Each included
+ * component is treated as a card. Only one card can be shown at a
+ * time. This class includes methods for changing which card is
+ * shown.
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class CardLayout implements LayoutManager2, Serializable
+{
+ private static final long serialVersionUID = -4328196481005934313L;
+
+ /**
+ * Initializes a new instance of <code>CardLayout</code> with horizontal
+ * and vertical gaps of 0.
+ */
+ public CardLayout ()
+ {
+ this (0, 0);
+ }
+
+ /**
+ * Create a new <code>CardLayout</code> object with the specified
+ * horizontal and vertical gaps.
+ *
+ * @param hgap The horizontal gap
+ * @param vgap The vertical gap
+ */
+ public CardLayout (int hgap, int vgap)
+ {
+ this.hgap = hgap;
+ this.vgap = vgap;
+ this.tab = new Hashtable ();
+ }
+
+ /**
+ * Add a new component to the layout. The constraint must be a
+ * string which is used to name the component. This string can
+ * later be used to refer to the particular component.
+ *
+ * @param comp The component to add
+ * @param constraints The name by which the component can later be called
+ *
+ * @exception IllegalArgumentException If `constraints' is not a
+ * <code>String</code>
+ */
+ public void addLayoutComponent (Component comp, Object constraints)
+ {
+ if (! (constraints instanceof String))
+ throw new IllegalArgumentException ("Object " + constraints
+ + " is not a string");
+ addLayoutComponent ((String) constraints, comp);
+ }
+
+ /**
+ * Add a new component to the layout. The name can be used later
+ * to refer to the component.
+ *
+ * @param name The name by which the component can later be called
+ * @param comp The component to add
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>addLayoutComponent(Component, Object)</code>.
+ */
+ public void addLayoutComponent (String name, Component comp)
+ {
+ tab.put (name, comp);
+ // First component added is the default component.
+ comp.setVisible(tab.size() == 1);
+ }
+
+ /**
+ * Cause the first component in the container to be displayed.
+ *
+ * @param parent The parent container, not <code>null</code>.
+ */
+ public void first (Container parent)
+ {
+ gotoComponent (parent, FIRST);
+ }
+
+ /**
+ * Return this layout manager's horizontal gap.
+ *
+ * @return the horizontal gap
+ */
+ public int getHgap ()
+ {
+ return hgap;
+ }
+
+ /**
+ * Return this layout manager's x alignment. This method always
+ * returns Component.CENTER_ALIGNMENT.
+ *
+ * @param parent Container using this layout manager instance
+ *
+ * @return the x-axis alignment
+ */
+ public float getLayoutAlignmentX (Container parent)
+ {
+ return Component.CENTER_ALIGNMENT;
+ }
+
+ /**
+ * Returns this layout manager's y alignment. This method always
+ * returns Component.CENTER_ALIGNMENT.
+ *
+ * @param parent Container using this layout manager instance
+ *
+ * @return the y-axis alignment
+ */
+ public float getLayoutAlignmentY (Container parent)
+ {
+ return Component.CENTER_ALIGNMENT;
+ }
+
+ /**
+ * Return this layout manager's vertical gap.
+ *
+ * @return the vertical gap
+ */
+ public int getVgap ()
+ {
+ return vgap;
+ }
+
+ /**
+ * Invalidate this layout manager's state.
+ */
+ public void invalidateLayout (Container target)
+ {
+ // Do nothing.
+ }
+
+ /**
+ * Cause the last component in the container to be displayed.
+ *
+ * @param parent The parent container, not <code>null</code>.
+ */
+ public void last (Container parent)
+ {
+ gotoComponent (parent, LAST);
+ }
+
+ /**
+ * Lays out the container. This is done by resizing the child components
+ * to be the same size as the parent, less insets and gaps.
+ *
+ * @param parent The parent container.
+ */
+ public void layoutContainer (Container parent)
+ {
+ synchronized (parent.getTreeLock ())
+ {
+ int width = parent.width;
+ int height = parent.height;
+
+ Insets ins = parent.getInsets ();
+
+ int num = parent.ncomponents;
+ Component[] comps = parent.component;
+
+ int x = ins.left + hgap;
+ int y = ins.top + vgap;
+ width = width - 2 * hgap - ins.left - ins.right;
+ height = height - 2 * vgap - ins.top - ins.bottom;
+
+ for (int i = 0; i < num; ++i)
+ comps[i].setBounds (x, y, width, height);
+ }
+ }
+
+ /**
+ * Get the maximum layout size of the container.
+ *
+ * @param target The parent container
+ *
+ * @return the maximum layout size
+ */
+ public Dimension maximumLayoutSize (Container target)
+ {
+ if (target == null || target.ncomponents == 0)
+ return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
+ // The JCL says that this returns Integer.MAX_VALUE for both
+ // dimensions. But that just seems wrong to me.
+ return getSize (target, MAX);
+ }
+
+ /**
+ * Get the minimum layout size of the container.
+ *
+ * @param target The parent container
+ *
+ * @return the minimum layout size
+ */
+ public Dimension minimumLayoutSize (Container target)
+ {
+ return getSize (target, MIN);
+ }
+
+ /**
+ * Cause the next component in the container to be displayed. If
+ * this current card is the last one in the deck, the first
+ * component is displayed.
+ *
+ * @param parent The parent container, not <code>null</code>.
+ */
+ public void next (Container parent)
+ {
+ gotoComponent (parent, NEXT);
+ }
+
+ /**
+ * Get the preferred layout size of the container.
+ *
+ * @param parent The parent container
+ *
+ * @return the preferred layout size
+ */
+ public Dimension preferredLayoutSize (Container parent)
+ {
+ return getSize (parent, PREF);
+ }
+
+ /**
+ * Cause the previous component in the container to be displayed.
+ * If this current card is the first one in the deck, the last
+ * component is displayed.
+ *
+ * @param parent The parent container, not <code>null</code>.
+ */
+ public void previous (Container parent)
+ {
+ gotoComponent (parent, PREV);
+ }
+
+ /**
+ * Remove the indicated component from this layout manager.
+ *
+ * @param comp The component to remove
+ */
+ public void removeLayoutComponent (Component comp)
+ {
+ Enumeration e = tab.keys ();
+ while (e.hasMoreElements ())
+ {
+ Object key = e.nextElement ();
+ if (tab.get (key) == comp)
+ {
+ tab.remove (key);
+ Container parent = comp.getParent();
+ next(parent);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Set this layout manager's horizontal gap.
+ *
+ * @param hgap The new gap
+ */
+ public void setHgap (int hgap)
+ {
+ this.hgap = hgap;
+ }
+
+ /**
+ * Set this layout manager's vertical gap.
+ *
+ * @param vgap The new gap
+ */
+ public void setVgap (int vgap)
+ {
+ this.vgap = vgap;
+ }
+
+ /**
+ * Cause the named component to be shown. If the component name is
+ * unknown or <code>null</code>, this method does nothing.
+ *
+ * @param parent The parent container, not <code>null</code>.
+ * @param name The name of the component to show
+ */
+ public void show (Container parent, String name)
+ {
+ if (name == null)
+ return;
+
+ if (parent.getLayout() != this)
+ throw new IllegalArgumentException("parent's layout is not this CardLayout");
+
+ Object target = tab.get (name);
+ if (target != null)
+ {
+ int num = parent.ncomponents;
+ // This is more efficient than calling getComponents().
+ Component[] comps = parent.component;
+ for (int i = 0; i < num; ++i)
+ {
+ if (comps[i].isVisible())
+ {
+ if (target == comps[i])
+ return;
+ comps[i].setVisible (false);
+ }
+ }
+ ((Component) target).setVisible (true);
+ parent.validate();
+ }
+ }
+
+ /**
+ * Returns a string representation of this layout manager.
+ *
+ * @return A string representation of this object.
+ */
+ public String toString ()
+ {
+ return getClass ().getName () + "[hgap=" + hgap + ",vgap=" + vgap + "]";
+ }
+
+ /**
+ * This implements first(), last(), next(), and previous().
+ *
+ * @param parent The parent container
+ * @param what The type of goto: FIRST, LAST, NEXT or PREV
+ *
+ * @throws IllegalArgumentException if parent has not this
+ * CardLayout set as its layout.
+ */
+ private void gotoComponent (Container parent, int what)
+ {
+ if (parent.getLayout() != this)
+ throw new IllegalArgumentException("parent's layout is not this CardLayout");
+
+ synchronized (parent.getTreeLock ())
+ {
+ int num = parent.ncomponents;
+ // This is more efficient than calling getComponents().
+ Component[] comps = parent.component;
+
+ if (num == 1)
+ {
+ comps[0].setVisible(true);
+ return;
+ }
+
+ int choice = -1;
+
+ if (what == FIRST)
+ choice = 0;
+ else if (what == LAST)
+ choice = num - 1;
+
+ for (int i = 0; i < num; ++i)
+ {
+ if (comps[i].isVisible ())
+ {
+ if (choice == i)
+ {
+ // Do nothing if we're already looking at the right
+ // component.
+ return;
+ }
+ else if (what == PREV)
+ {
+ choice = i - 1;
+ if (choice < 0)
+ choice = num - 1;
+ }
+ else if (what == NEXT)
+ {
+ choice = i + 1;
+ if (choice == num)
+ choice = 0;
+ }
+ comps[i].setVisible (false);
+
+ if (choice >= 0)
+ break;
+ } else
+ {
+ comps[i].setVisible(true);
+ }
+ }
+
+ if (choice >= 0 && choice < num)
+ comps[choice].setVisible (true);
+ }
+ }
+
+ // Compute the size according to WHAT.
+ private Dimension getSize (Container parent, int what)
+ {
+ synchronized (parent.getTreeLock ())
+ {
+ int w = 0, h = 0, num = parent.ncomponents;
+ Component[] comps = parent.component;
+
+ for (int i = 0; i < num; ++i)
+ {
+ Dimension d;
+
+ if (what == MIN)
+ d = comps[i].getMinimumSize ();
+ else if (what == MAX)
+ d = comps[i].getMaximumSize ();
+ else
+ d = comps[i].getPreferredSize ();
+
+ w = Math.max (d.width, w);
+ h = Math.max (d.height, h);
+ }
+
+ Insets i = parent.getInsets ();
+ w += 2 * hgap + i.right + i.left;
+ h += 2 * vgap + i.bottom + i.top;
+
+ // Handle overflow.
+ if (w < 0)
+ w = Integer.MAX_VALUE;
+ if (h < 0)
+ h = Integer.MAX_VALUE;
+
+ return new Dimension (w, h);
+ }
+ }
+
+ /**
+ * @serial Horizontal gap value.
+ */
+ private int hgap;
+
+ /**
+ * @serial Vertical gap value.
+ */
+ private int vgap;
+
+ /**
+ * @serial Table of named components.
+ */
+ private Hashtable tab;
+
+ // These constants are used by the private gotoComponent method.
+ private static final int FIRST = 0;
+ private static final int LAST = 1;
+ private static final int NEXT = 2;
+ private static final int PREV = 3;
+
+ // These constants are used by the private getSize method.
+ private static final int MIN = 0;
+ private static final int MAX = 1;
+ private static final int PREF = 2;
+}
diff --git a/libjava/classpath/java/awt/Checkbox.java b/libjava/classpath/java/awt/Checkbox.java
new file mode 100644
index 000000000..dffb57da3
--- /dev/null
+++ b/libjava/classpath/java/awt/Checkbox.java
@@ -0,0 +1,665 @@
+/* Checkbox.java -- An AWT checkbox widget
+ Copyright (C) 1999, 2000, 2001, 2002, 2005, 2006
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.peer.CheckboxPeer;
+import java.io.Serializable;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleAction;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleState;
+import javax.accessibility.AccessibleStateSet;
+import javax.accessibility.AccessibleValue;
+
+/**
+ * This class implements a component which has an on/off state. Two
+ * or more Checkboxes can be grouped by a CheckboxGroup.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@redhat.com)
+ */
+public class Checkbox extends Component
+ implements ItemSelectable, Accessible, Serializable
+{
+
+// FIXME: Need readObject/writeObject for this.
+
+/*
+ * Static Variables
+ */
+
+// Serialization Constant
+private static final long serialVersionUID = 7270714317450821763L;
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * @serial The checkbox group for this checkbox.
+ */
+private CheckboxGroup group;
+
+/**
+ * @serial The label on this checkbox.
+ */
+private String label;
+
+/**
+ * @serial The state of this checkbox.
+ * This is package-private to avoid an accessor method.
+ */
+boolean state;
+
+// The list of listeners for this object.
+private transient ItemListener item_listeners;
+
+ /*
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_checkbox_number;
+
+/**
+ * This class provides accessibility support for the
+ * checkbox.
+ *
+ * @author Jerry Quinn (jlquinn@optonline.net)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+protected class AccessibleAWTCheckbox
+ extends AccessibleAWTComponent
+ implements ItemListener, AccessibleAction, AccessibleValue
+{
+ /**
+ * Serialization constant to match JDK 1.5
+ */
+ private static final long serialVersionUID = 7881579233144754107L;
+
+ /**
+ * Default constructor which simply calls the
+ * super class for generic component accessibility
+ * handling.
+ */
+ public AccessibleAWTCheckbox()
+ {
+ super();
+ }
+
+ /**
+ * Captures changes to the state of the checkbox and
+ * fires appropriate accessible property change events.
+ *
+ * @param event the event fired.
+ * @see java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent)
+ */
+ public void itemStateChanged(ItemEvent event)
+ {
+ firePropertyChange(ACCESSIBLE_STATE_PROPERTY,
+ state ? null : AccessibleState.CHECKED,
+ state ? AccessibleState.CHECKED : null);
+ }
+
+ /**
+ * Returns an implementation of the <code>AccessibleAction</code>
+ * interface for this accessible object. In this case, the
+ * current instance is simply returned (with a more appropriate
+ * type), as it also implements the accessible action as well as
+ * the context.
+ *
+ * @return the accessible action associated with this context.
+ * @see javax.accessibility.AccessibleAction
+ */
+ public AccessibleAction getAccessibleAction()
+ {
+ return this;
+ }
+
+ /**
+ * Returns an implementation of the <code>AccessibleValue</code>
+ * interface for this accessible object. In this case, the
+ * current instance is simply returned (with a more appropriate
+ * type), as it also implements the accessible value as well as
+ * the context.
+ *
+ * @return the accessible value associated with this context.
+ * @see javax.accessibility.AccessibleValue
+ */
+ public AccessibleValue getAccessibleValue()
+ {
+ return this;
+ }
+
+ /*
+ * The following methods are implemented in the JDK (up to
+ * 1.5) as stubs. We do likewise here.
+ */
+
+ /**
+ * Returns the number of actions associated with this accessible
+ * object. This default implementation returns 0.
+ *
+ * @return the number of accessible actions available.
+ * @see javax.accessibility.AccessibleAction#getAccessibleActionCount()
+ */
+ public int getAccessibleActionCount()
+ {
+ // 1.4.1 and 1.5 do this
+ return 0;
+ }
+
+ /**
+ * Returns a description of the action with the supplied id.
+ * This default implementation always returns null.
+ *
+ * @param i the id of the action whose description should be
+ * retrieved.
+ * @return a <code>String</code> describing the action.
+ * @see javax.accessibility.AccessibleAction#getAccessibleActionDescription(int)
+ */
+ public String getAccessibleActionDescription(int i)
+ {
+ // 1.5 does this
+ return null;
+ }
+
+ /**
+ * Executes the action with the specified id. This
+ * default implementation simply returns false.
+ *
+ * @param i the id of the action to perform.
+ * @return true if the action was performed.
+ * @see javax.accessibility.AccessibleAction#doAccessibleAction(int)
+ */
+ public boolean doAccessibleAction(int i)
+ {
+ // 1.5 does this
+ return false;
+ }
+
+ /**
+ * Returns the current value of this accessible object.
+ * If no value has been set, null is returned. This
+ * default implementation always returns null, regardless.
+ *
+ * @return the numeric value of this object, or null if
+ * no value has been set.
+ * @see javax.accessibility.AccessibleValue#getCurrentAccessibleValue()
+ */
+ public Number getCurrentAccessibleValue()
+ {
+ // 1.5 does this
+ return null;
+ }
+
+ /**
+ * Sets the current value of this accessible object
+ * to that supplied. In this default implementation,
+ * the value is never set and the method always returns
+ * false.
+ *
+ * @param number the new accessible value.
+ * @return true if the value was set.
+ * @see javax.accessibility.AccessibleValue#setCurrentAccessibleValue(java.lang.Number)
+ */
+ public boolean setCurrentAccessibleValue(Number number)
+ {
+ // 1.5 does this
+ return false;
+ }
+
+ /**
+ * Returns the minimum acceptable accessible value used
+ * by this object, or null if no minimum value exists.
+ * This default implementation always returns null.
+ *
+ * @return the minimum acceptable accessible value, or null
+ * if there is no minimum.
+ * @see javax.accessibility.AccessibleValue#getMinimumAccessibleValue()
+ */
+ public Number getMinimumAccessibleValue()
+ {
+ return null;
+ }
+
+ /**
+ * Returns the maximum acceptable accessible value used
+ * by this object, or null if no maximum value exists.
+ * This default implementation always returns null.
+ *
+ * @return the maximum acceptable accessible value, or null
+ * if there is no maximum.
+ * @see javax.accessibility.AccessibleValue#getMaximumAccessibleValue()
+ */
+ public Number getMaximumAccessibleValue()
+ {
+ return null;
+ }
+
+ /**
+ * Returns the role of this accessible object.
+ *
+ * @return the instance of <code>AccessibleRole</code>,
+ * which describes this object.
+ * @see javax.accessibility.AccessibleRole
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.CHECK_BOX;
+ }
+
+ /**
+ * Returns the state set of this accessible object.
+ *
+ * @return a set of <code>AccessibleState</code>s
+ * which represent the current state of the
+ * accessible object.
+ * @see javax.accessibility.AccessibleState
+ * @see javax.accessibility.AccessibleStateSet
+ */
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ AccessibleStateSet set = super.getAccessibleStateSet();
+ if (state)
+ set.add(AccessibleState.CHECKED);
+ return set;
+ }
+
+}
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * Initializes a new instance of <code>Checkbox</code> with no label,
+ * an initial state of off, and that is not part of any checkbox group.
+ */
+public
+Checkbox()
+{
+ this("", false, null);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>Checkbox</code> with the specified
+ * label, an initial state of off, and that is not part of any checkbox
+ * group.
+ *
+ * @param label The label for this checkbox.
+ */
+public
+Checkbox(String label)
+{
+ this(label, false, null);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>Checkbox</code> with the specified
+ * label and initial state, and that is not part of any checkbox
+ * group.
+ *
+ * @param label The label for this checkbox.
+ * @param state The initial state of the checkbox, <code>true</code> for
+ * on, <code>false</code> for off.
+ */
+public
+Checkbox(String label, boolean state)
+{
+ this(label, state, null);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>Checkbox</code> with the specified
+ * label, initial state, and checkbox group.
+ *
+ * @param label The label for this checkbox.
+ * @param group The checkbox group for this box, or <code>null</code>
+ * if there is no checkbox group.
+ * @param state The initial state of the checkbox, <code>true</code> for
+ * on, <code>false</code> for off.
+ */
+public
+Checkbox(String label, CheckboxGroup group, boolean state)
+{
+ this(label, state, group);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>Checkbox</code> with the specified
+ * label, initial state, and checkbox group.
+ *
+ * @param label The label for this checkbox.
+ * @param state The initial state of the checkbox, <code>true</code> for
+ * on, <code>false</code> for off.
+ * @param group The checkbox group for this box, or <code>null</code>
+ * if there is no checkbox group.
+ */
+public
+Checkbox(String label, boolean state, CheckboxGroup group)
+{
+ this.label = label;
+ this.state = state;
+ this.group = group;
+
+ if ( state && group != null )
+ {
+ group.setSelectedCheckbox(this);
+ }
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * Returns the label for this checkbox.
+ *
+ * @return The label for this checkbox.
+ */
+public String
+getLabel()
+{
+ return(label);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the label for this checkbox to the specified value.
+ *
+ * @param label The new checkbox label.
+ */
+public synchronized void
+setLabel(String label)
+{
+ this.label = label;
+ if (peer != null)
+ {
+ CheckboxPeer cp = (CheckboxPeer) peer;
+ cp.setLabel(label);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the state of this checkbox.
+ *
+ * @return The state of this checkbox, which will be <code>true</code> for
+ * on and <code>false</code> for off.
+ */
+public boolean
+getState()
+{
+ return(state);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the state of this checkbox to the specified value.
+ *
+ * @param state The new state of the checkbox, which will be <code>true</code>
+ * for on or <code>false</code> for off.
+ */
+public synchronized void
+setState(boolean state)
+{
+ if (this.state != state)
+ {
+ this.state = state;
+ if (peer != null)
+ {
+ CheckboxPeer cp = (CheckboxPeer) peer;
+ cp.setState (state);
+ }
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Returns an array of length one containing the checkbox label if this
+ * checkbox is selected. Otherwise <code>null</code> is returned.
+ *
+ * @return The selection state of this checkbox.
+ */
+public Object[]
+getSelectedObjects()
+{
+ if (state == false)
+ return(null);
+
+ Object[] objs = new Object[1];
+ objs[0] = label;
+
+ return(objs);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the checkbox group this object is a member of, if any.
+ *
+ * @return This object's checkbox group, of <code>null</code> if it is
+ * not a member of any group.
+ */
+public CheckboxGroup
+getCheckboxGroup()
+{
+ return(group);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets this object's checkbox group to the specified group.
+ *
+ * @param group The new checkbox group, or <code>null</code> to make this
+ * object part of no checkbox group.
+ */
+public synchronized void
+setCheckboxGroup(CheckboxGroup group)
+{
+ this.group = group;
+ if (peer != null)
+ {
+ CheckboxPeer cp = (CheckboxPeer) peer;
+ cp.setCheckboxGroup (group);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Creates this object's native peer.
+ */
+public void
+addNotify()
+{
+ if (peer == null)
+ peer = getToolkit ().createCheckbox (this);
+ super.addNotify ();
+}
+
+ public ItemListener[] getItemListeners ()
+ {
+ return (ItemListener[])
+ AWTEventMulticaster.getListeners (item_listeners, ItemListener.class);
+ }
+
+/**
+ * Adds a new listeners to the list of registered listeners for this object.
+ *
+ * @param listener The new listener to add.
+ */
+public synchronized void
+addItemListener(ItemListener listener)
+{
+ item_listeners = AWTEventMulticaster.add(item_listeners, listener);
+}
+
+/*************************************************************************/
+
+/**
+ * Removes a listener from the list of registered listeners for this object.
+ *
+ * @param listener The listener to remove.
+ */
+public synchronized void
+removeItemListener(ItemListener listener)
+{
+ item_listeners = AWTEventMulticaster.remove(item_listeners, listener);
+}
+
+/*************************************************************************/
+
+/**
+ * Processes this event by calling <code>processItemEvent()</code> if it
+ * is any instance of <code>ItemEvent</code>. Otherwise it is passed to
+ * the superclass for processing.
+ *
+ * @param event The event to process.
+ */
+protected void
+processEvent(AWTEvent event)
+{
+ if (event instanceof ItemEvent)
+ processItemEvent((ItemEvent)event);
+ else
+ super.processEvent(event);
+}
+
+/*************************************************************************/
+
+/**
+ * Processes this event by dispatching it to any registered listeners.
+ *
+ * @param event The <code>ItemEvent</code> to process.
+ */
+protected void
+processItemEvent(ItemEvent event)
+{
+ if (item_listeners != null)
+ item_listeners.itemStateChanged(event);
+}
+
+void
+dispatchEventImpl(AWTEvent e)
+{
+ if (e.id <= ItemEvent.ITEM_LAST
+ && e.id >= ItemEvent.ITEM_FIRST)
+ {
+ ItemEvent ie = (ItemEvent) e;
+ int itemState = ie.getStateChange();
+ setState(itemState == ItemEvent.SELECTED ? true : false);
+ if (item_listeners != null
+ || (eventMask & AWTEvent.ITEM_EVENT_MASK) != 0)
+ processEvent(e);
+ }
+ else
+ super.dispatchEventImpl(e);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a debugging string for this object.
+ */
+protected String
+paramString()
+{
+ // Note: We cannot add the checkbox group information here because this
+ // would trigger infinite recursion when CheckboxGroup.toString() is
+ // called and the box is in its selected state.
+ return ("label=" + label + ",state=" + state + "," + super.paramString());
+}
+
+/**
+ * Gets the AccessibleContext associated with this <code>Checkbox</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+public AccessibleContext getAccessibleContext()
+{
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ {
+ AccessibleAWTCheckbox ac = new AccessibleAWTCheckbox();
+ accessibleContext = ac;
+ addItemListener(ac);
+ }
+ return accessibleContext;
+}
+
+ /**
+ * Generate a unique name for this checkbox.
+ *
+ * @return A unique name for this checkbox.
+ */
+ String generateName()
+ {
+ return "checkbox" + getUniqueLong();
+ }
+
+ private static synchronized long getUniqueLong()
+ {
+ return next_checkbox_number++;
+ }
+}
diff --git a/libjava/classpath/java/awt/CheckboxGroup.java b/libjava/classpath/java/awt/CheckboxGroup.java
new file mode 100644
index 000000000..30f3e1635
--- /dev/null
+++ b/libjava/classpath/java/awt/CheckboxGroup.java
@@ -0,0 +1,172 @@
+/* CheckboxGroup.java -- A grouping class for checkboxes.
+ Copyright (C) 1999, 2000, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This class if for combining checkboxes into groups so that only
+ * one checkbox in the group can be selected at any one time.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@redhat.com)
+ */
+public class CheckboxGroup implements java.io.Serializable
+{
+
+/*
+ * Static Variables
+ */
+
+// Serialization constant
+private static final long serialVersionUID = 3729780091441768983L;
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * @serial The currently selected checkbox.
+ */
+private Checkbox selectedCheckbox;
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * Initializes a new instance of <code>CheckboxGroup</code>.
+ */
+public
+CheckboxGroup()
+{
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Methods
+ */
+
+/**
+ * Returns the currently selected checkbox, or <code>null</code> if none
+ * of the checkboxes in this group are selected.
+ *
+ * @return The selected checkbox.
+ */
+public Checkbox
+getSelectedCheckbox()
+{
+ return getCurrent ();
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the currently selected checkbox, or <code>null</code> if none
+ * of the checkboxes in this group are selected.
+ *
+ * @return The selected checkbox.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getSelectedCheckbox()</code>.
+ */
+public Checkbox
+getCurrent()
+{
+ return(selectedCheckbox);
+}
+
+/*************************************************************************/
+
+/**
+ * This method sets the specified checkbox to be the selected on in this
+ * group, and unsets all others.
+ *
+ * @param selectedCheckbox The new selected checkbox.
+ */
+public void
+setSelectedCheckbox(Checkbox selectedCheckbox)
+{
+ setCurrent (selectedCheckbox);
+}
+
+/*************************************************************************/
+
+/**
+ * This method sets the specified checkbox to be the selected on in this
+ * group, and unsets all others.
+ *
+ * @param selectedCheckbox The new selected checkbox.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>setSelectedCheckbox()</code>.
+ */
+public void
+setCurrent(Checkbox selectedCheckbox)
+{
+ if (this.selectedCheckbox != null)
+ {
+ if (this.selectedCheckbox.getCheckboxGroup() != this)
+ return;
+
+ this.selectedCheckbox.setState(false);
+ }
+
+ this.selectedCheckbox = selectedCheckbox;
+ if (selectedCheckbox != null)
+ selectedCheckbox.setState(true);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a string representation of this checkbox group.
+ *
+ * @return A string representation of this checkbox group.
+ */
+public String
+toString()
+{
+ return(getClass().getName() + "[selectedCheckbox=" + selectedCheckbox + "]");
+}
+
+} // class CheckboxGroup
diff --git a/libjava/classpath/java/awt/CheckboxMenuItem.java b/libjava/classpath/java/awt/CheckboxMenuItem.java
new file mode 100644
index 000000000..597e1964b
--- /dev/null
+++ b/libjava/classpath/java/awt/CheckboxMenuItem.java
@@ -0,0 +1,376 @@
+/* CheckboxMenuItem.java -- A menu option with a checkbox on it.
+ Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.peer.CheckboxMenuItemPeer;
+import java.util.EventListener;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleAction;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleValue;
+
+/**
+ * This class implements a menu item that has a checkbox on it indicating
+ * the selected state of some option.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@redhat.com)
+ */
+public class CheckboxMenuItem extends MenuItem
+ implements ItemSelectable, Accessible
+{
+
+/*
+ * Static Variables
+ */
+
+/**
+ * The number used to generate the name returned by getName.
+ */
+private static transient long next_chkmenuitem_number;
+
+// Serialization constant
+private static final long serialVersionUID = 6190621106981774043L;
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * @serial The state of the checkbox, with <code>true</code> being on and
+ * <code>false</code> being off.
+ */
+private boolean state;
+
+// List of registered ItemListeners
+private transient ItemListener item_listeners;
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * Initializes a new instance of <code>CheckboxMenuItem</code> with no
+ * label and an initial state of off.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true.
+ */
+public
+CheckboxMenuItem()
+{
+ this("", false);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>CheckboxMenuItem</code> with the
+ * specified label and an initial state of off.
+ *
+ * @param label The label of the menu item.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true.
+ */
+public
+CheckboxMenuItem(String label)
+{
+ this(label, false);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>CheckboxMenuItem</code> with the
+ * specified label and initial state.
+ *
+ * @param label The label of the menu item.
+ * @param state The initial state of the menu item, where <code>true</code>
+ * is on, and <code>false</code> is off.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true.
+ */
+public
+CheckboxMenuItem(String label, boolean state)
+{
+ super(label);
+ this.state = state;
+
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException ();
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Methods
+ */
+
+/**
+ * Returns the state of this menu item.
+ *
+ * @return The state of this menu item.
+ */
+public boolean
+getState()
+{
+ return(state);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the state of this menu item.
+ *
+ * @param state The initial state of the menu item, where <code>true</code>
+ * is on, and <code>false</code> is off.
+ */
+public synchronized void
+setState(boolean state)
+{
+ this.state = state;
+ if (peer != null)
+ {
+ CheckboxMenuItemPeer cp = (CheckboxMenuItemPeer) peer;
+ cp.setState (state);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Returns an array of length 1 with the menu item label for this object
+ * if the state is on. Otherwise <code>null</code> is returned.
+ *
+ * @return An array with this menu item's label if it has a state of on,
+ * or <code>null</code> otherwise.
+ */
+public Object[]
+getSelectedObjects()
+{
+ if (state == false)
+ return(null);
+
+ Object[] obj = new Object[1];
+ obj[0] = getLabel();
+
+ return(obj);
+}
+
+/*************************************************************************/
+
+/**
+ * Create's this object's native peer
+ */
+public synchronized void
+addNotify()
+{
+ if (peer == null)
+ peer = getToolkit().createCheckboxMenuItem(this);
+
+ super.addNotify ();
+}
+
+/*************************************************************************/
+
+/**
+ * Adds the specified listener to the list of registered item listeners
+ * for this object.
+ *
+ * @param listener The listener to add.
+ */
+public synchronized void
+addItemListener(ItemListener listener)
+{
+ item_listeners = AWTEventMulticaster.add(item_listeners, listener);
+
+ enableEvents(AWTEvent.ITEM_EVENT_MASK);
+}
+
+/*************************************************************************/
+
+/**
+ * Removes the specified listener from the list of registered item
+ * listeners for this object.
+ *
+ * @param listener The listener to remove.
+ */
+public synchronized void
+removeItemListener(ItemListener listener)
+{
+ item_listeners = AWTEventMulticaster.remove(item_listeners, listener);
+}
+
+/*************************************************************************/
+
+/**
+ * Processes the specified event by calling <code>processItemEvent()</code>
+ * if it is an instance of <code>ItemEvent</code> or calling the superclass
+ * method otherwise.
+ *
+ * @param event The event to process.
+ */
+protected void
+processEvent(AWTEvent event)
+{
+ if (event instanceof ItemEvent)
+ processItemEvent((ItemEvent)event);
+ else
+ super.processEvent(event);
+}
+
+/*************************************************************************/
+
+/**
+ * Processes the specified event by dispatching it to any registered listeners.
+ *
+ * @param event The event to process.
+ */
+protected void
+processItemEvent(ItemEvent event)
+{
+ if (item_listeners != null)
+ item_listeners.itemStateChanged(event);
+}
+
+void
+dispatchEventImpl(AWTEvent e)
+{
+ if (e instanceof ItemEvent)
+ {
+ synchronized (this)
+ {
+ state = (((ItemEvent) e).getStateChange() == ItemEvent.SELECTED);
+ }
+ }
+
+ if (e.id <= ItemEvent.ITEM_LAST
+ && e.id >= ItemEvent.ITEM_FIRST
+ && (item_listeners != null
+ || (eventMask & AWTEvent.ITEM_EVENT_MASK) != 0))
+ processEvent(e);
+ else
+ super.dispatchEventImpl(e);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a debugging string for this object.
+ *
+ * @return A debugging string for this object.
+ */
+public String
+paramString()
+{
+ return ("label=" + getLabel() + ",state=" + state
+ + "," + super.paramString());
+}
+
+ /**
+ * Returns an array of all the objects currently registered as FooListeners
+ * upon this <code>CheckboxMenuItem</code>. FooListeners are registered using
+ * the addFooListener method.
+ *
+ * @exception ClassCastException If listenerType doesn't specify a class or
+ * interface that implements java.util.EventListener.
+ */
+ public <T extends EventListener> T[] getListeners (Class<T> listenerType)
+ {
+ if (listenerType == ItemListener.class)
+ return AWTEventMulticaster.getListeners (item_listeners, listenerType);
+
+ return super.getListeners (listenerType);
+ }
+
+ /**
+ * Returns an aray of all item listeners currently registered to this
+ * <code>CheckBoxMenuItem</code>.
+ */
+ public ItemListener[] getItemListeners ()
+ {
+ return (ItemListener[]) getListeners (ItemListener.class);
+ }
+
+
+ protected class AccessibleAWTCheckboxMenuItem extends AccessibleAWTMenuItem
+ implements AccessibleAction, AccessibleValue
+ {
+ // I think the base class provides the necessary implementation
+
+ private static final long serialVersionUID = -1122642964303476L;
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>CheckboxMenuItem</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTCheckboxMenuItem();
+ return accessibleContext;
+ }
+
+ /**
+ * Generate a unique name for this <code>CheckboxMenuItem</code>.
+ *
+ * @return A unique name for this <code>CheckboxMenuItem</code>.
+ */
+ String generateName()
+ {
+ return "chkmenuitem" + getUniqueLong();
+ }
+
+ private static synchronized long getUniqueLong()
+ {
+ return next_chkmenuitem_number++;
+ }
+
+} // class CheckboxMenuItem
diff --git a/libjava/classpath/java/awt/Choice.java b/libjava/classpath/java/awt/Choice.java
new file mode 100644
index 000000000..5d2cfaf67
--- /dev/null
+++ b/libjava/classpath/java/awt/Choice.java
@@ -0,0 +1,569 @@
+/* Choice.java -- Java choice button widget.
+ Copyright (C) 1999, 2000, 2001, 2002, 2004, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.peer.ChoicePeer;
+import java.io.Serializable;
+import java.util.EventListener;
+import java.util.Vector;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleAction;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+
+/**
+ * This class implements a drop down choice list.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class Choice extends Component
+ implements ItemSelectable, Serializable, Accessible
+{
+ /**
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_choice_number;
+
+ // Serialization constant
+ private static final long serialVersionUID = -4075310674757313071L;
+
+ /**
+ * @serial A list of items for the choice box, which can be <code>null</code>.
+ * This is package-private to avoid an accessor method.
+ */
+ Vector pItems = new Vector();
+
+ /**
+ * @serial The index of the selected item in the choice box.
+ */
+ private int selectedIndex = -1;
+
+ /**
+ * ItemListener chain
+ */
+ private ItemListener item_listeners;
+
+ /**
+ * This class provides accessibility support for the
+ * combo box.
+ *
+ * @author Jerry Quinn (jlquinn@optonline.net)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+ protected class AccessibleAWTChoice
+ extends AccessibleAWTComponent
+ implements AccessibleAction
+ {
+
+ /**
+ * Serialization constant to match JDK 1.5
+ */
+ private static final long serialVersionUID = 7175603582428509322L;
+
+ /**
+ * Default constructor which simply calls the
+ * super class for generic component accessibility
+ * handling.
+ */
+ public AccessibleAWTChoice()
+ {
+ super();
+ }
+
+ /**
+ * Returns an implementation of the <code>AccessibleAction</code>
+ * interface for this accessible object. In this case, the
+ * current instance is simply returned (with a more appropriate
+ * type), as it also implements the accessible action as well as
+ * the context.
+ *
+ * @return the accessible action associated with this context.
+ * @see javax.accessibility.AccessibleAction
+ */
+ public AccessibleAction getAccessibleAction()
+ {
+ return this;
+ }
+
+ /**
+ * Returns the role of this accessible object.
+ *
+ * @return the instance of <code>AccessibleRole</code>,
+ * which describes this object.
+ * @see javax.accessibility.AccessibleRole
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.COMBO_BOX;
+ }
+
+ /**
+ * Returns the number of actions associated with this accessible
+ * object. In this case, it is the number of choices available.
+ *
+ * @return the number of choices available.
+ * @see javax.accessibility.AccessibleAction#getAccessibleActionCount()
+ */
+ public int getAccessibleActionCount()
+ {
+ return pItems.size();
+ }
+
+ /**
+ * Returns a description of the action with the supplied id.
+ * In this case, it is the text used in displaying the particular
+ * choice on-screen.
+ *
+ * @param i the id of the choice whose description should be
+ * retrieved.
+ * @return the <code>String</code> used to describe the choice.
+ * @see javax.accessibility.AccessibleAction#getAccessibleActionDescription(int)
+ */
+ public String getAccessibleActionDescription(int i)
+ {
+ return (String) pItems.get(i);
+ }
+
+ /**
+ * Executes the action with the specified id. In this case,
+ * calling this method provides the same behaviour as would
+ * choosing a choice from the list in a visual manner.
+ *
+ * @param i the id of the choice to select.
+ * @return true if a valid choice was specified.
+ * @see javax.accessibility.AccessibleAction#doAccessibleAction(int)
+ */
+ public boolean doAccessibleAction(int i)
+ {
+ if (i < 0 || i >= pItems.size())
+ return false;
+
+ Choice.this.select( i );
+
+ return true;
+ }
+ }
+
+ /**
+ * Initializes a new instance of <code>Choice</code>.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true
+ */
+ public Choice()
+ {
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException ();
+ }
+
+ /**
+ * Returns the number of items in the list.
+ *
+ * @return The number of items in the list.
+ */
+ public int getItemCount()
+ {
+ return countItems ();
+ }
+
+ /**
+ * Returns the number of items in the list.
+ *
+ * @return The number of items in the list.
+ *
+ * @deprecated This method is deprecated in favor of <code>getItemCount</code>.
+ */
+ public int countItems()
+ {
+ return pItems.size();
+ }
+
+ /**
+ * Returns the item at the specified index in the list.
+ *
+ * @param index The index into the list to return the item from.
+ *
+ * @exception ArrayIndexOutOfBoundsException If the index is invalid.
+ */
+ public String getItem(int index)
+ {
+ return (String)pItems.elementAt(index);
+ }
+
+ /**
+ * Adds the specified item to this choice box.
+ *
+ * @param item The item to add.
+ *
+ * @exception NullPointerException If the item's value is null
+ *
+ * @since 1.1
+ */
+ public synchronized void add(String item)
+ {
+ if (item == null)
+ throw new NullPointerException ("item must be non-null");
+
+ pItems.addElement(item);
+
+ if (peer != null)
+ ((ChoicePeer) peer).add(item, getItemCount() - 1);
+
+ if (selectedIndex == -1)
+ select( 0 );
+ }
+
+ /**
+ * Adds the specified item to this choice box.
+ *
+ * This method is oboslete since Java 2 platform 1.1. Please use
+ * {@link #add(String)} instead.
+ *
+ * @param item The item to add.
+ *
+ * @exception NullPointerException If the item's value is equal to null
+ */
+ public synchronized void addItem(String item)
+ {
+ add(item);
+ }
+
+ /** Inserts an item into this Choice. Existing items are shifted
+ * upwards. If the new item is the only item, then it is selected.
+ * If the currently selected item is shifted, then the first item is
+ * selected. If the currently selected item is not shifted, then it
+ * remains selected.
+ *
+ * @param item The item to add.
+ * @param index The index at which the item should be inserted.
+ *
+ * @exception IllegalArgumentException If index is less than 0
+ */
+ public synchronized void insert(String item, int index)
+ {
+ if (index < 0)
+ throw new IllegalArgumentException ("index may not be less then 0");
+
+ if (index > getItemCount ())
+ index = getItemCount ();
+
+ pItems.insertElementAt(item, index);
+
+ if (peer != null)
+ ((ChoicePeer) peer).add (item, index);
+
+ if (selectedIndex == -1 || selectedIndex >= index)
+ select(0);
+ }
+
+ /**
+ * Removes the specified item from the choice box.
+ *
+ * @param item The item to remove.
+ *
+ * @exception IllegalArgumentException If the specified item doesn't exist.
+ */
+ public synchronized void remove(String item)
+ {
+ int index = pItems.indexOf(item);
+ if (index == -1)
+ throw new IllegalArgumentException ("item \""
+ + item + "\" not found in Choice");
+ remove(index);
+ }
+
+ /**
+ * Removes the item at the specified index from the choice box.
+ *
+ * @param index The index of the item to remove.
+ *
+ * @exception IndexOutOfBoundsException If the index is not valid.
+ */
+ public synchronized void remove(int index)
+ {
+ pItems.removeElementAt(index);
+
+ if (peer != null)
+ ((ChoicePeer) peer).remove( index );
+
+ if( getItemCount() == 0 )
+ selectedIndex = -1;
+ else
+ {
+ if( selectedIndex > index )
+ selectedIndex--;
+ else if( selectedIndex == index )
+ selectedIndex = 0;
+
+ if( peer != null )
+ ((ChoicePeer)peer).select( selectedIndex );
+ }
+ }
+
+ /**
+ * Removes all of the objects from this choice box.
+ */
+ public synchronized void removeAll()
+ {
+ if (getItemCount() <= 0)
+ return;
+
+ pItems.removeAllElements ();
+
+ if (peer != null)
+ {
+ ChoicePeer cp = (ChoicePeer) peer;
+ cp.removeAll ();
+ }
+
+ selectedIndex = -1;
+ }
+
+ /**
+ * Returns the currently selected item, or null if no item is
+ * selected.
+ *
+ * @return The currently selected item.
+ */
+ public synchronized String getSelectedItem()
+ {
+ return (selectedIndex == -1
+ ? null
+ : ((String)pItems.elementAt(selectedIndex)));
+ }
+
+ /**
+ * Returns an array with one row containing the selected item.
+ *
+ * @return An array containing the selected item.
+ */
+ public synchronized Object[] getSelectedObjects()
+ {
+ if (selectedIndex == -1)
+ return null;
+
+ Object[] objs = new Object[1];
+ objs[0] = pItems.elementAt(selectedIndex);
+
+ return objs;
+ }
+
+ /**
+ * Returns the index of the selected item.
+ *
+ * @return The index of the selected item.
+ */
+ public int getSelectedIndex()
+ {
+ return selectedIndex;
+ }
+
+ /**
+ * Forces the item at the specified index to be selected.
+ *
+ * @param index The index of the row to make selected.
+ *
+ * @exception IllegalArgumentException If the specified index is invalid.
+ */
+ public synchronized void select(int index)
+ {
+ if ((index < 0) || (index >= getItemCount()))
+ throw new IllegalArgumentException("Bad index: " + index);
+
+ if( selectedIndex == index )
+ return;
+
+ selectedIndex = index;
+ if( peer != null )
+ ((ChoicePeer)peer).select( index );
+ }
+
+ /**
+ * Forces the named item to be selected.
+ *
+ * @param item The item to be selected.
+ *
+ * @exception IllegalArgumentException If the specified item does not exist.
+ */
+ public synchronized void select(String item)
+ {
+ int index = pItems.indexOf(item);
+ if( index >= 0 )
+ select( index );
+ }
+
+ /**
+ * Creates the native peer for this object.
+ */
+ public void addNotify()
+ {
+ if (peer == null)
+ peer = getToolkit ().createChoice (this);
+ super.addNotify ();
+ }
+
+ /**
+ * Adds the specified listener to the list of registered listeners for
+ * this object.
+ *
+ * @param listener The listener to add.
+ */
+ public synchronized void addItemListener(ItemListener listener)
+ {
+ item_listeners = AWTEventMulticaster.add(item_listeners, listener);
+ }
+
+ /**
+ * Removes the specified listener from the list of registered listeners for
+ * this object.
+ *
+ * @param listener The listener to remove.
+ */
+ public synchronized void removeItemListener(ItemListener listener)
+ {
+ item_listeners = AWTEventMulticaster.remove(item_listeners, listener);
+ }
+
+ /**
+ * Processes this event by invoking <code>processItemEvent()</code> if the
+ * event is an instance of <code>ItemEvent</code>, otherwise the event
+ * is passed to the superclass.
+ *
+ * @param event The event to process.
+ */
+ protected void processEvent(AWTEvent event)
+ {
+ if (event instanceof ItemEvent)
+ processItemEvent((ItemEvent)event);
+ else
+ super.processEvent(event);
+ }
+
+ void dispatchEventImpl(AWTEvent e)
+ {
+ super.dispatchEventImpl(e);
+
+ if( e.id <= ItemEvent.ITEM_LAST && e.id >= ItemEvent.ITEM_FIRST &&
+ ( item_listeners != null ||
+ ( eventMask & AWTEvent.ITEM_EVENT_MASK ) != 0 ) )
+ processEvent(e);
+ }
+
+ /**
+ * Processes item event by dispatching to any registered listeners.
+ *
+ * @param event The event to process.
+ */
+ protected void processItemEvent(ItemEvent event)
+ {
+ int index = pItems.indexOf((String) event.getItem());
+ if (item_listeners != null)
+ item_listeners.itemStateChanged(event);
+ }
+
+ /**
+ * Returns a debugging string for this object.
+ *
+ * @return A debugging string for this object.
+ */
+ protected String paramString()
+ {
+ return "selectedIndex=" + selectedIndex + "," + super.paramString();
+ }
+
+ /**
+ * Returns an array of all the objects currently registered as FooListeners
+ * upon this Choice. FooListeners are registered using the addFooListener
+ * method.
+ *
+ * @exception ClassCastException If listenerType doesn't specify a class or
+ * interface that implements java.util.EventListener.
+ *
+ * @since 1.3
+ */
+ public <T extends EventListener> T[] getListeners (Class<T> listenerType)
+ {
+ if (listenerType == ItemListener.class)
+ return AWTEventMulticaster.getListeners (item_listeners, listenerType);
+
+ return super.getListeners (listenerType);
+ }
+
+ /**
+ * Returns all registered item listeners.
+ *
+ * @since 1.4
+ */
+ public ItemListener[] getItemListeners ()
+ {
+ return (ItemListener[]) getListeners (ItemListener.class);
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>Choice</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTChoice();
+ return accessibleContext;
+ }
+
+ /**
+ * Generate a unique name for this <code>Choice</code>.
+ *
+ * @return A unique name for this <code>Choice</code>.
+ */
+ String generateName()
+ {
+ return "choice" + getUniqueLong();
+ }
+
+ private static synchronized long getUniqueLong()
+ {
+ return next_choice_number++;
+ }
+} // class Choice
diff --git a/libjava/classpath/java/awt/Color.java b/libjava/classpath/java/awt/Color.java
new file mode 100644
index 000000000..243a5e86f
--- /dev/null
+++ b/libjava/classpath/java/awt/Color.java
@@ -0,0 +1,1025 @@
+/* Color.java -- represents a color in Java
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.color.ColorSpace;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.ColorModel;
+import java.io.Serializable;
+
+/**
+ * This class represents a color value in the AWT system. It uses the sRGB
+ * (standard Red-Green-Blue) system, along with an alpha value ranging from
+ * transparent (0.0f or 0) and opaque (1.0f or 255). The color is not
+ * pre-multiplied by the alpha value an any of the accessor methods. Further
+ * information about sRGB can be found at
+ * <a href="http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html">
+ * http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html</a>.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see ColorSpace
+ * @see AlphaComposite
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public class Color implements Paint, Serializable
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 118526816881161077L;
+
+ /** Constant for the color white: R=255, G=255, B=255. */
+ public static final Color white = new Color(0xffffff, false);
+
+ /**
+ * Constant for the color white: R=255, G=255, B=255.
+ *
+ * @since 1.4
+ */
+ public static final Color WHITE = white;
+
+ /** Constant for the color light gray: R=192, G=192, B=192. */
+ public static final Color lightGray = new Color(0xc0c0c0, false);
+
+ /**
+ * Constant for the color light gray: R=192, G=192, B=192.
+ *
+ * @since 1.4
+ */
+ public static final Color LIGHT_GRAY = lightGray;
+
+ /** Constant for the color gray: R=128, G=128, B=128. */
+ public static final Color gray = new Color(0x808080, false);
+
+ /**
+ * Constant for the color gray: R=128, G=128, B=128.
+ *
+ * @since 1.4
+ */
+ public static final Color GRAY = gray;
+
+ /** Constant for the color dark gray: R=64, G=64, B=64. */
+ public static final Color darkGray = new Color(0x404040, false);
+
+ /**
+ * Constant for the color dark gray: R=64, G=64, B=64.
+ *
+ * @since 1.4
+ */
+ public static final Color DARK_GRAY = darkGray;
+
+ /** Constant for the color black: R=0, G=0, B=0. */
+ public static final Color black = new Color(0x000000, false);
+
+ /**
+ * Constant for the color black: R=0, G=0, B=0.
+ *
+ * @since 1.4
+ */
+ public static final Color BLACK = black;
+
+ /** Constant for the color red: R=255, G=0, B=0. */
+ public static final Color red = new Color(0xff0000, false);
+
+ /**
+ * Constant for the color red: R=255, G=0, B=0.
+ *
+ * @since 1.4
+ */
+ public static final Color RED = red;
+
+ /** Constant for the color pink: R=255, G=175, B=175. */
+ public static final Color pink = new Color(0xffafaf, false);
+
+ /**
+ * Constant for the color pink: R=255, G=175, B=175.
+ *
+ * @since 1.4
+ */
+ public static final Color PINK = pink;
+
+ /** Constant for the color orange: R=255, G=200, B=0. */
+ public static final Color orange = new Color(0xffc800, false);
+
+ /**
+ * Constant for the color orange: R=255, G=200, B=0.
+ *
+ * @since 1.4
+ */
+ public static final Color ORANGE = orange;
+
+ /** Constant for the color yellow: R=255, G=255, B=0. */
+ public static final Color yellow = new Color(0xffff00, false);
+
+ /**
+ * Constant for the color yellow: R=255, G=255, B=0.
+ *
+ * @since 1.4
+ */
+ public static final Color YELLOW = yellow;
+
+ /** Constant for the color green: R=0, G=255, B=0. */
+ public static final Color green = new Color(0x00ff00, false);
+
+ /**
+ * Constant for the color green: R=0, G=255, B=0.
+ *
+ * @since 1.4
+ */
+ public static final Color GREEN = green;
+
+ /** Constant for the color magenta: R=255, G=0, B=255. */
+ public static final Color magenta = new Color(0xff00ff, false);
+
+ /**
+ * Constant for the color magenta: R=255, G=0, B=255.
+ *
+ * @since 1.4
+ */
+ public static final Color MAGENTA = magenta;
+
+ /** Constant for the color cyan: R=0, G=255, B=255. */
+ public static final Color cyan = new Color(0x00ffff, false);
+
+ /**
+ * Constant for the color cyan: R=0, G=255, B=255.
+ *
+ * @since 1.4
+ */
+ public static final Color CYAN = cyan;
+
+ /** Constant for the color blue: R=0, G=0, B=255. */
+ public static final Color blue = new Color(0x0000ff, false);
+
+ /**
+ * Constant for the color blue: R=0, G=0, B=255.
+ *
+ * @since 1.4
+ */
+ public static final Color BLUE = blue;
+
+ /** Internal mask for red. */
+ private static final int RED_MASK = 255 << 16;
+
+ /** Internal mask for green. */
+ private static final int GREEN_MASK = 255 << 8;
+
+ /** Internal mask for blue. */
+ private static final int BLUE_MASK = 255;
+
+ /** Internal mask for alpha. Package visible for use in subclass. */
+ static final int ALPHA_MASK = 255 << 24;
+
+ /** Amount to scale a color by when brightening or darkening. */
+ private static final float BRIGHT_SCALE = 0.7f;
+
+ /**
+ * The color value, in sRGB. Note that the actual color may be more
+ * precise if frgbvalue or fvalue is non-null. This class stores alpha, red,
+ * green, and blue, each 0-255, packed in an int. However, the subclass
+ * SystemColor stores an index into an array. Therefore, for serial
+ * compatibility (and because of poor design on Sun's part), this value
+ * cannot be used directly; instead you must use <code>getRGB()</code>.
+ *
+ * @see #getRGB()
+ * @serial the value of the color, whether an RGB literal or array index
+ */
+ final int value;
+
+ /**
+ * The color value, in sRGB. This may be null if the color was constructed
+ * with ints; and it does not include alpha. This stores red, green, and
+ * blue, in the range 0.0f - 1.0f.
+ *
+ * @see #getRGBColorComponents(float[])
+ * @see #getRGBComponents(float[])
+ * @serial the rgb components of the value
+ * @since 1.2
+ */
+ private float[] frgbvalue;
+
+ /**
+ * The color value, in the native ColorSpace components. This may be null
+ * if the color was constructed with ints or in the sRGB color space; and
+ * it does not include alpha.
+ *
+ * @see #getRGBColorComponents(float[])
+ * @see #getRGBComponents(float[])
+ * @serial the original color space components of the color
+ * @since 1.2
+ */
+ private float[] fvalue;
+
+ /**
+ * The alpha value. This is in the range 0.0f - 1.0f, but is invalid if
+ * deserialized as 0.0 when frgbvalue is null.
+ *
+ * @see #getRGBComponents(float[])
+ * @see #getComponents(float[])
+ * @serial the alpha component of this color
+ * @since 1.2
+ */
+ private final float falpha;
+
+ /**
+ * The ColorSpace. Null means the default sRGB space.
+ *
+ * @see #getColor(String)
+ * @see #getColorSpace()
+ * @see #getColorComponents(float[])
+ * @serial the color space for this color
+ * @since 1.2
+ */
+ private final ColorSpace cs;
+
+ /**
+ * The paint context for this solid color. Package visible for use in
+ * subclass.
+ */
+ transient ColorPaintContext context;
+
+ /**
+ * Initializes a new instance of <code>Color</code> using the specified
+ * red, green, and blue values, which must be given as integers in the
+ * range of 0-255. Alpha will default to 255 (opaque). When drawing to
+ * screen, the actual color may be adjusted to the best match of hardware
+ * capabilities.
+ *
+ * @param red the red component of the RGB value
+ * @param green the green component of the RGB value
+ * @param blue the blue component of the RGB value
+ * @throws IllegalArgumentException if the values are out of range 0-255
+ * @see #getRed()
+ * @see #getGreen()
+ * @see #getBlue()
+ * @see #getRGB()
+ * @see #Color(int, int, int, int)
+ */
+ public Color(int red, int green, int blue)
+ {
+ this(red, green, blue, 255);
+ }
+
+ /**
+ * Initializes a new instance of <code>Color</code> using the specified
+ * red, green, blue, and alpha values, which must be given as integers in
+ * the range of 0-255. When drawing to screen, the actual color may be
+ * adjusted to the best match of hardware capabilities.
+ *
+ * @param red the red component of the RGB value
+ * @param green the green component of the RGB value
+ * @param blue the blue component of the RGB value
+ * @param alpha the alpha value of the color
+ * @throws IllegalArgumentException if the values are out of range 0-255
+ * @see #getRed()
+ * @see #getGreen()
+ * @see #getBlue()
+ * @see #getAlpha()
+ * @see #getRGB()
+ */
+ public Color(int red, int green, int blue, int alpha)
+ {
+ if ((red & 255) != red || (green & 255) != green || (blue & 255) != blue
+ || (alpha & 255) != alpha)
+ throw new IllegalArgumentException("Bad RGB values"
+ +" red=0x"+Integer.toHexString(red)
+ +" green=0x"+Integer.toHexString(green)
+ +" blue=0x"+Integer.toHexString(blue)
+ +" alpha=0x"+Integer.toHexString(alpha) );
+
+ value = (alpha << 24) | (red << 16) | (green << 8) | blue;
+ falpha = 1;
+ cs = null;
+ }
+
+ /**
+ * Initializes a new instance of <code>Color</code> using the specified
+ * RGB value. The blue value is in bits 0-7, green in bits 8-15, and
+ * red in bits 16-23. The other bits are ignored. The alpha value is set
+ * to 255 (opaque). When drawing to screen, the actual color may be
+ * adjusted to the best match of hardware capabilities.
+ *
+ * @param value the RGB value
+ * @see ColorModel#getRGBdefault()
+ * @see #getRed()
+ * @see #getGreen()
+ * @see #getBlue()
+ * @see #getRGB()
+ * @see #Color(int, boolean)
+ */
+ public Color(int value)
+ {
+ this(value, false);
+ }
+
+ /**
+ * Initializes a new instance of <code>Color</code> using the specified
+ * RGB value. The blue value is in bits 0-7, green in bits 8-15, and
+ * red in bits 16-23. The alpha value is in bits 24-31, unless hasalpha
+ * is false, in which case alpha is set to 255. When drawing to screen, the
+ * actual color may be adjusted to the best match of hardware capabilities.
+ *
+ * @param value the RGB value
+ * @param hasalpha true if value includes the alpha
+ * @see ColorModel#getRGBdefault()
+ * @see #getRed()
+ * @see #getGreen()
+ * @see #getBlue()
+ * @see #getAlpha()
+ * @see #getRGB()
+ */
+ public Color(int value, boolean hasalpha)
+ {
+ // Note: SystemColor calls this constructor, setting falpha to 0; but
+ // code in getRGBComponents correctly reports falpha as 1.0 to the user
+ // for all instances of SystemColor since frgbvalue is left null here.
+ if (hasalpha)
+ falpha = ((value & ALPHA_MASK) >> 24) / 255f;
+ else
+ {
+ value |= ALPHA_MASK;
+ falpha = 1;
+ }
+ this.value = value;
+ cs = null;
+ }
+
+ /**
+ * Initializes a new instance of <code>Color</code> using the specified
+ * RGB values. These must be in the range of 0.0-1.0. Alpha is assigned
+ * the value of 1.0 (opaque). When drawing to screen, the actual color may
+ * be adjusted to the best match of hardware capabilities.
+ *
+ * @param red the red component of the RGB value
+ * @param green the green component of the RGB value
+ * @param blue the blue component of the RGB value
+ * @throws IllegalArgumentException tf the values are out of range 0.0f-1.0f
+ * @see #getRed()
+ * @see #getGreen()
+ * @see #getBlue()
+ * @see #getRGB()
+ * @see #Color(float, float, float, float)
+ */
+ public Color(float red, float green, float blue)
+ {
+ this(red, green, blue, 1.0f);
+ }
+
+ /**
+ * Initializes a new instance of <code>Color</code> using the specified
+ * RGB and alpha values. These must be in the range of 0.0-1.0. When drawing
+ * to screen, the actual color may be adjusted to the best match of
+ * hardware capabilities.
+ *
+ * @param red the red component of the RGB value
+ * @param green the green component of the RGB value
+ * @param blue the blue component of the RGB value
+ * @param alpha the alpha value of the color
+ * @throws IllegalArgumentException tf the values are out of range 0.0f-1.0f
+ * @see #getRed()
+ * @see #getGreen()
+ * @see #getBlue()
+ * @see #getAlpha()
+ * @see #getRGB()
+ */
+ public Color(float red, float green, float blue, float alpha)
+ {
+ value = convert(red, green, blue, alpha);
+ frgbvalue = new float[] {red, green, blue};
+ falpha = alpha;
+ cs = null;
+ }
+
+ /**
+ * Creates a color in the given ColorSpace with the specified alpha. The
+ * array must be non-null and have enough elements for the color space
+ * (for example, RGB requires 3 elements, CMYK requires 4). When drawing
+ * to screen, the actual color may be adjusted to the best match of
+ * hardware capabilities.
+ *
+ * @param space the color space of components
+ * @param components the color components, except alpha
+ * @param alpha the alpha value of the color
+ * @throws NullPointerException if cpsace or components is null
+ * @throws ArrayIndexOutOfBoundsException if components is too small
+ * @throws IllegalArgumentException if alpha or any component is out of range
+ * @see #getComponents(float[])
+ * @see #getColorComponents(float[])
+ */
+ public Color(ColorSpace space, float[] components, float alpha)
+ {
+ frgbvalue = space.toRGB(components);
+ fvalue = components;
+ falpha = alpha;
+ cs = space;
+ value = convert(frgbvalue[0], frgbvalue[1], frgbvalue[2], alpha);
+ }
+
+ /**
+ * Returns the red value for this color, as an integer in the range 0-255
+ * in the sRGB color space.
+ *
+ * @return the red value for this color
+ * @see #getRGB()
+ */
+ public int getRed()
+ {
+ // Do not inline getRGB() to value, because of SystemColor.
+ return (getRGB() & RED_MASK) >> 16;
+ }
+
+ /**
+ * Returns the green value for this color, as an integer in the range 0-255
+ * in the sRGB color space.
+ *
+ * @return the green value for this color
+ * @see #getRGB()
+ */
+ public int getGreen()
+ {
+ // Do not inline getRGB() to value, because of SystemColor.
+ return (getRGB() & GREEN_MASK) >> 8;
+ }
+
+ /**
+ * Returns the blue value for this color, as an integer in the range 0-255
+ * in the sRGB color space.
+ *
+ * @return the blue value for this color
+ * @see #getRGB()
+ */
+ public int getBlue()
+ {
+ // Do not inline getRGB() to value, because of SystemColor.
+ return getRGB() & BLUE_MASK;
+ }
+
+ /**
+ * Returns the alpha value for this color, as an integer in the range 0-255.
+ *
+ * @return the alpha value for this color
+ * @see #getRGB()
+ */
+ public int getAlpha()
+ {
+ // Do not inline getRGB() to value, because of SystemColor.
+ return (getRGB() & ALPHA_MASK) >>> 24;
+ }
+
+ /**
+ * Returns the RGB value for this color, in the sRGB color space. The blue
+ * value will be in bits 0-7, green in 8-15, red in 16-23, and alpha value in
+ * 24-31.
+ *
+ * @return the RGB value for this color
+ * @see ColorModel#getRGBdefault()
+ * @see #getRed()
+ * @see #getGreen()
+ * @see #getBlue()
+ * @see #getAlpha()
+ */
+ public int getRGB()
+ {
+ return value;
+ }
+
+ /**
+ * Returns a brighter version of this color. This is done by increasing the
+ * RGB values by an arbitrary scale factor. The new color is opaque (an
+ * alpha of 255). Note that this method and the <code>darker()</code>
+ * method are not necessarily inverses.
+ *
+ * @return a brighter version of this color
+ * @see #darker()
+ */
+ public Color brighter()
+ {
+ // Do not inline getRGB() to this.value, because of SystemColor.
+ int value = getRGB();
+ int[] hues = new int[3];
+ hues[0] = (value & RED_MASK) >> 16;
+ hues[1] = (value & GREEN_MASK) >> 8;
+ hues[2] = value & BLUE_MASK;
+
+ // (0,0,0) is a special case.
+ if (hues[0] == 0 && hues[1] == 0 && hues[2] ==0)
+ {
+ hues[0] = 3;
+ hues[1] = 3;
+ hues[2] = 3;
+ }
+ else
+ {
+ for (int index = 0; index < 3; index++)
+ {
+
+ if (hues[index] > 2)
+ hues[index] = (int) Math.min(255, hues[index]/0.7f);
+ if (hues[index] == 1 || hues[index] == 2)
+ hues[index] = 4;
+ }
+ }
+
+ return new Color(hues[0], hues[1], hues[2], 255);
+ }
+
+ /**
+ * Returns a darker version of this color. This is done by decreasing the
+ * RGB values by an arbitrary scale factor. The new color is opaque (an
+ * alpha of 255). Note that this method and the <code>brighter()</code>
+ * method are not necessarily inverses.
+ *
+ * @return a darker version of this color
+ * @see #brighter()
+ */
+ public Color darker()
+ {
+ // Do not inline getRGB() to this.value, because of SystemColor.
+ int value = getRGB();
+ return new Color((int) (((value & RED_MASK) >> 16) * BRIGHT_SCALE),
+ (int) (((value & GREEN_MASK) >> 8) * BRIGHT_SCALE),
+ (int) ((value & BLUE_MASK) * BRIGHT_SCALE), 255);
+ }
+
+ /**
+ * Returns a hash value for this color. This is simply the color in 8-bit
+ * precision, in the format 0xAARRGGBB (alpha, red, green, blue).
+ *
+ * @return a hash value for this color
+ */
+ public int hashCode()
+ {
+ return value;
+ }
+
+ /**
+ * Tests this object for equality against the specified object. This will
+ * be true if and only if the specified object is an instance of
+ * <code>Color</code> and has the same 8-bit integer red, green, and blue
+ * values as this object. Note that two colors may be slightly different
+ * as float values, but round to the same integer values. Also note that
+ * this does not accurately compare SystemColors, since that class does
+ * not store its internal data in RGB format like regular colors.
+ *
+ * @param obj the object to compare to
+ * @return true if the specified object is semantically equal to this one
+ */
+ public boolean equals(Object obj)
+ {
+ return obj instanceof Color && ((Color) obj).value == value;
+ }
+
+ /**
+ * Returns a string representation of this object. Subclasses may return
+ * any desired format, except for null, but this implementation returns
+ * <code>getClass().getName() + "[r=" + getRed() + ",g=" + getGreen()
+ * + ",b=" + getBlue() + ']'</code>.
+ *
+ * @return a string representation of this object
+ */
+ public String toString()
+ {
+ return getClass().getName() + "[r=" + ((value & RED_MASK) >> 16)
+ + ",g=" + ((value & GREEN_MASK) >> 8) + ",b=" + (value & BLUE_MASK)
+ + ']';
+ }
+
+ /**
+ * Converts the specified string to a number, using Integer.decode, and
+ * creates a new instance of <code>Color</code> from the value. The alpha
+ * value will be 255 (opaque).
+ *
+ * @param str the numeric color string
+ * @return a new instance of <code>Color</code> for the string
+ * @throws NumberFormatException if the string cannot be parsed
+ * @throws NullPointerException if the string is null
+ * @see Integer#decode(String)
+ * @see #Color(int)
+ * @since 1.1
+ */
+ public static Color decode(String str)
+ {
+ return new Color(Integer.decode(str).intValue(), false);
+ }
+
+ /**
+ * Returns a new instance of <code>Color</code> from the value of the
+ * system property named by the specified string. If the property does not
+ * exist, or cannot be parsed, then <code>null</code> will be returned.
+ *
+ * @param prop the system property to retrieve
+ * @throws SecurityException if getting the property is denied
+ * @see #getColor(String, Color)
+ * @see Integer#getInteger(String)
+ */
+ public static Color getColor(String prop)
+ {
+ return getColor(prop, null);
+ }
+
+ /**
+ * Returns a new instance of <code>Color</code> from the value of the
+ * system property named by the specified string. If the property does
+ * not exist, or cannot be parsed, then the default color value will be
+ * returned.
+ *
+ * @param prop the system property to retrieve
+ * @param defcolor the default color
+ * @throws SecurityException if getting the property is denied
+ * @see Integer#getInteger(String)
+ */
+ public static Color getColor(String prop, Color defcolor)
+ {
+ Integer val = Integer.getInteger(prop, null);
+ return val == null ? defcolor
+ : new Color(val.intValue(), false);
+ }
+
+ /**
+ * Returns a new instance of <code>Color</code> from the value of the
+ * system property named by the specified string. If the property does
+ * not exist, or cannot be parsed, then the default RGB value will be
+ * used to create a return value.
+ *
+ * @param prop the system property to retrieve
+ * @param defrgb the default RGB value
+ * @throws SecurityException if getting the property is denied
+ * @see #getColor(String, Color)
+ * @see Integer#getInteger(String, int)
+ */
+ public static Color getColor(String prop, int defrgb)
+ {
+ Color c = getColor(prop, null);
+ return c == null ? new Color(defrgb, false) : c;
+ }
+
+ /**
+ * Converts from the HSB (hue, saturation, brightness) color model to the
+ * RGB (red, green, blue) color model. The hue may be any floating point;
+ * it's fractional portion is used to select the angle in the HSB model.
+ * The saturation and brightness must be between 0 and 1. The result is
+ * suitable for creating an RGB color with the one-argument constructor.
+ *
+ * @param hue the hue of the HSB value
+ * @param saturation the saturation of the HSB value
+ * @param brightness the brightness of the HSB value
+ * @return the RGB value
+ * @see #getRGB()
+ * @see #Color(int)
+ * @see ColorModel#getRGBdefault()
+ */
+ public static int HSBtoRGB(float hue, float saturation, float brightness)
+ {
+ if (saturation == 0)
+ return convert(brightness, brightness, brightness, 0);
+ if (saturation < 0 || saturation > 1 || brightness < 0 || brightness > 1)
+ throw new IllegalArgumentException();
+ hue = hue - (float) Math.floor(hue);
+ int i = (int) (6 * hue);
+ float f = 6 * hue - i;
+ float p = brightness * (1 - saturation);
+ float q = brightness * (1 - saturation * f);
+ float t = brightness * (1 - saturation * (1 - f));
+ switch (i)
+ {
+ case 0:
+ return convert(brightness, t, p, 0);
+ case 1:
+ return convert(q, brightness, p, 0);
+ case 2:
+ return convert(p, brightness, t, 0);
+ case 3:
+ return convert(p, q, brightness, 0);
+ case 4:
+ return convert(t, p, brightness, 0);
+ case 5:
+ return convert(brightness, p, q, 0);
+ default:
+ throw new InternalError("impossible");
+ }
+ }
+
+ /**
+ * Converts from the RGB (red, green, blue) color model to the HSB (hue,
+ * saturation, brightness) color model. If the array is null, a new one
+ * is created, otherwise it is recycled. The results will be in the range
+ * 0.0-1.0 if the inputs are in the range 0-255.
+ *
+ * @param red the red part of the RGB value
+ * @param green the green part of the RGB value
+ * @param blue the blue part of the RGB value
+ * @param array an array for the result (at least 3 elements), or null
+ * @return the array containing HSB value
+ * @throws ArrayIndexOutOfBoundsException of array is too small
+ * @see #getRGB()
+ * @see #Color(int)
+ * @see ColorModel#getRGBdefault()
+ */
+ public static float[] RGBtoHSB(int red, int green, int blue, float array[])
+ {
+ if (array == null)
+ array = new float[3];
+ // Calculate brightness.
+ int min;
+ int max;
+ if (red < green)
+ {
+ min = red;
+ max = green;
+ }
+ else
+ {
+ min = green;
+ max = red;
+ }
+ if (blue > max)
+ max = blue;
+ else if (blue < min)
+ min = blue;
+ array[2] = max / 255f;
+ // Calculate saturation.
+ if (max == 0)
+ array[1] = 0;
+ else
+ array[1] = ((float) (max - min)) / ((float) max);
+ // Calculate hue.
+ if (array[1] == 0)
+ array[0] = 0;
+ else
+ {
+ float delta = (max - min) * 6;
+ if (red == max)
+ array[0] = (green - blue) / delta;
+ else if (green == max)
+ array[0] = 1f / 3 + (blue - red) / delta;
+ else
+ array[0] = 2f / 3 + (red - green) / delta;
+ if (array[0] < 0)
+ array[0]++;
+ }
+ return array;
+ }
+
+ /**
+ * Returns a new instance of <code>Color</code> based on the specified
+ * HSB values. The hue may be any floating point; it's fractional portion
+ * is used to select the angle in the HSB model. The saturation and
+ * brightness must be between 0 and 1.
+ *
+ * @param hue the hue of the HSB value
+ * @param saturation the saturation of the HSB value
+ * @param brightness the brightness of the HSB value
+ * @return the new <code>Color</code> object
+ */
+ public static Color getHSBColor(float hue, float saturation,
+ float brightness)
+ {
+ return new Color(HSBtoRGB(hue, saturation, brightness), false);
+ }
+
+ /**
+ * Returns a float array with the red, green, and blue components, and the
+ * alpha value, in the default sRGB space, with values in the range 0.0-1.0.
+ * If the array is null, a new one is created, otherwise it is recycled.
+ *
+ * @param array the array to put results into (at least 4 elements), or null
+ * @return the RGB components and alpha value
+ * @throws ArrayIndexOutOfBoundsException if array is too small
+ */
+ public float[] getRGBComponents(float[] array)
+ {
+ if (array == null)
+ array = new float[4];
+ getRGBColorComponents(array);
+ // Stupid serialization issues require this check.
+ array[3] = (falpha == 0 && frgbvalue == null
+ ? ((getRGB() & ALPHA_MASK) >> 24) / 255f : falpha);
+ return array;
+ }
+
+ /**
+ * Returns a float array with the red, green, and blue components, in the
+ * default sRGB space, with values in the range 0.0-1.0. If the array is
+ * null, a new one is created, otherwise it is recycled.
+ *
+ * @param array the array to put results into (at least 3 elements), or null
+ * @return the RGB components
+ * @throws ArrayIndexOutOfBoundsException if array is too small
+ */
+ public float[] getRGBColorComponents(float[] array)
+ {
+ if (array == null)
+ array = new float[3];
+ else if (array == frgbvalue)
+ return array; // Optimization for getColorComponents(float[]).
+ if (frgbvalue == null)
+ {
+ // Do not inline getRGB() to this.value, because of SystemColor.
+ int value = getRGB();
+ frgbvalue = new float[] { ((value & RED_MASK) >> 16) / 255f,
+ ((value & GREEN_MASK) >> 8) / 255f,
+ (value & BLUE_MASK) / 255f };
+ }
+ array[0] = frgbvalue[0];
+ array[1] = frgbvalue[1];
+ array[2] = frgbvalue[2];
+ return array;
+ }
+
+ /**
+ * Returns a float array containing the color and alpha components of this
+ * color in the ColorSpace it was created with (the constructors which do
+ * not take a ColorSpace parameter use a default sRGB ColorSpace). If the
+ * array is null, a new one is created, otherwise it is recycled, and must
+ * have at least one more position than components used in the color space.
+ *
+ * @param array the array to put results into, or null
+ * @return the original color space components and alpha value
+ * @throws ArrayIndexOutOfBoundsException if array is too small
+ */
+ public float[] getComponents(float[] array)
+ {
+ int numComponents = cs == null ? 3 : cs.getNumComponents();
+ if (array == null)
+ array = new float[1 + numComponents];
+ getColorComponents(array);
+ // Stupid serialization issues require this check.
+ array[numComponents] = (falpha == 0 && frgbvalue == null
+ ? ((getRGB() & ALPHA_MASK) >> 24) / 255f : falpha);
+ return array;
+ }
+
+ /**
+ * Returns a float array containing the color components of this color in
+ * the ColorSpace it was created with (the constructors which do not take
+ * a ColorSpace parameter use a default sRGB ColorSpace). If the array is
+ * null, a new one is created, otherwise it is recycled, and must have at
+ * least as many positions as used in the color space.
+ *
+ * @param array the array to put results into, or null
+ * @return the original color space components
+ * @throws ArrayIndexOutOfBoundsException if array is too small
+ */
+ public float[] getColorComponents(float[] array)
+ {
+ int numComponents = cs == null ? 3 : cs.getNumComponents();
+ if (array == null)
+ array = new float[numComponents];
+ if (fvalue == null) // If fvalue is null, cs should be null too.
+ fvalue = getRGBColorComponents(frgbvalue);
+ System.arraycopy(fvalue, 0, array, 0, numComponents);
+ return array;
+ }
+
+ /**
+ * Returns a float array containing the color and alpha components of this
+ * color in the given ColorSpace. If the array is null, a new one is
+ * created, otherwise it is recycled, and must have at least one more
+ * position than components used in the color space.
+ *
+ * @param space the color space to translate to
+ * @param array the array to put results into, or null
+ * @return the color space components and alpha value
+ * @throws ArrayIndexOutOfBoundsException if array is too small
+ * @throws NullPointerException if space is null
+ */
+ public float[] getComponents(ColorSpace space, float[] array)
+ {
+ int numComponents = space.getNumComponents();
+ if (array == null)
+ array = new float[1 + numComponents];
+ getColorComponents(space, array);
+ // Stupid serialization issues require this check.
+ array[numComponents] = (falpha == 0 && frgbvalue == null
+ ? ((getRGB() & ALPHA_MASK) >> 24) / 255f : falpha);
+ return array;
+ }
+
+ /**
+ * Returns a float array containing the color components of this color in
+ * the given ColorSpace. If the array is null, a new one is created,
+ * otherwise it is recycled, and must have at least as many positions as
+ * used in the color space.
+ *
+ * @param space the color space to translate to
+ * @return the color space components
+ * @throws ArrayIndexOutOfBoundsException if array is too small
+ * @throws NullPointerException if space is null
+ */
+ public float[] getColorComponents(ColorSpace space, float[] array)
+ {
+ float[] components = space.fromRGB(getRGBColorComponents(frgbvalue));
+ if (array == null)
+ return components;
+ System.arraycopy(components, 0, array, 0, components.length);
+ return array;
+ }
+
+ /**
+ * Returns the color space of this color. Except for the constructor which
+ * takes a ColorSpace argument, this will be an implementation of
+ * ColorSpace.CS_sRGB.
+ *
+ * @return the color space
+ */
+ public ColorSpace getColorSpace()
+ {
+ return cs == null ? ColorSpace.getInstance(ColorSpace.CS_sRGB) : cs;
+ }
+
+ /**
+ * Returns a paint context, used for filling areas of a raster scan with
+ * this color. Since the color is constant across the entire rectangle, and
+ * since it is always in sRGB space, this implementation returns the same
+ * object, regardless of the parameters. Subclasses, however, may have a
+ * mutable result.
+ *
+ * @param cm the requested color model
+ * @param deviceBounds the bounding box in device coordinates, ignored
+ * @param userBounds the bounding box in user coordinates, ignored
+ * @param xform the bounds transformation, ignored
+ * @param hints any rendering hints, ignored
+ * @return a context for painting this solid color
+ */
+ public PaintContext createContext(ColorModel cm, Rectangle deviceBounds,
+ Rectangle2D userBounds,
+ AffineTransform xform,
+ RenderingHints hints)
+ {
+ if (context == null || !context.getColorModel().equals(cm))
+ context = new ColorPaintContext(cm,value);
+ return context;
+ }
+
+ /**
+ * Returns the transparency level of this color.
+ *
+ * @return one of {@link #OPAQUE}, {@link #BITMASK}, or {@link #TRANSLUCENT}
+ */
+ public int getTransparency()
+ {
+ // Do not inline getRGB() to this.value, because of SystemColor.
+ int alpha = getRGB() & ALPHA_MASK;
+ return alpha == (255 << 24) ? OPAQUE : alpha == 0 ? BITMASK : TRANSLUCENT;
+ }
+
+ /**
+ * Converts float values to integer value.
+ *
+ * @param red the red value
+ * @param green the green value
+ * @param blue the blue value
+ * @param alpha the alpha value
+ * @return the integer value made of 8-bit sections
+ * @throws IllegalArgumentException if parameters are out of range 0.0-1.0
+ */
+ private static int convert(float red, float green, float blue, float alpha)
+ {
+ if (red < 0 || red > 1 || green < 0 || green > 1 || blue < 0 || blue > 1
+ || alpha < 0 || alpha > 1)
+ throw new IllegalArgumentException("Bad RGB values");
+ int redval = Math.round(255 * red);
+ int greenval = Math.round(255 * green);
+ int blueval = Math.round(255 * blue);
+ int alphaval = Math.round(255 * alpha);
+ return (alphaval << 24) | (redval << 16) | (greenval << 8) | blueval;
+ }
+} // class Color
diff --git a/libjava/classpath/java/awt/ColorPaintContext.java b/libjava/classpath/java/awt/ColorPaintContext.java
new file mode 100644
index 000000000..5ba688617
--- /dev/null
+++ b/libjava/classpath/java/awt/ColorPaintContext.java
@@ -0,0 +1,195 @@
+/* ColorPaintContext.java -- context for painting solid colors
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.image.ColorModel;
+import java.awt.image.Raster;
+
+/**
+ * This class provides a paint context which will fill a rectanglar region of
+ * a raster scan with the given color. However, it is not yet completely
+ * implemented.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+class ColorPaintContext implements PaintContext
+{
+ /**
+ * The color to fill any raster with. Package visible for use in
+ * SystemColor.
+ */
+ final int color;
+ final ColorModel colorModel;
+
+ private ColorRaster cachedRaster;
+
+
+ /**
+ * Create the context for a given color.
+ *
+ * @param colorRGB The solid color to use.
+ */
+ ColorPaintContext(int colorRGB)
+ {
+ this(ColorModel.getRGBdefault(), colorRGB);
+ }
+
+ /**
+ * Create the context for a given color.
+ *
+ * @param cm The color model of this context.
+ * @param colorRGB The solid color to use.
+ */
+ ColorPaintContext(ColorModel cm,int colorRGB)
+ {
+ color = colorRGB;
+ colorModel = cm;
+ }
+
+ /**
+ * Release the resources allocated for the paint. As the color is constant,
+ * there aren't any resources.
+ */
+ public void dispose()
+ {
+ }
+
+ /**
+ * Return the color model of this context.
+ *
+ * @return the context color model
+ */
+ public ColorModel getColorModel()
+ {
+ return colorModel;
+ }
+
+ /**
+ * Return a raster containing the colors for the graphics operation.
+ *
+ * @param x the x-coordinate, in device space
+ * @param y the y-coordinate, in device space
+ * @param width the width, in device space
+ * @param height the height, in device space
+ * @return a raster for the given area and color
+ */
+ public Raster getRaster(int x, int y, int width, int height)
+ {
+ if( cachedRaster == null
+ || cachedRaster.getWidth() < width
+ || cachedRaster.getHeight() < height)
+ {
+ cachedRaster = new ColorRaster(colorModel, 0, 0, width, height, color);
+ }
+ return cachedRaster.createChild(0 ,0 ,width ,height ,0 ,0 , null);
+ }
+
+ /**
+ * A ColorRaster is a raster that is completely filled with one color. The
+ * data layout is taken from the color model given to the constructor.
+ */
+ private class ColorRaster extends Raster
+ {
+
+ /**
+ * Create a raster that is compaltible with the given color model and
+ * filled with the given color.
+ * @param cm The color model for this raster.
+ * @param x The smallest horizontal corrdinate in the raster.
+ * @param y The smallest vertical coordinate in the raster.
+ * @param width The width of the raster.
+ * @param height The height of the raster.
+ * @param rgbPixel The RGB value of the color for this raster.
+ */
+ ColorRaster(ColorModel cm,int x, int y, int width, int height, int rgbPixel)
+ {
+ super(cm.createCompatibleSampleModel(width,height),new Point(x,y));
+ Object pixel = cm.getDataElements(rgbPixel,null);
+ int[] pixelComps = cm.getComponents(pixel, null, 0);
+ int[] d = (int[]) multiplyData(pixelComps,null,width*height);
+ getSampleModel().setPixels(0, 0, width, height, d,
+ dataBuffer);
+ }
+
+
+
+ private Object multiplyData(Object src, Object dest, int factor)
+ {
+ Object from;
+ int srcLength = 0;
+ if (src instanceof byte[])
+ {
+ srcLength = ((byte[])src).length;
+
+ if (dest == null) dest = new byte[factor * srcLength];
+ }
+ else if (src instanceof short[])
+ {
+ srcLength = ((short[])src).length;
+ if (dest == null) dest = new short[factor * srcLength];
+ }
+ else if (src instanceof int[])
+ {
+ srcLength = ((int[]) src).length;
+ if (dest == null) dest = new int[factor * srcLength];
+ }
+ else
+ {
+ throw new ClassCastException("Unknown data buffer type");
+ }
+
+ System.arraycopy(src,0,dest,0,srcLength);
+
+ int count = 1;
+ while(count*2 < factor)
+ {
+ System.arraycopy(dest, 0, dest, count * srcLength, count*srcLength);
+ count *= 2;
+ }
+
+ if(factor > count)
+ System.arraycopy(dest,0, dest, count * srcLength,
+ (factor - count) * srcLength );
+
+ return dest;
+ }
+
+ }
+
+} // class ColorPaintContext
diff --git a/libjava/classpath/java/awt/Component.java b/libjava/classpath/java/awt/Component.java
new file mode 100644
index 000000000..d2878a9fd
--- /dev/null
+++ b/libjava/classpath/java/awt/Component.java
@@ -0,0 +1,7099 @@
+/* Component.java -- a graphics component
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2006
+ Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+//import gnu.java.awt.dnd.peer.gtk.GtkDropTargetContextPeer;
+
+import gnu.java.awt.ComponentReshapeEvent;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.awt.dnd.DropTarget;
+import java.awt.event.ActionEvent;
+import java.awt.event.AdjustmentEvent;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.HierarchyBoundsListener;
+import java.awt.event.HierarchyEvent;
+import java.awt.event.HierarchyListener;
+import java.awt.event.InputEvent;
+import java.awt.event.InputMethodEvent;
+import java.awt.event.InputMethodListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.event.MouseWheelEvent;
+import java.awt.event.MouseWheelListener;
+import java.awt.event.PaintEvent;
+import java.awt.event.WindowEvent;
+import java.awt.im.InputContext;
+import java.awt.im.InputMethodRequests;
+import java.awt.image.BufferStrategy;
+import java.awt.image.ColorModel;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.image.VolatileImage;
+import java.awt.peer.ComponentPeer;
+import java.awt.peer.LightweightPeer;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.util.Collections;
+import java.util.EventListener;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Set;
+import java.util.Vector;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleComponent;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleState;
+import javax.accessibility.AccessibleStateSet;
+
+/**
+ * The root of all evil. All graphical representations are subclasses of this
+ * giant class, which is designed for screen display and user interaction.
+ * This class can be extended directly to build a lightweight component (one
+ * not associated with a native window); lightweight components must reside
+ * inside a heavyweight window.
+ *
+ * <p>This class is Serializable, which has some big implications. A user can
+ * save the state of all graphical components in one VM, and reload them in
+ * another. Note that this class will only save Serializable listeners, and
+ * ignore the rest, without causing any serialization exceptions. However, by
+ * making a listener serializable, and adding it to another element, you link
+ * in that entire element to the state of this component. To get around this,
+ * use the idiom shown in the example below - make listeners non-serializable
+ * in inner classes, rather than using this object itself as the listener, if
+ * external objects do not need to save the state of this object.
+ *
+ * <pre>
+ * import java.awt.*;
+ * import java.awt.event.*;
+ * import java.io.Serializable;
+ * class MyApp implements Serializable
+ * {
+ * BigObjectThatShouldNotBeSerializedWithAButton bigOne;
+ * // Serializing aButton will not suck in an instance of MyApp, with its
+ * // accompanying field bigOne.
+ * Button aButton = new Button();
+ * class MyActionListener implements ActionListener
+ * {
+ * public void actionPerformed(ActionEvent e)
+ * {
+ * System.out.println("Hello There");
+ * }
+ * }
+ * MyApp()
+ * {
+ * aButton.addActionListener(new MyActionListener());
+ * }
+ * }
+ * </pre>
+ *
+ * <p>Status: Incomplete. The event dispatch mechanism is implemented. All
+ * other methods defined in the J2SE 1.3 API javadoc exist, but are mostly
+ * incomplete or only stubs; except for methods relating to the Drag and
+ * Drop, Input Method, and Accessibility frameworks: These methods are
+ * present but commented out.
+ *
+ * @author original author unknown
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.0
+ * @status still missing 1.4 support
+ */
+public abstract class Component
+ implements ImageObserver, MenuContainer, Serializable
+{
+ // Word to the wise - this file is huge. Search for '\f' (^L) for logical
+ // sectioning by fields, public API, private API, and nested classes.
+
+
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -7644114512714619750L;
+
+ /**
+ * Constant returned by the <code>getAlignmentY</code> method to indicate
+ * that the component wishes to be aligned to the top relative to
+ * other components.
+ *
+ * @see #getAlignmentY()
+ */
+ public static final float TOP_ALIGNMENT = 0;
+
+ /**
+ * Constant returned by the <code>getAlignmentY</code> and
+ * <code>getAlignmentX</code> methods to indicate
+ * that the component wishes to be aligned to the centdisper relative to
+ * other components.
+ *
+ * @see #getAlignmentX()
+ * @see #getAlignmentY()
+ */
+ public static final float CENTER_ALIGNMENT = 0.5f;
+
+ /**
+ * Constant returned by the <code>getAlignmentY</code> method to indicate
+ * that the component wishes to be aligned to the bottom relative to
+ * other components.
+ *
+ * @see #getAlignmentY()
+ */
+ public static final float BOTTOM_ALIGNMENT = 1;
+
+ /**
+ * Constant returned by the <code>getAlignmentX</code> method to indicate
+ * that the component wishes to be aligned to the right relative to
+ * other components.
+ *
+ * @see #getAlignmentX()
+ */
+ public static final float RIGHT_ALIGNMENT = 1;
+
+ /**
+ * Constant returned by the <code>getAlignmentX</code> method to indicate
+ * that the component wishes to be aligned to the left relative to
+ * other components.
+ *
+ * @see #getAlignmentX()
+ */
+ public static final float LEFT_ALIGNMENT = 0;
+
+ /**
+ * Make the treelock a String so that it can easily be identified
+ * in debug dumps. We clone the String in order to avoid a conflict in
+ * the unlikely event that some other package uses exactly the same string
+ * as a lock object.
+ */
+ static final Object treeLock = new String("AWT_TREE_LOCK");
+
+ /**
+ * The default maximum size.
+ */
+ private static final Dimension DEFAULT_MAX_SIZE
+ = new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
+
+ // Serialized fields from the serialization spec.
+
+ /**
+ * The x position of the component in the parent's coordinate system.
+ *
+ * @see #getLocation()
+ * @serial the x position
+ */
+ int x;
+
+ /**
+ * The y position of the component in the parent's coordinate system.
+ *
+ * @see #getLocation()
+ * @serial the y position
+ */
+ int y;
+
+ /**
+ * The component width.
+ *
+ * @see #getSize()
+ * @serial the width
+ */
+ int width;
+
+ /**
+ * The component height.
+ *
+ * @see #getSize()
+ * @serial the height
+ */
+ int height;
+
+ /**
+ * The foreground color for the component. This may be null.
+ *
+ * @see #getForeground()
+ * @see #setForeground(Color)
+ * @serial the foreground color
+ */
+ Color foreground;
+
+ /**
+ * The background color for the component. This may be null.
+ *
+ * @see #getBackground()
+ * @see #setBackground(Color)
+ * @serial the background color
+ */
+ Color background;
+
+ /**
+ * The default font used in the component. This may be null.
+ *
+ * @see #getFont()
+ * @see #setFont(Font)
+ * @serial the font
+ */
+ Font font;
+
+ /**
+ * The font in use by the peer, or null if there is no peer.
+ *
+ * @serial the peer's font
+ */
+ Font peerFont;
+
+ /**
+ * The cursor displayed when the pointer is over this component. This may
+ * be null.
+ *
+ * @see #getCursor()
+ * @see #setCursor(Cursor)
+ */
+ Cursor cursor;
+
+ /**
+ * The locale for the component.
+ *
+ * @see #getLocale()
+ * @see #setLocale(Locale)
+ */
+ Locale locale = Locale.getDefault ();
+
+ /**
+ * True if the object should ignore repaint events (usually because it is
+ * not showing).
+ *
+ * @see #getIgnoreRepaint()
+ * @see #setIgnoreRepaint(boolean)
+ * @serial true to ignore repaints
+ * @since 1.4
+ */
+ boolean ignoreRepaint;
+
+ /**
+ * True when the object is visible (although it is only showing if all
+ * ancestors are likewise visible). For component, this defaults to true.
+ *
+ * @see #isVisible()
+ * @see #setVisible(boolean)
+ * @serial true if visible
+ */
+ boolean visible = true;
+
+ /**
+ * True if the object is enabled, meaning it can interact with the user.
+ * For component, this defaults to true.
+ *
+ * @see #isEnabled()
+ * @see #setEnabled(boolean)
+ * @serial true if enabled
+ */
+ boolean enabled = true;
+
+ /**
+ * True if the object is valid. This is set to false any time a size
+ * adjustment means the component need to be layed out again.
+ *
+ * @see #isValid()
+ * @see #validate()
+ * @see #invalidate()
+ * @serial true if layout is valid
+ */
+ boolean valid;
+
+ /**
+ * The DropTarget for drag-and-drop operations.
+ *
+ * @see #getDropTarget()
+ * @see #setDropTarget(DropTarget)
+ * @serial the drop target, or null
+ * @since 1.2
+ */
+ DropTarget dropTarget;
+
+ /**
+ * The list of popup menus for this component.
+ *
+ * @see #add(PopupMenu)
+ * @serial the list of popups
+ */
+ Vector popups;
+
+ /**
+ * The component's name. May be null, in which case a default name is
+ * generated on the first use.
+ *
+ * @see #getName()
+ * @see #setName(String)
+ * @serial the name
+ */
+ String name;
+
+ /**
+ * True once the user has set the name. Note that the user may set the name
+ * to null.
+ *
+ * @see #name
+ * @see #getName()
+ * @see #setName(String)
+ * @serial true if the name has been explicitly set
+ */
+ boolean nameExplicitlySet;
+
+ /**
+ * Indicates if the object can be focused. Defaults to true for components.
+ *
+ * @see #isFocusable()
+ * @see #setFocusable(boolean)
+ * @since 1.4
+ */
+ boolean focusable = true;
+
+ /**
+ * Tracks whether this component's {@link #isFocusTraversable}
+ * method has been overridden.
+ *
+ * @since 1.4
+ */
+ int isFocusTraversableOverridden;
+
+ /**
+ * The focus traversal keys, if not inherited from the parent or
+ * default keyboard focus manager. These sets will contain only
+ * AWTKeyStrokes that represent press and release events to use as
+ * focus control.
+ *
+ * @see #getFocusTraversalKeys(int)
+ * @see #setFocusTraversalKeys(int, Set)
+ * @since 1.4
+ */
+ Set[] focusTraversalKeys;
+
+ /**
+ * True if focus traversal keys are enabled. This defaults to true for
+ * Component. If this is true, keystrokes in focusTraversalKeys are trapped
+ * and processed automatically rather than being passed on to the component.
+ *
+ * @see #getFocusTraversalKeysEnabled()
+ * @see #setFocusTraversalKeysEnabled(boolean)
+ * @since 1.4
+ */
+ boolean focusTraversalKeysEnabled = true;
+
+ /**
+ * Cached information on the minimum size. Should have been transient.
+ *
+ * @serial ignore
+ */
+ Dimension minSize;
+
+ /**
+ * Flag indicating whether the minimum size for the component has been set
+ * by a call to {@link #setMinimumSize(Dimension)} with a non-null value.
+ */
+ boolean minSizeSet;
+
+ /**
+ * The maximum size for the component.
+ * @see #setMaximumSize(Dimension)
+ */
+ Dimension maxSize;
+
+ /**
+ * A flag indicating whether the maximum size for the component has been set
+ * by a call to {@link #setMaximumSize(Dimension)} with a non-null value.
+ */
+ boolean maxSizeSet;
+
+ /**
+ * Cached information on the preferred size. Should have been transient.
+ *
+ * @serial ignore
+ */
+ Dimension prefSize;
+
+ /**
+ * Flag indicating whether the preferred size for the component has been set
+ * by a call to {@link #setPreferredSize(Dimension)} with a non-null value.
+ */
+ boolean prefSizeSet;
+
+ /**
+ * Set to true if an event is to be handled by this component, false if
+ * it is to be passed up the hierarcy.
+ *
+ * @see #dispatchEvent(AWTEvent)
+ * @serial true to process event locally
+ */
+ boolean newEventsOnly;
+
+ /**
+ * Set by subclasses to enable event handling of particular events, and
+ * left alone when modifying listeners. For component, this defaults to
+ * enabling only input methods.
+ *
+ * @see #enableInputMethods(boolean)
+ * @see AWTEvent
+ * @serial the mask of events to process
+ */
+ long eventMask = AWTEvent.INPUT_ENABLED_EVENT_MASK;
+
+ /**
+ * Describes all registered PropertyChangeListeners.
+ *
+ * @see #addPropertyChangeListener(PropertyChangeListener)
+ * @see #removePropertyChangeListener(PropertyChangeListener)
+ * @see #firePropertyChange(String, Object, Object)
+ * @serial the property change listeners
+ * @since 1.2
+ */
+ PropertyChangeSupport changeSupport;
+
+ /**
+ * True if the component has been packed (layed out).
+ *
+ * @serial true if this is packed
+ */
+ boolean isPacked;
+
+ /**
+ * The serialization version for this class. Currently at version 4.
+ *
+ * XXX How do we handle prior versions?
+ *
+ * @serial the serialization version
+ */
+ int componentSerializedDataVersion = 4;
+
+ /**
+ * The accessible context associated with this component. This is only set
+ * by subclasses.
+ *
+ * @see #getAccessibleContext()
+ * @serial the accessibility context
+ * @since 1.2
+ */
+ AccessibleContext accessibleContext;
+
+
+ // Guess what - listeners are special cased in serialization. See
+ // readObject and writeObject.
+
+ /** Component listener chain. */
+ transient ComponentListener componentListener;
+
+ /** Focus listener chain. */
+ transient FocusListener focusListener;
+
+ /** Key listener chain. */
+ transient KeyListener keyListener;
+
+ /** Mouse listener chain. */
+ transient MouseListener mouseListener;
+
+ /** Mouse motion listener chain. */
+ transient MouseMotionListener mouseMotionListener;
+
+ /**
+ * Mouse wheel listener chain.
+ *
+ * @since 1.4
+ */
+ transient MouseWheelListener mouseWheelListener;
+
+ /**
+ * Input method listener chain.
+ *
+ * @since 1.2
+ */
+ transient InputMethodListener inputMethodListener;
+
+ /**
+ * Hierarcy listener chain.
+ *
+ * @since 1.3
+ */
+ transient HierarchyListener hierarchyListener;
+
+ /**
+ * Hierarcy bounds listener chain.
+ *
+ * @since 1.3
+ */
+ transient HierarchyBoundsListener hierarchyBoundsListener;
+
+ // Anything else is non-serializable, and should be declared "transient".
+
+ /** The parent. */
+ transient Container parent;
+
+ /** The associated native peer. */
+ transient ComponentPeer peer;
+
+ /** The preferred component orientation. */
+ transient ComponentOrientation componentOrientation = ComponentOrientation.UNKNOWN;
+
+ /**
+ * The associated graphics configuration.
+ *
+ * @since 1.4
+ */
+ transient GraphicsConfiguration graphicsConfig;
+
+ /**
+ * The buffer strategy for repainting.
+ *
+ * @since 1.4
+ */
+ transient BufferStrategy bufferStrategy;
+
+ /**
+ * The number of hierarchy listeners of this container plus all of its
+ * children. This is needed for efficient handling of HierarchyEvents.
+ * These must be propagated to all child components with HierarchyListeners
+ * attached. To avoid traversal of the whole subtree, we keep track of
+ * the number of HierarchyListeners here and only walk the paths that
+ * actually have listeners.
+ */
+ int numHierarchyListeners;
+ int numHierarchyBoundsListeners;
+
+ /**
+ * true if requestFocus was called on this component when its
+ * top-level ancestor was not focusable.
+ */
+ private transient FocusEvent pendingFocusRequest = null;
+
+ /**
+ * The system properties that affect image updating.
+ */
+ private static transient boolean incrementalDraw;
+ private static transient Long redrawRate;
+
+ static
+ {
+ incrementalDraw = Boolean.getBoolean ("awt.image.incrementalDraw");
+ redrawRate = Long.getLong ("awt.image.redrawrate");
+ }
+
+ // Public and protected API.
+
+ /**
+ * Default constructor for subclasses. When Component is extended directly,
+ * it forms a lightweight component that must be hosted in an opaque native
+ * container higher in the tree.
+ */
+ protected Component()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the name of this component.
+ *
+ * @return the name of this component
+ * @see #setName(String)
+ * @since 1.1
+ */
+ public String getName()
+ {
+ if (name == null && ! nameExplicitlySet)
+ name = generateName();
+ return name;
+ }
+
+ /**
+ * Sets the name of this component to the specified name (this is a bound
+ * property with the name 'name').
+ *
+ * @param name the new name (<code>null</code> permitted).
+ * @see #getName()
+ * @since 1.1
+ */
+ public void setName(String name)
+ {
+ nameExplicitlySet = true;
+ String old = this.name;
+ this.name = name;
+ firePropertyChange("name", old, name);
+ }
+
+ /**
+ * Returns the parent of this component.
+ *
+ * @return the parent of this component
+ */
+ public Container getParent()
+ {
+ return parent;
+ }
+
+ /**
+ * Returns the native windowing system peer for this component. Only the
+ * platform specific implementation code should call this method.
+ *
+ * @return the peer for this component
+ * @deprecated user programs should not directly manipulate peers; use
+ * {@link #isDisplayable()} instead
+ */
+ // Classpath's Gtk peers rely on this.
+ public ComponentPeer getPeer()
+ {
+ return peer;
+ }
+
+ /**
+ * Set the associated drag-and-drop target, which receives events when this
+ * is enabled.
+ *
+ * @param dt the new drop target
+ * @see #isEnabled()
+ */
+ public void setDropTarget(DropTarget dt)
+ {
+ this.dropTarget = dt;
+
+ if (peer != null)
+ dropTarget.addNotify(peer);
+ }
+
+ /**
+ * Gets the associated drag-and-drop target, if there is one.
+ *
+ * @return the drop target
+ */
+ public DropTarget getDropTarget()
+ {
+ return dropTarget;
+ }
+
+ /**
+ * Returns the graphics configuration of this component, if there is one.
+ * If it has not been set, it is inherited from the parent.
+ *
+ * @return the graphics configuration, or null
+ * @since 1.3
+ */
+ public GraphicsConfiguration getGraphicsConfiguration()
+ {
+ GraphicsConfiguration conf = null;
+ synchronized (getTreeLock())
+ {
+ if (graphicsConfig != null)
+ {
+ conf = graphicsConfig;
+ }
+ else
+ {
+ Component par = getParent();
+ if (par != null)
+ {
+ conf = parent.getGraphicsConfiguration();
+ }
+ }
+ }
+ return conf;
+ }
+
+ /**
+ * Returns the object used for synchronization locks on this component
+ * when performing tree and layout functions.
+ *
+ * @return the synchronization lock for this component
+ */
+ public final Object getTreeLock()
+ {
+ return treeLock;
+ }
+
+ /**
+ * Returns the toolkit in use for this component. The toolkit is associated
+ * with the frame this component belongs to.
+ *
+ * @return the toolkit for this component
+ */
+ public Toolkit getToolkit()
+ {
+ // Only heavyweight peers can handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ Toolkit tk = null;
+ if (p != null)
+ {
+ tk = peer.getToolkit();
+ }
+ if (tk == null)
+ tk = Toolkit.getDefaultToolkit();
+ return tk;
+ }
+
+ /**
+ * Tests whether or not this component is valid. A invalid component needs
+ * to have its layout redone.
+ *
+ * @return true if this component is valid
+ * @see #validate()
+ * @see #invalidate()
+ */
+ public boolean isValid()
+ {
+ // Tests show that components are invalid as long as they are not showing, even after validate()
+ // has been called on them.
+ return peer != null && valid;
+ }
+
+ /**
+ * Tests if the component is displayable. It must be connected to a native
+ * screen resource. This reduces to checking that peer is not null. A
+ * containment hierarchy is made displayable when a window is packed or
+ * made visible.
+ *
+ * @return true if the component is displayable
+ * @see Container#add(Component)
+ * @see Container#remove(Component)
+ * @see Window#pack()
+ * @see Window#show()
+ * @see Window#dispose()
+ * @since 1.2
+ */
+ public boolean isDisplayable()
+ {
+ return peer != null;
+ }
+
+ /**
+ * Tests whether or not this component is visible. Except for top-level
+ * frames, components are initially visible.
+ *
+ * @return true if the component is visible
+ * @see #setVisible(boolean)
+ */
+ public boolean isVisible()
+ {
+ return visible;
+ }
+
+ /**
+ * Tests whether or not this component is actually being shown on
+ * the screen. This will be true if and only if it this component is
+ * visible and its parent components are all visible.
+ *
+ * @return true if the component is showing on the screen
+ * @see #setVisible(boolean)
+ */
+ public boolean isShowing()
+ {
+ Component par = parent;
+ return visible && peer != null && (par == null || par.isShowing());
+ }
+
+ /**
+ * Tests whether or not this component is enabled. Components are enabled
+ * by default, and must be enabled to receive user input or generate events.
+ *
+ * @return true if the component is enabled
+ * @see #setEnabled(boolean)
+ */
+ public boolean isEnabled()
+ {
+ return enabled;
+ }
+
+ /**
+ * Enables or disables this component. The component must be enabled to
+ * receive events (except that lightweight components always receive mouse
+ * events).
+ *
+ * @param enabled true to enable this component
+ *
+ * @see #isEnabled()
+ * @see #isLightweight()
+ *
+ * @since 1.1
+ */
+ public void setEnabled(boolean enabled)
+ {
+ enable(enabled);
+ }
+
+ /**
+ * Enables this component.
+ *
+ * @deprecated use {@link #setEnabled(boolean)} instead
+ */
+ public void enable()
+ {
+ if (! enabled)
+ {
+ // Need to lock the tree here, because the peers are involved.
+ synchronized (getTreeLock())
+ {
+ enabled = true;
+ ComponentPeer p = peer;
+ if (p != null)
+ p.enable();
+ }
+ }
+ }
+
+ /**
+ * Enables or disables this component.
+ *
+ * @param enabled true to enable this component
+ *
+ * @deprecated use {@link #setEnabled(boolean)} instead
+ */
+ public void enable(boolean enabled)
+ {
+ if (enabled)
+ enable();
+ else
+ disable();
+ }
+
+ /**
+ * Disables this component.
+ *
+ * @deprecated use {@link #setEnabled(boolean)} instead
+ */
+ public void disable()
+ {
+ if (enabled)
+ {
+ // Need to lock the tree here, because the peers are involved.
+ synchronized (getTreeLock())
+ {
+ enabled = false;
+ ComponentPeer p = peer;
+ if (p != null)
+ p.disable();
+ }
+ }
+ }
+
+ /**
+ * Checks if this image is painted to an offscreen image buffer that is
+ * later copied to screen (double buffering reduces flicker). This version
+ * returns false, so subclasses must override it if they provide double
+ * buffering.
+ *
+ * @return true if this is double buffered; defaults to false
+ */
+ public boolean isDoubleBuffered()
+ {
+ return false;
+ }
+
+ /**
+ * Enables or disables input method support for this component. By default,
+ * components have this enabled. Input methods are given the opportunity
+ * to process key events before this component and its listeners.
+ *
+ * @param enable true to enable input method processing
+ * @see #processKeyEvent(KeyEvent)
+ * @since 1.2
+ */
+ public void enableInputMethods(boolean enable)
+ {
+ if (enable)
+ eventMask |= AWTEvent.INPUT_ENABLED_EVENT_MASK;
+ else
+ eventMask &= ~AWTEvent.INPUT_ENABLED_EVENT_MASK;
+ }
+
+ /**
+ * Makes this component visible or invisible. Note that it wtill might
+ * not show the component, if a parent is invisible.
+ *
+ * @param visible true to make this component visible
+ *
+ * @see #isVisible()
+ *
+ * @since 1.1
+ */
+ public void setVisible(boolean visible)
+ {
+ // Inspection by subclassing shows that Sun's implementation calls
+ // show(boolean) which then calls show() or hide(). It is the show()
+ // method that is overriden in subclasses like Window.
+ show(visible);
+ }
+
+ /**
+ * Makes this component visible on the screen.
+ *
+ * @deprecated use {@link #setVisible(boolean)} instead
+ */
+ public void show()
+ {
+ // We must set visible before showing the peer. Otherwise the
+ // peer could post paint events before visible is true, in which
+ // case lightweight components are not initially painted --
+ // Container.paint first calls isShowing () before painting itself
+ // and its children.
+ if(! visible)
+ {
+ // Need to lock the tree here to avoid races and inconsistencies.
+ synchronized (getTreeLock())
+ {
+ visible = true;
+ // Avoid NullPointerExceptions by creating a local reference.
+ ComponentPeer currentPeer = peer;
+ if (currentPeer != null)
+ {
+ currentPeer.show();
+
+ // Fire HierarchyEvent.
+ fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED,
+ this, parent,
+ HierarchyEvent.SHOWING_CHANGED);
+
+ // The JDK repaints the component before invalidating the parent.
+ // So do we.
+ if (peer instanceof LightweightPeer)
+ repaint();
+ }
+
+ // Only post an event if this component actually has a listener
+ // or has this event explicitly enabled.
+ if (componentListener != null
+ || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0)
+ {
+ ComponentEvent ce =
+ new ComponentEvent(this,ComponentEvent.COMPONENT_SHOWN);
+ getToolkit().getSystemEventQueue().postEvent(ce);
+ }
+ }
+
+ // Invalidate the parent if we have one. The component itself must
+ // not be invalidated. We also avoid NullPointerException with
+ // a local reference here.
+ Container currentParent = parent;
+ if (currentParent != null)
+ currentParent.invalidate();
+
+ }
+ }
+
+ /**
+ * Makes this component visible or invisible.
+ *
+ * @param visible true to make this component visible
+ *
+ * @deprecated use {@link #setVisible(boolean)} instead
+ */
+ public void show(boolean visible)
+ {
+ if (visible)
+ show();
+ else
+ hide();
+ }
+
+ /**
+ * Hides this component so that it is no longer shown on the screen.
+ *
+ * @deprecated use {@link #setVisible(boolean)} instead
+ */
+ public void hide()
+ {
+ if (visible)
+ {
+ // Need to lock the tree here to avoid races and inconsistencies.
+ synchronized (getTreeLock())
+ {
+ visible = false;
+
+ // Avoid NullPointerExceptions by creating a local reference.
+ ComponentPeer currentPeer = peer;
+ if (currentPeer != null)
+ {
+ currentPeer.hide();
+
+ // Fire hierarchy event.
+ fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED,
+ this, parent,
+ HierarchyEvent.SHOWING_CHANGED);
+ // The JDK repaints the component before invalidating the
+ // parent. So do we. This only applies for lightweights.
+ if (peer instanceof LightweightPeer)
+ repaint();
+ }
+
+ // Only post an event if this component actually has a listener
+ // or has this event explicitly enabled.
+ if (componentListener != null
+ || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0)
+ {
+ ComponentEvent ce =
+ new ComponentEvent(this,ComponentEvent.COMPONENT_HIDDEN);
+ getToolkit().getSystemEventQueue().postEvent(ce);
+ }
+ }
+
+ // Invalidate the parent if we have one. The component itself need
+ // not be invalidated. We also avoid NullPointerException with
+ // a local reference here.
+ Container currentParent = parent;
+ if (currentParent != null)
+ currentParent.invalidate();
+
+ }
+ }
+
+ /**
+ * Returns this component's foreground color. If not set, this is inherited
+ * from the parent.
+ *
+ * @return this component's foreground color, or null
+ * @see #setForeground(Color)
+ */
+ public Color getForeground()
+ {
+ if (foreground != null)
+ return foreground;
+ return parent == null ? null : parent.getForeground();
+ }
+
+ /**
+ * Sets this component's foreground color to the specified color. This is a
+ * bound property.
+ *
+ * @param c the new foreground color
+ * @see #getForeground()
+ */
+ public void setForeground(Color c)
+ {
+ if (peer != null)
+ peer.setForeground(c);
+
+ Color previous = foreground;
+ foreground = c;
+ firePropertyChange("foreground", previous, c);
+ }
+
+ /**
+ * Tests if the foreground was explicitly set, or just inherited from the
+ * parent.
+ *
+ * @return true if the foreground has been set
+ * @since 1.4
+ */
+ public boolean isForegroundSet()
+ {
+ return foreground != null;
+ }
+
+ /**
+ * Returns this component's background color. If not set, this is inherited
+ * from the parent.
+ *
+ * @return the background color of the component, or null
+ * @see #setBackground(Color)
+ */
+ public Color getBackground()
+ {
+ if (background != null)
+ return background;
+ return parent == null ? null : parent.getBackground();
+ }
+
+ /**
+ * Sets this component's background color to the specified color. The parts
+ * of the component affected by the background color may by system dependent.
+ * This is a bound property.
+ *
+ * @param c the new background color
+ * @see #getBackground()
+ */
+ public void setBackground(Color c)
+ {
+ // return if the background is already set to that color.
+ if ((c != null) && c.equals(background))
+ return;
+
+ Color previous = background;
+ background = c;
+ if (peer != null && c != null)
+ peer.setBackground(c);
+ firePropertyChange("background", previous, c);
+ }
+
+ /**
+ * Tests if the background was explicitly set, or just inherited from the
+ * parent.
+ *
+ * @return true if the background has been set
+ * @since 1.4
+ */
+ public boolean isBackgroundSet()
+ {
+ return background != null;
+ }
+
+ /**
+ * Returns the font in use for this component. If not set, this is inherited
+ * from the parent.
+ *
+ * @return the font for this component
+ * @see #setFont(Font)
+ */
+ public Font getFont()
+ {
+ return getFontImpl();
+ }
+
+ /**
+ * Implementation of getFont(). This is pulled out of getFont() to prevent
+ * client programs from overriding this.
+ *
+ * @return the font of this component
+ */
+ private final Font getFontImpl()
+ {
+ Font f = font;
+ if (f == null)
+ {
+ Component p = parent;
+ if (p != null)
+ f = p.getFontImpl();
+ else
+ {
+ // It is important to return null here and not some kind of default
+ // font, otherwise the Swing UI would not install its fonts because
+ // it keeps non-UIResource fonts.
+ f = null;
+ }
+ }
+ return f;
+ }
+
+ /**
+ * Sets the font for this component to the specified font. This is a bound
+ * property.
+ *
+ * @param f the new font for this component
+ *
+ * @see #getFont()
+ */
+ public void setFont(Font f)
+ {
+ Font oldFont;
+ Font newFont;
+ // Synchronize on the tree because getFontImpl() relies on the hierarchy
+ // not beeing changed.
+ synchronized (getTreeLock())
+ {
+ // Synchronize on this here to guarantee thread safety wrt to the
+ // property values.
+ synchronized (this)
+ {
+ oldFont = font;
+ font = f;
+ newFont = f;
+ }
+ // Create local variable here for thread safety.
+ ComponentPeer p = peer;
+ if (p != null)
+ {
+ // The peer receives the real font setting, which can depend on
+ // the parent font when this component's font has been set to null.
+ f = getFont();
+ if (f != null)
+ {
+ p.setFont(f);
+ peerFont = f;
+ }
+ }
+ }
+
+ // Fire property change event.
+ firePropertyChange("font", oldFont, newFont);
+
+ // Invalidate when necessary as font changes can change the size of the
+ // component.
+ if (valid)
+ invalidate();
+ }
+
+ /**
+ * Tests if the font was explicitly set, or just inherited from the parent.
+ *
+ * @return true if the font has been set
+ * @since 1.4
+ */
+ public boolean isFontSet()
+ {
+ return font != null;
+ }
+
+ /**
+ * Returns the locale for this component. If this component does not
+ * have a locale, the locale of the parent component is returned.
+ *
+ * @return the locale for this component
+ * @throws IllegalComponentStateException if it has no locale or parent
+ * @see #setLocale(Locale)
+ * @since 1.1
+ */
+ public Locale getLocale()
+ {
+ if (locale != null)
+ return locale;
+ if (parent == null)
+ throw new IllegalComponentStateException
+ ("Component has no parent: can't determine Locale");
+ return parent.getLocale();
+ }
+
+ /**
+ * Sets the locale for this component to the specified locale. This is a
+ * bound property.
+ *
+ * @param newLocale the new locale for this component
+ */
+ public void setLocale(Locale newLocale)
+ {
+ if (locale == newLocale)
+ return;
+
+ Locale oldLocale = locale;
+ locale = newLocale;
+ firePropertyChange("locale", oldLocale, newLocale);
+ // New writing/layout direction or more/less room for localized labels.
+ invalidate();
+ }
+
+ /**
+ * Returns the color model of the device this componet is displayed on.
+ *
+ * @return this object's color model
+ * @see Toolkit#getColorModel()
+ */
+ public ColorModel getColorModel()
+ {
+ GraphicsConfiguration config = getGraphicsConfiguration();
+ return config != null ? config.getColorModel()
+ : getToolkit().getColorModel();
+ }
+
+ /**
+ * Returns the location of this component's top left corner relative to
+ * its parent component. This may be outdated, so for synchronous behavior,
+ * you should use a component listner.
+ *
+ * @return the location of this component
+ * @see #setLocation(int, int)
+ * @see #getLocationOnScreen()
+ * @since 1.1
+ */
+ public Point getLocation()
+ {
+ return location ();
+ }
+
+ /**
+ * Returns the location of this component's top left corner in screen
+ * coordinates.
+ *
+ * @return the location of this component in screen coordinates
+ * @throws IllegalComponentStateException if the component is not showing
+ */
+ public Point getLocationOnScreen()
+ {
+ if (! isShowing())
+ throw new IllegalComponentStateException("component "
+ + getClass().getName()
+ + " not showing");
+
+ // Need to lock the tree here. We get crazy races and explosions when
+ // the tree changes while we are trying to find the location of this
+ // component.
+ synchronized (getTreeLock())
+ {
+ // Only a heavyweight peer can answer the question for the screen
+ // location. So we are going through the hierarchy until we find
+ // one and add up the offsets while doing so.
+ int offsX = 0;
+ int offsY = 0;
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ offsX += comp.x;
+ offsY += comp.y;
+ comp = comp.parent;
+ p = comp == null ? null: comp.peer;
+ }
+ // Now we have a heavyweight component.
+ assert ! (p instanceof LightweightPeer);
+ Point loc = p.getLocationOnScreen();
+ loc.x += offsX;
+ loc.y += offsY;
+ return loc;
+ }
+ }
+
+ /**
+ * Returns the location of this component's top left corner relative to
+ * its parent component.
+ *
+ * @return the location of this component
+ * @deprecated use {@link #getLocation()} instead
+ */
+ public Point location()
+ {
+ return new Point (x, y);
+ }
+
+ /**
+ * Moves this component to the specified location, relative to the parent's
+ * coordinates. The coordinates are the new upper left corner of this
+ * component.
+ *
+ * @param x the new X coordinate of this component
+ * @param y the new Y coordinate of this component
+ * @see #getLocation()
+ * @see #setBounds(int, int, int, int)
+ */
+ public void setLocation(int x, int y)
+ {
+ move (x, y);
+ }
+
+ /**
+ * Moves this component to the specified location, relative to the parent's
+ * coordinates. The coordinates are the new upper left corner of this
+ * component.
+ *
+ * @param x the new X coordinate of this component
+ * @param y the new Y coordinate of this component
+ * @deprecated use {@link #setLocation(int, int)} instead
+ */
+ public void move(int x, int y)
+ {
+ setBounds(x, y, this.width, this.height);
+ }
+
+ /**
+ * Moves this component to the specified location, relative to the parent's
+ * coordinates. The coordinates are the new upper left corner of this
+ * component.
+ *
+ * @param p new coordinates for this component
+ * @throws NullPointerException if p is null
+ * @see #getLocation()
+ * @see #setBounds(int, int, int, int)
+ * @since 1.1
+ */
+ public void setLocation(Point p)
+ {
+ setLocation(p.x, p.y);
+ }
+
+ /**
+ * Returns the size of this object.
+ *
+ * @return the size of this object
+ * @see #setSize(int, int)
+ * @since 1.1
+ */
+ public Dimension getSize()
+ {
+ return size ();
+ }
+
+ /**
+ * Returns the size of this object.
+ *
+ * @return the size of this object
+ * @deprecated use {@link #getSize()} instead
+ */
+ public Dimension size()
+ {
+ return new Dimension (width, height);
+ }
+
+ /**
+ * Sets the size of this component to the specified width and height.
+ *
+ * @param width the new width of this component
+ * @param height the new height of this component
+ * @see #getSize()
+ * @see #setBounds(int, int, int, int)
+ */
+ public void setSize(int width, int height)
+ {
+ resize (width, height);
+ }
+
+ /**
+ * Sets the size of this component to the specified value.
+ *
+ * @param width the new width of the component
+ * @param height the new height of the component
+ * @deprecated use {@link #setSize(int, int)} instead
+ */
+ public void resize(int width, int height)
+ {
+ setBounds(this.x, this.y, width, height);
+ }
+
+ /**
+ * Sets the size of this component to the specified value.
+ *
+ * @param d the new size of this component
+ * @throws NullPointerException if d is null
+ * @see #setSize(int, int)
+ * @see #setBounds(int, int, int, int)
+ * @since 1.1
+ */
+ public void setSize(Dimension d)
+ {
+ resize (d);
+ }
+
+ /**
+ * Sets the size of this component to the specified value.
+ *
+ * @param d the new size of this component
+ * @throws NullPointerException if d is null
+ * @deprecated use {@link #setSize(Dimension)} instead
+ */
+ public void resize(Dimension d)
+ {
+ resize (d.width, d.height);
+ }
+
+ /**
+ * Returns a bounding rectangle for this component. Note that the
+ * returned rectange is relative to this component's parent, not to
+ * the screen.
+ *
+ * @return the bounding rectangle for this component
+ * @see #setBounds(int, int, int, int)
+ * @see #getLocation()
+ * @see #getSize()
+ */
+ public Rectangle getBounds()
+ {
+ return bounds ();
+ }
+
+ /**
+ * Returns a bounding rectangle for this component. Note that the
+ * returned rectange is relative to this component's parent, not to
+ * the screen.
+ *
+ * @return the bounding rectangle for this component
+ * @deprecated use {@link #getBounds()} instead
+ */
+ public Rectangle bounds()
+ {
+ return new Rectangle (x, y, width, height);
+ }
+
+ /**
+ * Sets the bounding rectangle for this component to the specified values.
+ * Note that these coordinates are relative to the parent, not to the screen.
+ *
+ * @param x the X coordinate of the upper left corner of the rectangle
+ * @param y the Y coordinate of the upper left corner of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @see #getBounds()
+ * @see #setLocation(int, int)
+ * @see #setLocation(Point)
+ * @see #setSize(int, int)
+ * @see #setSize(Dimension)
+ * @since 1.1
+ */
+ public void setBounds(int x, int y, int w, int h)
+ {
+ reshape (x, y, w, h);
+ }
+
+ /**
+ * Sets the bounding rectangle for this component to the specified values.
+ * Note that these coordinates are relative to the parent, not to the screen.
+ *
+ * @param x the X coordinate of the upper left corner of the rectangle
+ * @param y the Y coordinate of the upper left corner of the rectangle
+ * @param width the width of the rectangle
+ * @param height the height of the rectangle
+ * @deprecated use {@link #setBounds(int, int, int, int)} instead
+ */
+ public void reshape(int x, int y, int width, int height)
+ {
+ // We need to lock the tree here, otherwise we risk races and
+ // inconsistencies.
+ synchronized (getTreeLock())
+ {
+ int oldx = this.x;
+ int oldy = this.y;
+ int oldwidth = this.width;
+ int oldheight = this.height;
+
+ boolean resized = oldwidth != width || oldheight != height;
+ boolean moved = oldx != x || oldy != y;
+
+ if (resized || moved)
+ {
+ // Update the fields.
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+
+ if (peer != null)
+ {
+ peer.setBounds (x, y, width, height);
+ if (resized)
+ invalidate();
+ if (parent != null && parent.valid)
+ parent.invalidate();
+ }
+
+ // Send some events to interested listeners.
+ notifyReshape(resized, moved);
+
+ // Repaint this component and the parent if appropriate.
+ if (parent != null && peer instanceof LightweightPeer
+ && isShowing())
+ {
+ // The parent repaints the area that we occupied before.
+ parent.repaint(oldx, oldy, oldwidth, oldheight);
+ // This component repaints the area that we occupy now.
+ repaint();
+ }
+ }
+ }
+ }
+
+ /**
+ * Sends notification to interested listeners about resizing and/or moving
+ * the component. If this component has interested
+ * component listeners or the corresponding event mask enabled, then
+ * COMPONENT_MOVED and/or COMPONENT_RESIZED events are posted to the event
+ * queue.
+ *
+ * @param resized true if the component has been resized, false otherwise
+ * @param moved true if the component has been moved, false otherwise
+ */
+ void notifyReshape(boolean resized, boolean moved)
+ {
+ // Only post an event if this component actually has a listener
+ // or has this event explicitly enabled.
+ if (componentListener != null
+ || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0)
+ {
+ // Fire component event on this component.
+ if (moved)
+ {
+ ComponentEvent ce = new ComponentEvent(this,
+ ComponentEvent.COMPONENT_MOVED);
+ getToolkit().getSystemEventQueue().postEvent(ce);
+ }
+ if (resized)
+ {
+ ComponentEvent ce = new ComponentEvent(this,
+ ComponentEvent.COMPONENT_RESIZED);
+ getToolkit().getSystemEventQueue().postEvent(ce);
+ }
+ }
+ }
+
+ /**
+ * Sets the bounding rectangle for this component to the specified
+ * rectangle. Note that these coordinates are relative to the parent, not
+ * to the screen.
+ *
+ * @param r the new bounding rectangle
+ * @throws NullPointerException if r is null
+ * @see #getBounds()
+ * @see #setLocation(Point)
+ * @see #setSize(Dimension)
+ * @since 1.1
+ */
+ public void setBounds(Rectangle r)
+ {
+ setBounds (r.x, r.y, r.width, r.height);
+ }
+
+ /**
+ * Gets the x coordinate of the upper left corner. This is more efficient
+ * than getBounds().x or getLocation().x.
+ *
+ * @return the current x coordinate
+ * @since 1.2
+ */
+ public int getX()
+ {
+ return x;
+ }
+
+ /**
+ * Gets the y coordinate of the upper left corner. This is more efficient
+ * than getBounds().y or getLocation().y.
+ *
+ * @return the current y coordinate
+ * @since 1.2
+ */
+ public int getY()
+ {
+ return y;
+ }
+
+ /**
+ * Gets the width of the component. This is more efficient than
+ * getBounds().width or getSize().width.
+ *
+ * @return the current width
+ * @since 1.2
+ */
+ public int getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Gets the height of the component. This is more efficient than
+ * getBounds().height or getSize().height.
+ *
+ * @return the current width
+ * @since 1.2
+ */
+ public int getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * Returns the bounds of this component. This allows reuse of an existing
+ * rectangle, if r is non-null.
+ *
+ * @param r the rectangle to use, or null
+ * @return the bounds
+ */
+ public Rectangle getBounds(Rectangle r)
+ {
+ if (r == null)
+ r = new Rectangle();
+ r.x = x;
+ r.y = y;
+ r.width = width;
+ r.height = height;
+ return r;
+ }
+
+ /**
+ * Returns the size of this component. This allows reuse of an existing
+ * dimension, if d is non-null.
+ *
+ * @param d the dimension to use, or null
+ * @return the size
+ */
+ public Dimension getSize(Dimension d)
+ {
+ if (d == null)
+ d = new Dimension();
+ d.width = width;
+ d.height = height;
+ return d;
+ }
+
+ /**
+ * Returns the location of this component. This allows reuse of an existing
+ * point, if p is non-null.
+ *
+ * @param p the point to use, or null
+ * @return the location
+ */
+ public Point getLocation(Point p)
+ {
+ if (p == null)
+ p = new Point();
+ p.x = x;
+ p.y = y;
+ return p;
+ }
+
+ /**
+ * Tests if this component is opaque. All "heavyweight" (natively-drawn)
+ * components are opaque. A component is opaque if it draws all pixels in
+ * the bounds; a lightweight component is partially transparent if it lets
+ * pixels underneath show through. Subclasses that guarantee that all pixels
+ * will be drawn should override this.
+ *
+ * @return true if this is opaque
+ * @see #isLightweight()
+ * @since 1.2
+ */
+ public boolean isOpaque()
+ {
+ return ! isLightweight();
+ }
+
+ /**
+ * Return whether the component is lightweight. That means the component has
+ * no native peer, but is displayable. This applies to subclasses of
+ * Component not in this package, such as javax.swing.
+ *
+ * @return true if the component has a lightweight peer
+ * @see #isDisplayable()
+ * @since 1.2
+ */
+ public boolean isLightweight()
+ {
+ return peer instanceof LightweightPeer;
+ }
+
+ /**
+ * Returns the component's preferred size.
+ *
+ * @return the component's preferred size
+ * @see #getMinimumSize()
+ * @see #setPreferredSize(Dimension)
+ * @see LayoutManager
+ */
+ public Dimension getPreferredSize()
+ {
+ return preferredSize();
+ }
+
+ /**
+ * Sets the preferred size that will be returned by
+ * {@link #getPreferredSize()} always, and sends a
+ * {@link PropertyChangeEvent} (with the property name 'preferredSize') to
+ * all registered listeners.
+ *
+ * @param size the preferred size (<code>null</code> permitted).
+ *
+ * @since 1.5
+ *
+ * @see #getPreferredSize()
+ */
+ public void setPreferredSize(Dimension size)
+ {
+ Dimension old = prefSizeSet ? prefSize : null;
+ prefSize = size;
+ prefSizeSet = (size != null);
+ firePropertyChange("preferredSize", old, size);
+ }
+
+ /**
+ * Returns <code>true</code> if the current preferred size is not
+ * <code>null</code> and was set by a call to
+ * {@link #setPreferredSize(Dimension)}, otherwise returns <code>false</code>.
+ *
+ * @return A boolean.
+ *
+ * @since 1.5
+ */
+ public boolean isPreferredSizeSet()
+ {
+ return prefSizeSet;
+ }
+
+ /**
+ * Returns the component's preferred size.
+ *
+ * @return the component's preferred size
+ * @deprecated use {@link #getPreferredSize()} instead
+ */
+ public Dimension preferredSize()
+ {
+ // Create a new Dimension object, so that the application doesn't mess
+ // with the actual values.
+ return new Dimension(preferredSizeImpl());
+ }
+
+ /**
+ * The actual calculation is pulled out of preferredSize() so that
+ * we can call it from Container.preferredSize() and avoid creating a
+ * new intermediate Dimension object.
+ *
+ * @return the preferredSize of the component
+ */
+ Dimension preferredSizeImpl()
+ {
+ Dimension size = prefSize;
+ // Try to use a cached value.
+ if (size == null || !(valid || prefSizeSet))
+ {
+ // We need to lock here, because the calculation depends on the
+ // component structure not changing.
+ synchronized (getTreeLock())
+ {
+ ComponentPeer p = peer;
+ if (p != null)
+ size = peer.preferredSize();
+ else
+ size = minimumSizeImpl();
+ }
+ }
+ return size;
+ }
+
+ /**
+ * Returns the component's minimum size.
+ *
+ * @return the component's minimum size
+ * @see #getPreferredSize()
+ * @see #setMinimumSize(Dimension)
+ * @see LayoutManager
+ */
+ public Dimension getMinimumSize()
+ {
+ return minimumSize();
+ }
+
+ /**
+ * Sets the minimum size that will be returned by {@link #getMinimumSize()}
+ * always, and sends a {@link PropertyChangeEvent} (with the property name
+ * 'minimumSize') to all registered listeners.
+ *
+ * @param size the minimum size (<code>null</code> permitted).
+ *
+ * @since 1.5
+ *
+ * @see #getMinimumSize()
+ */
+ public void setMinimumSize(Dimension size)
+ {
+ Dimension old = minSizeSet ? minSize : null;
+ minSize = size;
+ minSizeSet = (size != null);
+ firePropertyChange("minimumSize", old, size);
+ }
+
+ /**
+ * Returns <code>true</code> if the current minimum size is not
+ * <code>null</code> and was set by a call to
+ * {@link #setMinimumSize(Dimension)}, otherwise returns <code>false</code>.
+ *
+ * @return A boolean.
+ *
+ * @since 1.5
+ */
+ public boolean isMinimumSizeSet()
+ {
+ return minSizeSet;
+ }
+
+ /**
+ * Returns the component's minimum size.
+ *
+ * @return the component's minimum size
+ * @deprecated use {@link #getMinimumSize()} instead
+ */
+ public Dimension minimumSize()
+ {
+ // Create a new Dimension object, so that the application doesn't mess
+ // with the actual values.
+ return new Dimension(minimumSizeImpl());
+ }
+
+ /**
+ * The actual calculation is pulled out of minimumSize() so that
+ * we can call it from Container.preferredSize() and
+ * Component.preferredSizeImpl and avoid creating a
+ * new intermediate Dimension object.
+ *
+ * @return the minimum size of the component
+ */
+ Dimension minimumSizeImpl()
+ {
+ Dimension size = minSize;
+ if (size == null || !(valid || minSizeSet))
+ {
+ // We need to lock here, because the calculation depends on the
+ // component structure not changing.
+ synchronized (getTreeLock())
+ {
+ ComponentPeer p = peer;
+ if (p != null)
+ size = peer.minimumSize();
+ else
+ size = size();
+ }
+ }
+ return size;
+ }
+
+ /**
+ * Returns the component's maximum size.
+ *
+ * @return the component's maximum size
+ * @see #getMinimumSize()
+ * @see #setMaximumSize(Dimension)
+ * @see #getPreferredSize()
+ * @see LayoutManager
+ */
+ public Dimension getMaximumSize()
+ {
+ return new Dimension(maximumSizeImpl());
+ }
+
+ /**
+ * This is pulled out from getMaximumSize(), so that we can access it
+ * from Container.getMaximumSize() without creating an additional
+ * intermediate Dimension object.
+ *
+ * @return the maximum size of the component
+ */
+ Dimension maximumSizeImpl()
+ {
+ Dimension size;
+ if (maxSizeSet)
+ size = maxSize;
+ else
+ size = DEFAULT_MAX_SIZE;
+ return size;
+ }
+
+ /**
+ * Sets the maximum size that will be returned by {@link #getMaximumSize()}
+ * always, and sends a {@link PropertyChangeEvent} (with the property name
+ * 'maximumSize') to all registered listeners.
+ *
+ * @param size the maximum size (<code>null</code> permitted).
+ *
+ * @since 1.5
+ *
+ * @see #getMaximumSize()
+ */
+ public void setMaximumSize(Dimension size)
+ {
+ Dimension old = maxSizeSet ? maxSize : null;
+ maxSize = size;
+ maxSizeSet = (size != null);
+ firePropertyChange("maximumSize", old, size);
+ }
+
+ /**
+ * Returns <code>true</code> if the current maximum size is not
+ * <code>null</code> and was set by a call to
+ * {@link #setMaximumSize(Dimension)}, otherwise returns <code>false</code>.
+ *
+ * @return A boolean.
+ *
+ * @since 1.5
+ */
+ public boolean isMaximumSizeSet()
+ {
+ return maxSizeSet;
+ }
+
+ /**
+ * Returns the preferred horizontal alignment of this component. The value
+ * returned will be between {@link #LEFT_ALIGNMENT} and
+ * {@link #RIGHT_ALIGNMENT}, inclusive.
+ *
+ * @return the preferred horizontal alignment of this component
+ */
+ public float getAlignmentX()
+ {
+ return CENTER_ALIGNMENT;
+ }
+
+ /**
+ * Returns the preferred vertical alignment of this component. The value
+ * returned will be between {@link #TOP_ALIGNMENT} and
+ * {@link #BOTTOM_ALIGNMENT}, inclusive.
+ *
+ * @return the preferred vertical alignment of this component
+ */
+ public float getAlignmentY()
+ {
+ return CENTER_ALIGNMENT;
+ }
+
+ /**
+ * Calls the layout manager to re-layout the component. This is called
+ * during validation of a container in most cases.
+ *
+ * @see #validate()
+ * @see LayoutManager
+ */
+ public void doLayout()
+ {
+ layout ();
+ }
+
+ /**
+ * Calls the layout manager to re-layout the component. This is called
+ * during validation of a container in most cases.
+ *
+ * @deprecated use {@link #doLayout()} instead
+ */
+ public void layout()
+ {
+ // Nothing to do unless we're a container.
+ }
+
+ /**
+ * Called to ensure that the layout for this component is valid. This is
+ * usually called on containers.
+ *
+ * @see #invalidate()
+ * @see #doLayout()
+ * @see LayoutManager
+ * @see Container#validate()
+ */
+ public void validate()
+ {
+ if (! valid)
+ {
+ // Synchronize on the tree here as this might change the layout
+ // of the hierarchy.
+ synchronized (getTreeLock())
+ {
+ // Create local variables for thread safety.
+ ComponentPeer p = peer;
+ if (p != null)
+ {
+ // Possibly update the peer's font.
+ Font newFont = getFont();
+ Font oldFont = peerFont;
+ // Only update when the font really changed.
+ if (newFont != oldFont
+ && (oldFont == null || ! oldFont.equals(newFont)))
+ {
+ p.setFont(newFont);
+ peerFont = newFont;
+ }
+ // Let the peer perform any layout.
+ p.layout();
+ }
+ }
+ valid = true;
+ }
+ }
+
+ /**
+ * Invalidates this component and all of its parent components. This will
+ * cause them to have their layout redone. This is called frequently, so
+ * make it fast.
+ */
+ public void invalidate()
+ {
+ // Need to lock here, to avoid races and other ugly stuff when doing
+ // layout or structure changes in other threads.
+ synchronized (getTreeLock())
+ {
+ // Invalidate.
+ valid = false;
+
+ // Throw away cached layout information.
+ if (! minSizeSet)
+ minSize = null;
+ if (! prefSizeSet)
+ prefSize = null;
+ if (! maxSizeSet)
+ maxSize = null;
+
+ // Also invalidate the parent, if it hasn't already been invalidated.
+ if (parent != null && parent.isValid())
+ parent.invalidate();
+ }
+ }
+
+ /**
+ * Returns a graphics object for this component. Returns <code>null</code>
+ * if this component is not currently displayed on the screen.
+ *
+ * @return a graphics object for this component
+ * @see #paint(Graphics)
+ */
+ public Graphics getGraphics()
+ {
+ // Only heavyweight peers can handle this.
+ ComponentPeer p = peer;
+ Graphics g = null;
+ if (p instanceof LightweightPeer)
+ {
+ if (parent != null)
+ {
+ g = parent.getGraphics();
+ if (g != null)
+ {
+ g.translate(x, y);
+ g.setClip(0, 0, width, height);
+ g.setFont(getFont());
+ }
+ }
+ }
+ else
+ {
+ if (p != null)
+ g = p.getGraphics();
+ }
+ return g;
+ }
+
+ /**
+ * Returns the font metrics for the specified font in this component.
+ *
+ * @param font the font to retrieve metrics for
+ * @return the font metrics for the specified font
+ * @throws NullPointerException if font is null
+ * @see #getFont()
+ * @see Toolkit#getFontMetrics(Font)
+ */
+ public FontMetrics getFontMetrics(Font font)
+ {
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ return p == null ? getToolkit().getFontMetrics(font)
+ : p.getFontMetrics(font);
+ }
+
+ /**
+ * Sets the cursor for this component to the specified cursor. The cursor
+ * is displayed when the point is contained by the component, and the
+ * component is visible, displayable, and enabled. This is inherited by
+ * subcomponents unless they set their own cursor.
+ *
+ * @param cursor the new cursor for this component
+ * @see #isEnabled()
+ * @see #isShowing()
+ * @see #getCursor()
+ * @see #contains(int, int)
+ * @see Toolkit#createCustomCursor(Image, Point, String)
+ */
+ public void setCursor(Cursor cursor)
+ {
+ this.cursor = cursor;
+
+ // Only heavyweight peers handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ if (p != null)
+ p.setCursor(cursor);
+ }
+
+ /**
+ * Returns the cursor for this component. If not set, this is inherited
+ * from the parent, or from Cursor.getDefaultCursor().
+ *
+ * @return the cursor for this component
+ */
+ public Cursor getCursor()
+ {
+ if (cursor != null)
+ return cursor;
+ return parent != null ? parent.getCursor() : Cursor.getDefaultCursor();
+ }
+
+ /**
+ * Tests if the cursor was explicitly set, or just inherited from the parent.
+ *
+ * @return true if the cursor has been set
+ * @since 1.4
+ */
+ public boolean isCursorSet()
+ {
+ return cursor != null;
+ }
+
+ /**
+ * Paints this component on the screen. The clipping region in the graphics
+ * context will indicate the region that requires painting. This is called
+ * whenever the component first shows, or needs to be repaired because
+ * something was temporarily drawn on top. It is not necessary for
+ * subclasses to call <code>super.paint(g)</code>. Components with no area
+ * are not painted.
+ *
+ * @param g the graphics context for this paint job
+ * @see #update(Graphics)
+ */
+ public void paint(Graphics g)
+ {
+ // This is a callback method and is meant to be overridden by subclasses
+ // that want to perform custom painting.
+ }
+
+ /**
+ * Updates this component. This is called for heavyweight components in
+ * response to {@link #repaint()}. The default implementation simply forwards
+ * to {@link #paint(Graphics)}. The coordinates of the graphics are
+ * relative to this component. Subclasses should call either
+ * <code>super.update(g)</code> or <code>paint(g)</code>.
+ *
+ * @param g the graphics context for this update
+ *
+ * @see #paint(Graphics)
+ * @see #repaint()
+ */
+ public void update(Graphics g)
+ {
+ // Note 1: We used to clear the background here for lightweights and
+ // toplevel components. Tests show that this is not what the JDK does
+ // here. Note that there is some special handling and background
+ // clearing code in Container.update(Graphics).
+
+ // Note 2 (for peer implementors): The JDK doesn't seem call update() for
+ // toplevel components, even when an UPDATE event is sent (as a result
+ // of repaint).
+ paint(g);
+ }
+
+ /**
+ * Paints this entire component, including any sub-components.
+ *
+ * @param g the graphics context for this paint job
+ *
+ * @see #paint(Graphics)
+ */
+ public void paintAll(Graphics g)
+ {
+ if (isShowing())
+ {
+ validate();
+ if (peer instanceof LightweightPeer)
+ paint(g);
+ else
+ peer.paint(g);
+ }
+ }
+
+ /**
+ * Repaint this entire component. The <code>update()</code> method
+ * on this component will be called as soon as possible.
+ *
+ * @see #update(Graphics)
+ * @see #repaint(long, int, int, int, int)
+ */
+ public void repaint()
+ {
+ repaint(0, 0, 0, width, height);
+ }
+
+ /**
+ * Repaint this entire component. The <code>update()</code> method on this
+ * component will be called in approximate the specified number of
+ * milliseconds.
+ *
+ * @param tm milliseconds before this component should be repainted
+ * @see #paint(Graphics)
+ * @see #repaint(long, int, int, int, int)
+ */
+ public void repaint(long tm)
+ {
+ repaint(tm, 0, 0, width, height);
+ }
+
+ /**
+ * Repaints the specified rectangular region within this component. The
+ * <code>update</code> method on this component will be called as soon as
+ * possible. The coordinates are relative to this component.
+ *
+ * @param x the X coordinate of the upper left of the region to repaint
+ * @param y the Y coordinate of the upper left of the region to repaint
+ * @param w the width of the region to repaint
+ * @param h the height of the region to repaint
+ * @see #update(Graphics)
+ * @see #repaint(long, int, int, int, int)
+ */
+ public void repaint(int x, int y, int w, int h)
+ {
+ repaint(0, x, y, w, h);
+ }
+
+ /**
+ * Repaints the specified rectangular region within this component. The
+ * <code>update</code> method on this component will be called in
+ * approximately the specified number of milliseconds. The coordinates
+ * are relative to this component.
+ *
+ * @param tm milliseconds before this component should be repainted
+ * @param x the X coordinate of the upper left of the region to repaint
+ * @param y the Y coordinate of the upper left of the region to repaint
+ * @param width the width of the region to repaint
+ * @param height the height of the region to repaint
+ * @see #update(Graphics)
+ */
+ public void repaint(long tm, int x, int y, int width, int height)
+ {
+ // The repaint() call has previously been delegated to
+ // {@link ComponentPeer.repaint()}. Testing on the JDK using some
+ // dummy peers show that this methods is never called. I think it makes
+ // sense to actually perform the tasks below here, since it's pretty
+ // much peer independent anyway, and makes sure only heavyweights are
+ // bothered by this.
+ ComponentPeer p = peer;
+
+ // Let the nearest heavyweight parent handle repainting for lightweight
+ // components.
+ // We need to recursivly call repaint() on the parent here, since
+ // a (lightweight) parent component might have overridden repaint()
+ // to perform additional custom tasks.
+
+ if (p instanceof LightweightPeer)
+ {
+ // We perform some boundary checking to restrict the paint
+ // region to this component.
+ if (parent != null)
+ {
+ int px = this.x + Math.max(0, x);
+ int py = this.y + Math.max(0, y);
+ int pw = Math.min(this.width, width);
+ int ph = Math.min(this.height, height);
+ parent.repaint(tm, px, py, pw, ph);
+ }
+ }
+ else
+ {
+ // Now send an UPDATE event to the heavyweight component that we've found.
+ if (isVisible() && p != null && width > 0 && height > 0)
+ {
+ PaintEvent pe = new PaintEvent(this, PaintEvent.UPDATE,
+ new Rectangle(x, y, width, height));
+ getToolkit().getSystemEventQueue().postEvent(pe);
+ }
+ }
+ }
+
+ /**
+ * Prints this component. This method is provided so that printing can be
+ * done in a different manner from painting. However, the implementation
+ * in this class simply calls the <code>paint()</code> method.
+ *
+ * @param g the graphics context of the print device
+ *
+ * @see #paint(Graphics)
+ */
+ public void print(Graphics g)
+ {
+ paint(g);
+ }
+
+ /**
+ * Prints this component, including all sub-components.
+ *
+ * @param g the graphics context of the print device
+ *
+ * @see #paintAll(Graphics)
+ */
+ public void printAll(Graphics g)
+ {
+ if( peer != null )
+ peer.print( g );
+ paintAll( g );
+ }
+
+ /**
+ * Called when an image has changed so that this component is repainted.
+ * This incrementally draws an image as more bits are available, when
+ * possible. Incremental drawing is enabled if the system property
+ * <code>awt.image.incrementalDraw</code> is not present or is true, in which
+ * case the redraw rate is set to 100ms or the value of the system property
+ * <code>awt.image.redrawrate</code>.
+ *
+ * <p>The coordinate system used depends on the particular flags.
+ *
+ * @param img the image that has been updated
+ * @param flags tlags as specified in <code>ImageObserver</code>
+ * @param x the X coordinate
+ * @param y the Y coordinate
+ * @param w the width
+ * @param h the height
+ * @return false if the image is completely loaded, loading has been
+ * aborted, or an error has occurred. true if more updates are
+ * required.
+ * @see ImageObserver
+ * @see Graphics#drawImage(Image, int, int, Color, ImageObserver)
+ * @see Graphics#drawImage(Image, int, int, ImageObserver)
+ * @see Graphics#drawImage(Image, int, int, int, int, Color, ImageObserver)
+ * @see Graphics#drawImage(Image, int, int, int, int, ImageObserver)
+ * @see ImageObserver#imageUpdate(Image, int, int, int, int, int)
+ */
+ public boolean imageUpdate(Image img, int flags, int x, int y, int w, int h)
+ {
+ if ((flags & (FRAMEBITS | ALLBITS)) != 0)
+ repaint();
+ else if ((flags & SOMEBITS) != 0)
+ {
+ if (incrementalDraw)
+ {
+ if (redrawRate != null)
+ {
+ long tm = redrawRate.longValue();
+ if (tm < 0)
+ tm = 0;
+ repaint(tm);
+ }
+ else
+ repaint(100);
+ }
+ }
+ return (flags & (ALLBITS | ABORT | ERROR)) == 0;
+ }
+
+ /**
+ * Creates an image from the specified producer.
+ *
+ * @param producer the image procedure to create the image from
+ * @return the resulting image
+ */
+ public Image createImage(ImageProducer producer)
+ {
+ // Only heavyweight peers can handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ // Sun allows producer to be null.
+ Image im;
+ if (p != null)
+ im = p.createImage(producer);
+ else
+ im = getToolkit().createImage(producer);
+ return im;
+ }
+
+ /**
+ * Creates an image with the specified width and height for use in
+ * double buffering. Headless environments do not support images.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ * @return the requested image, or null if it is not supported
+ */
+ public Image createImage (int width, int height)
+ {
+ Image returnValue = null;
+ if (!GraphicsEnvironment.isHeadless ())
+ {
+ // Only heavyweight peers can handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ if (p != null)
+ returnValue = p.createImage(width, height);
+ }
+ return returnValue;
+ }
+
+ /**
+ * Creates an image with the specified width and height for use in
+ * double buffering. Headless environments do not support images.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ * @return the requested image, or null if it is not supported
+ * @since 1.4
+ */
+ public VolatileImage createVolatileImage(int width, int height)
+ {
+ // Only heavyweight peers can handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ VolatileImage im = null;
+ if (p != null)
+ im = p.createVolatileImage(width, height);
+ return im;
+ }
+
+ /**
+ * Creates an image with the specified width and height for use in
+ * double buffering. Headless environments do not support images. The image
+ * will support the specified capabilities.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ * @param caps the requested capabilities
+ * @return the requested image, or null if it is not supported
+ * @throws AWTException if a buffer with the capabilities cannot be created
+ * @since 1.4
+ */
+ public VolatileImage createVolatileImage(int width, int height,
+ ImageCapabilities caps)
+ throws AWTException
+ {
+ // Only heavyweight peers can handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ VolatileImage im = null;
+ if (p != null)
+ im = peer.createVolatileImage(width, height);
+ return im;
+ }
+
+ /**
+ * Prepares the specified image for rendering on this component.
+ *
+ * @param image the image to prepare for rendering
+ * @param observer the observer to notify of image preparation status
+ * @return true if the image is already fully prepared
+ * @throws NullPointerException if image is null
+ */
+ public boolean prepareImage(Image image, ImageObserver observer)
+ {
+ return prepareImage(image, image.getWidth(observer),
+ image.getHeight(observer), observer);
+ }
+
+ /**
+ * Prepares the specified image for rendering on this component at the
+ * specified scaled width and height
+ *
+ * @param image the image to prepare for rendering
+ * @param width the scaled width of the image
+ * @param height the scaled height of the image
+ * @param observer the observer to notify of image preparation status
+ * @return true if the image is already fully prepared
+ */
+ public boolean prepareImage(Image image, int width, int height,
+ ImageObserver observer)
+ {
+ // Only heavyweight peers handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ boolean retval;
+ if (p != null)
+ retval = p.prepareImage(image, width, height, observer);
+ else
+ retval = getToolkit().prepareImage(image, width, height, observer);
+ return retval;
+ }
+
+ /**
+ * Returns the status of the loading of the specified image. The value
+ * returned will be those flags defined in <code>ImageObserver</code>.
+ *
+ * @param image the image to check on
+ * @param observer the observer to notify of image loading progress
+ * @return the image observer flags indicating the status of the load
+ * @see #prepareImage(Image, int, int, ImageObserver)
+ * @see Toolkit#checkImage(Image, int, int, ImageObserver)
+ * @throws NullPointerException if image is null
+ */
+ public int checkImage(Image image, ImageObserver observer)
+ {
+ return checkImage(image, -1, -1, observer);
+ }
+
+ /**
+ * Returns the status of the loading of the specified image. The value
+ * returned will be those flags defined in <code>ImageObserver</code>.
+ *
+ * @param image the image to check on
+ * @param width the scaled image width
+ * @param height the scaled image height
+ * @param observer the observer to notify of image loading progress
+ * @return the image observer flags indicating the status of the load
+ * @see #prepareImage(Image, int, int, ImageObserver)
+ * @see Toolkit#checkImage(Image, int, int, ImageObserver)
+ */
+ public int checkImage(Image image, int width, int height,
+ ImageObserver observer)
+ {
+ // Only heavyweight peers handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ int retval;
+ if (p != null)
+ retval = p.checkImage(image, width, height, observer);
+ else
+ retval = getToolkit().checkImage(image, width, height, observer);
+ return retval;
+ }
+
+ /**
+ * Sets whether paint messages delivered by the operating system should be
+ * ignored. This does not affect messages from AWT, except for those
+ * triggered by OS messages. Setting this to true can allow faster
+ * performance in full-screen mode or page-flipping.
+ *
+ * @param ignoreRepaint the new setting for ignoring repaint events
+ * @see #getIgnoreRepaint()
+ * @see BufferStrategy
+ * @see GraphicsDevice#setFullScreenWindow(Window)
+ * @since 1.4
+ */
+ public void setIgnoreRepaint(boolean ignoreRepaint)
+ {
+ this.ignoreRepaint = ignoreRepaint;
+ }
+
+ /**
+ * Test whether paint events from the operating system are ignored.
+ *
+ * @return the status of ignoring paint events
+ * @see #setIgnoreRepaint(boolean)
+ * @since 1.4
+ */
+ public boolean getIgnoreRepaint()
+ {
+ return ignoreRepaint;
+ }
+
+ /**
+ * Tests whether or not the specified point is contained within this
+ * component. Coordinates are relative to this component.
+ *
+ * @param x the X coordinate of the point to test
+ * @param y the Y coordinate of the point to test
+ * @return true if the point is within this component
+ * @see #getComponentAt(int, int)
+ */
+ public boolean contains(int x, int y)
+ {
+ return inside (x, y);
+ }
+
+ /**
+ * Tests whether or not the specified point is contained within this
+ * component. Coordinates are relative to this component.
+ *
+ * @param x the X coordinate of the point to test
+ * @param y the Y coordinate of the point to test
+ * @return true if the point is within this component
+ * @deprecated use {@link #contains(int, int)} instead
+ */
+ public boolean inside(int x, int y)
+ {
+ return x >= 0 && y >= 0 && x < width && y < height;
+ }
+
+ /**
+ * Tests whether or not the specified point is contained within this
+ * component. Coordinates are relative to this component.
+ *
+ * @param p the point to test
+ * @return true if the point is within this component
+ * @throws NullPointerException if p is null
+ * @see #getComponentAt(Point)
+ * @since 1.1
+ */
+ public boolean contains(Point p)
+ {
+ return contains (p.x, p.y);
+ }
+
+ /**
+ * Returns the component occupying the position (x,y). This will either
+ * be this component, an immediate child component, or <code>null</code>
+ * if neither of the first two occupies the specified location.
+ *
+ * @param x the X coordinate to search for components at
+ * @param y the Y coordinate to search for components at
+ * @return the component at the specified location, or null
+ * @see #contains(int, int)
+ */
+ public Component getComponentAt(int x, int y)
+ {
+ return locate (x, y);
+ }
+
+ /**
+ * Returns the component occupying the position (x,y). This will either
+ * be this component, an immediate child component, or <code>null</code>
+ * if neither of the first two occupies the specified location.
+ *
+ * @param x the X coordinate to search for components at
+ * @param y the Y coordinate to search for components at
+ * @return the component at the specified location, or null
+ * @deprecated use {@link #getComponentAt(int, int)} instead
+ */
+ public Component locate(int x, int y)
+ {
+ return contains (x, y) ? this : null;
+ }
+
+ /**
+ * Returns the component occupying the position (x,y). This will either
+ * be this component, an immediate child component, or <code>null</code>
+ * if neither of the first two occupies the specified location.
+ *
+ * @param p the point to search for components at
+ * @return the component at the specified location, or null
+ * @throws NullPointerException if p is null
+ * @see #contains(Point)
+ * @since 1.1
+ */
+ public Component getComponentAt(Point p)
+ {
+ return getComponentAt (p.x, p.y);
+ }
+
+ /**
+ * AWT 1.0 event delivery.
+ *
+ * Deliver an AWT 1.0 event to this Component. This method simply
+ * calls {@link #postEvent}.
+ *
+ * @param e the event to deliver
+ * @deprecated use {@link #dispatchEvent (AWTEvent)} instead
+ */
+ public void deliverEvent (Event e)
+ {
+ postEvent (e);
+ }
+
+ /**
+ * Forwards AWT events to processEvent() if:<ul>
+ * <li>Events have been enabled for this type of event via
+ * <code>enableEvents()</code></li>,
+ * <li>There is at least one registered listener for this type of event</li>
+ * </ul>
+ *
+ * @param e the event to dispatch
+ */
+ public final void dispatchEvent(AWTEvent e)
+ {
+ // Some subclasses in the AWT package need to override this behavior,
+ // hence the use of dispatchEventImpl().
+ dispatchEventImpl(e);
+ }
+
+ /**
+ * By default, no old mouse events should be ignored.
+ * This can be overridden by subclasses.
+ *
+ * @return false, no mouse events are ignored.
+ */
+ static boolean ignoreOldMouseEvents()
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 event handler.
+ *
+ * This method simply calls handleEvent and returns the result.
+ *
+ * @param e the event to handle
+ * @return true if the event was handled, false otherwise
+ * @deprecated use {@link #dispatchEvent(AWTEvent)} instead
+ */
+ public boolean postEvent (Event e)
+ {
+ boolean handled = handleEvent (e);
+
+ if (!handled && getParent() != null)
+ // FIXME: need to translate event coordinates to parent's
+ // coordinate space.
+ handled = getParent ().postEvent (e);
+
+ return handled;
+ }
+
+ /**
+ * Adds the specified listener to this component. This is harmless if the
+ * listener is null, but if the listener has already been registered, it
+ * will now be registered twice.
+ *
+ * @param listener the new listener to add
+ * @see ComponentEvent
+ * @see #removeComponentListener(ComponentListener)
+ * @see #getComponentListeners()
+ * @since 1.1
+ */
+ public synchronized void addComponentListener(ComponentListener listener)
+ {
+ if (listener != null)
+ {
+ componentListener = AWTEventMulticaster.add(componentListener,
+ listener);
+ newEventsOnly = true;
+ }
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see ComponentEvent
+ * @see #addComponentListener(ComponentListener)
+ * @see #getComponentListeners()
+ * @since 1.1
+ */
+ public synchronized void removeComponentListener(ComponentListener listener)
+ {
+ componentListener = AWTEventMulticaster.remove(componentListener, listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addComponentListener(ComponentListener)
+ * @see #removeComponentListener(ComponentListener)
+ * @since 1.4
+ */
+ public synchronized ComponentListener[] getComponentListeners()
+ {
+ return (ComponentListener[])
+ AWTEventMulticaster.getListeners(componentListener,
+ ComponentListener.class);
+ }
+
+ /**
+ * Adds the specified listener to this component. This is harmless if the
+ * listener is null, but if the listener has already been registered, it
+ * will now be registered twice.
+ *
+ * @param listener the new listener to add
+ * @see FocusEvent
+ * @see #removeFocusListener(FocusListener)
+ * @see #getFocusListeners()
+ * @since 1.1
+ */
+ public synchronized void addFocusListener(FocusListener listener)
+ {
+ if (listener != null)
+ {
+ focusListener = AWTEventMulticaster.add(focusListener, listener);
+ newEventsOnly = true;
+ }
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see FocusEvent
+ * @see #addFocusListener(FocusListener)
+ * @see #getFocusListeners()
+ * @since 1.1
+ */
+ public synchronized void removeFocusListener(FocusListener listener)
+ {
+ focusListener = AWTEventMulticaster.remove(focusListener, listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addFocusListener(FocusListener)
+ * @see #removeFocusListener(FocusListener)
+ * @since 1.4
+ */
+ public synchronized FocusListener[] getFocusListeners()
+ {
+ return (FocusListener[])
+ AWTEventMulticaster.getListeners(focusListener, FocusListener.class);
+ }
+
+ /**
+ * Adds the specified listener to this component. This is harmless if the
+ * listener is null, but if the listener has already been registered, it
+ * will now be registered twice.
+ *
+ * @param listener the new listener to add
+ * @see HierarchyEvent
+ * @see #removeHierarchyListener(HierarchyListener)
+ * @see #getHierarchyListeners()
+ * @since 1.3
+ */
+ public synchronized void addHierarchyListener(HierarchyListener listener)
+ {
+ if (listener != null)
+ {
+ hierarchyListener = AWTEventMulticaster.add(hierarchyListener,
+ listener);
+ newEventsOnly = true;
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyListeners++;
+ if (parent != null)
+ parent.updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
+ 1);
+ }
+ }
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see HierarchyEvent
+ * @see #addHierarchyListener(HierarchyListener)
+ * @see #getHierarchyListeners()
+ * @since 1.3
+ */
+ public synchronized void removeHierarchyListener(HierarchyListener listener)
+ {
+ hierarchyListener = AWTEventMulticaster.remove(hierarchyListener, listener);
+
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyListeners--;
+ if (parent != null)
+ parent.updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
+ -1);
+ }
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addHierarchyListener(HierarchyListener)
+ * @see #removeHierarchyListener(HierarchyListener)
+ * @since 1.4
+ */
+ public synchronized HierarchyListener[] getHierarchyListeners()
+ {
+ return (HierarchyListener[])
+ AWTEventMulticaster.getListeners(hierarchyListener,
+ HierarchyListener.class);
+ }
+
+ /**
+ * Adds the specified listener to this component. This is harmless if the
+ * listener is null, but if the listener has already been registered, it
+ * will now be registered twice.
+ *
+ * @param listener the new listener to add
+ * @see HierarchyEvent
+ * @see #removeHierarchyBoundsListener(HierarchyBoundsListener)
+ * @see #getHierarchyBoundsListeners()
+ * @since 1.3
+ */
+ public synchronized void
+ addHierarchyBoundsListener(HierarchyBoundsListener listener)
+ {
+ if (listener != null)
+ {
+ hierarchyBoundsListener =
+ AWTEventMulticaster.add(hierarchyBoundsListener, listener);
+ newEventsOnly = true;
+
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyBoundsListeners++;
+ if (parent != null)
+ parent.updateHierarchyListenerCount
+ (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, 1);
+ }
+ }
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see HierarchyEvent
+ * @see #addHierarchyBoundsListener(HierarchyBoundsListener)
+ * @see #getHierarchyBoundsListeners()
+ * @since 1.3
+ */
+ public synchronized void
+ removeHierarchyBoundsListener(HierarchyBoundsListener listener)
+ {
+ hierarchyBoundsListener =
+ AWTEventMulticaster.remove(hierarchyBoundsListener, listener);
+
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyBoundsListeners--;
+ if (parent != null)
+ parent.updateHierarchyListenerCount
+ (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
+ -1);
+ }
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addHierarchyBoundsListener(HierarchyBoundsListener)
+ * @see #removeHierarchyBoundsListener(HierarchyBoundsListener)
+ * @since 1.4
+ */
+ public synchronized HierarchyBoundsListener[] getHierarchyBoundsListeners()
+ {
+ return (HierarchyBoundsListener[])
+ AWTEventMulticaster.getListeners(hierarchyBoundsListener,
+ HierarchyBoundsListener.class);
+ }
+
+ /**
+ * Fires a HierarchyEvent or HierarchyChangeEvent on this component.
+ *
+ * @param id the event id
+ * @param changed the changed component
+ * @param parent the parent
+ * @param flags the event flags
+ */
+ void fireHierarchyEvent(int id, Component changed, Container parent,
+ long flags)
+ {
+ boolean enabled = false;
+ switch (id)
+ {
+ case HierarchyEvent.HIERARCHY_CHANGED:
+ enabled = hierarchyListener != null
+ || (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0;
+ break;
+ case HierarchyEvent.ANCESTOR_MOVED:
+ case HierarchyEvent.ANCESTOR_RESIZED:
+ enabled = hierarchyBoundsListener != null
+ || (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0;
+ break;
+ default:
+ assert false : "Should not reach here";
+ }
+ if (enabled)
+ {
+ HierarchyEvent ev = new HierarchyEvent(this, id, changed, parent,
+ flags);
+ dispatchEvent(ev);
+ }
+ }
+
+ /**
+ * Adds the specified listener to this component. This is harmless if the
+ * listener is null, but if the listener has already been registered, it
+ * will now be registered twice.
+ *
+ * @param listener the new listener to add
+ * @see KeyEvent
+ * @see #removeKeyListener(KeyListener)
+ * @see #getKeyListeners()
+ * @since 1.1
+ */
+ public synchronized void addKeyListener(KeyListener listener)
+ {
+ if (listener != null)
+ {
+ keyListener = AWTEventMulticaster.add(keyListener, listener);
+ newEventsOnly = true;
+ }
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see KeyEvent
+ * @see #addKeyListener(KeyListener)
+ * @see #getKeyListeners()
+ * @since 1.1
+ */
+ public synchronized void removeKeyListener(KeyListener listener)
+ {
+ keyListener = AWTEventMulticaster.remove(keyListener, listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addKeyListener(KeyListener)
+ * @see #removeKeyListener(KeyListener)
+ * @since 1.4
+ */
+ public synchronized KeyListener[] getKeyListeners()
+ {
+ return (KeyListener[])
+ AWTEventMulticaster.getListeners(keyListener, KeyListener.class);
+ }
+
+ /**
+ * Adds the specified listener to this component. This is harmless if the
+ * listener is null, but if the listener has already been registered, it
+ * will now be registered twice.
+ *
+ * @param listener the new listener to add
+ * @see MouseEvent
+ * @see #removeMouseListener(MouseListener)
+ * @see #getMouseListeners()
+ * @since 1.1
+ */
+ public synchronized void addMouseListener(MouseListener listener)
+ {
+ if (listener != null)
+ {
+ mouseListener = AWTEventMulticaster.add(mouseListener, listener);
+ newEventsOnly = true;
+ }
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see MouseEvent
+ * @see #addMouseListener(MouseListener)
+ * @see #getMouseListeners()
+ * @since 1.1
+ */
+ public synchronized void removeMouseListener(MouseListener listener)
+ {
+ mouseListener = AWTEventMulticaster.remove(mouseListener, listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addMouseListener(MouseListener)
+ * @see #removeMouseListener(MouseListener)
+ * @since 1.4
+ */
+ public synchronized MouseListener[] getMouseListeners()
+ {
+ return (MouseListener[])
+ AWTEventMulticaster.getListeners(mouseListener, MouseListener.class);
+ }
+
+ /**
+ * Adds the specified listener to this component. This is harmless if the
+ * listener is null, but if the listener has already been registered, it
+ * will now be registered twice.
+ *
+ * @param listener the new listener to add
+ * @see MouseEvent
+ * @see #removeMouseMotionListener(MouseMotionListener)
+ * @see #getMouseMotionListeners()
+ * @since 1.1
+ */
+ public synchronized void addMouseMotionListener(MouseMotionListener listener)
+ {
+ if (listener != null)
+ {
+ mouseMotionListener = AWTEventMulticaster.add(mouseMotionListener,
+ listener);
+ newEventsOnly = true;
+ }
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see MouseEvent
+ * @see #addMouseMotionListener(MouseMotionListener)
+ * @see #getMouseMotionListeners()
+ * @since 1.1
+ */
+ public synchronized void removeMouseMotionListener(MouseMotionListener listener)
+ {
+ mouseMotionListener = AWTEventMulticaster.remove(mouseMotionListener, listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addMouseMotionListener(MouseMotionListener)
+ * @see #removeMouseMotionListener(MouseMotionListener)
+ * @since 1.4
+ */
+ public synchronized MouseMotionListener[] getMouseMotionListeners()
+ {
+ return (MouseMotionListener[])
+ AWTEventMulticaster.getListeners(mouseMotionListener,
+ MouseMotionListener.class);
+ }
+
+ /**
+ * Adds the specified listener to this component. This is harmless if the
+ * listener is null, but if the listener has already been registered, it
+ * will now be registered twice.
+ *
+ * @param listener the new listener to add
+ * @see MouseEvent
+ * @see MouseWheelEvent
+ * @see #removeMouseWheelListener(MouseWheelListener)
+ * @see #getMouseWheelListeners()
+ * @since 1.4
+ */
+ public synchronized void addMouseWheelListener(MouseWheelListener listener)
+ {
+ if (listener != null)
+ {
+ mouseWheelListener = AWTEventMulticaster.add(mouseWheelListener,
+ listener);
+ newEventsOnly = true;
+ }
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see MouseEvent
+ * @see MouseWheelEvent
+ * @see #addMouseWheelListener(MouseWheelListener)
+ * @see #getMouseWheelListeners()
+ * @since 1.4
+ */
+ public synchronized void removeMouseWheelListener(MouseWheelListener listener)
+ {
+ mouseWheelListener = AWTEventMulticaster.remove(mouseWheelListener, listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addMouseWheelListener(MouseWheelListener)
+ * @see #removeMouseWheelListener(MouseWheelListener)
+ * @since 1.4
+ */
+ public synchronized MouseWheelListener[] getMouseWheelListeners()
+ {
+ return (MouseWheelListener[])
+ AWTEventMulticaster.getListeners(mouseWheelListener,
+ MouseWheelListener.class);
+ }
+
+ /**
+ * Adds the specified listener to this component. This is harmless if the
+ * listener is null, but if the listener has already been registered, it
+ * will now be registered twice.
+ *
+ * @param listener the new listener to add
+ * @see InputMethodEvent
+ * @see #removeInputMethodListener(InputMethodListener)
+ * @see #getInputMethodListeners()
+ * @see #getInputMethodRequests()
+ * @since 1.2
+ */
+ public synchronized void addInputMethodListener(InputMethodListener listener)
+ {
+ if (listener != null)
+ {
+ inputMethodListener = AWTEventMulticaster.add(inputMethodListener,
+ listener);
+ newEventsOnly = true;
+ }
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see InputMethodEvent
+ * @see #addInputMethodListener(InputMethodListener)
+ * @see #getInputMethodRequests()
+ * @since 1.2
+ */
+ public synchronized void removeInputMethodListener(InputMethodListener listener)
+ {
+ inputMethodListener = AWTEventMulticaster.remove(inputMethodListener, listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addInputMethodListener(InputMethodListener)
+ * @see #removeInputMethodListener(InputMethodListener)
+ * @since 1.4
+ */
+ public synchronized InputMethodListener[] getInputMethodListeners()
+ {
+ return (InputMethodListener[])
+ AWTEventMulticaster.getListeners(inputMethodListener,
+ InputMethodListener.class);
+ }
+
+ /**
+ * Returns all registered {@link EventListener}s of the given
+ * <code>listenerType</code>.
+ *
+ * @param listenerType the class of listeners to filter (<code>null</code>
+ * not permitted).
+ *
+ * @return An array of registered listeners.
+ *
+ * @throws ClassCastException if <code>listenerType</code> does not implement
+ * the {@link EventListener} interface.
+ * @throws NullPointerException if <code>listenerType</code> is
+ * <code>null</code>.
+ *
+ * @see #getComponentListeners()
+ * @see #getFocusListeners()
+ * @see #getHierarchyListeners()
+ * @see #getHierarchyBoundsListeners()
+ * @see #getKeyListeners()
+ * @see #getMouseListeners()
+ * @see #getMouseMotionListeners()
+ * @see #getMouseWheelListeners()
+ * @see #getInputMethodListeners()
+ * @see #getPropertyChangeListeners()
+ * @since 1.3
+ */
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
+ {
+ if (listenerType == ComponentListener.class)
+ return (T[]) getComponentListeners();
+ if (listenerType == FocusListener.class)
+ return (T[]) getFocusListeners();
+ if (listenerType == HierarchyListener.class)
+ return (T[]) getHierarchyListeners();
+ if (listenerType == HierarchyBoundsListener.class)
+ return (T[]) getHierarchyBoundsListeners();
+ if (listenerType == KeyListener.class)
+ return (T[]) getKeyListeners();
+ if (listenerType == MouseListener.class)
+ return (T[]) getMouseListeners();
+ if (listenerType == MouseMotionListener.class)
+ return (T[]) getMouseMotionListeners();
+ if (listenerType == MouseWheelListener.class)
+ return (T[]) getMouseWheelListeners();
+ if (listenerType == InputMethodListener.class)
+ return (T[]) getInputMethodListeners();
+ if (listenerType == PropertyChangeListener.class)
+ return (T[]) getPropertyChangeListeners();
+ return (T[]) Array.newInstance(listenerType, 0);
+ }
+
+ /**
+ * Returns the input method request handler, for subclasses which support
+ * on-the-spot text input. By default, input methods are handled by AWT,
+ * and this returns null.
+ *
+ * @return the input method handler, null by default
+ * @since 1.2
+ */
+ public InputMethodRequests getInputMethodRequests()
+ {
+ return null;
+ }
+
+ /**
+ * Gets the input context of this component, which is inherited from the
+ * parent unless this is overridden.
+ *
+ * @return the text input context
+ * @since 1.2
+ */
+ public InputContext getInputContext()
+ {
+ return parent == null ? null : parent.getInputContext();
+ }
+
+ /**
+ * Enables the specified events. The events to enable are specified
+ * by OR-ing together the desired masks from <code>AWTEvent</code>.
+ *
+ * <p>Events are enabled by default when a listener is attached to the
+ * component for that event type. This method can be used by subclasses
+ * to ensure the delivery of a specified event regardless of whether
+ * or not a listener is attached.
+ *
+ * @param eventsToEnable the desired events to enable
+ * @see #processEvent(AWTEvent)
+ * @see #disableEvents(long)
+ * @see AWTEvent
+ * @since 1.1
+ */
+ protected final void enableEvents(long eventsToEnable)
+ {
+ // Update the counter for hierarchy (bounds) listeners.
+ if ((eventsToEnable & AWTEvent.HIERARCHY_EVENT_MASK) != 0
+ && (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) == 0)
+ {
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyListeners++;
+ if (parent != null)
+ parent.updateHierarchyListenerCount
+ (AWTEvent.HIERARCHY_EVENT_MASK,
+ 1);
+ }
+ }
+ if ((eventsToEnable & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0
+ && (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) == 0)
+ {
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyBoundsListeners++;
+ if (parent != null)
+ parent.updateHierarchyListenerCount
+ (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
+ 1);
+ }
+ }
+
+ eventMask |= eventsToEnable;
+ newEventsOnly = true;
+
+ // Only heavyweight peers handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ if (p != null)
+ p.setEventMask(eventMask);
+
+ }
+
+ /**
+ * Disables the specified events. The events to disable are specified
+ * by OR-ing together the desired masks from <code>AWTEvent</code>.
+ *
+ * @param eventsToDisable the desired events to disable
+ * @see #enableEvents(long)
+ * @since 1.1
+ */
+ protected final void disableEvents(long eventsToDisable)
+ {
+ // Update the counter for hierarchy (bounds) listeners.
+ if ((eventsToDisable & AWTEvent.HIERARCHY_EVENT_MASK) != 0
+ && (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0)
+ {
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyListeners--;
+ if (parent != null)
+ parent.updateHierarchyListenerCount
+ (AWTEvent.HIERARCHY_EVENT_MASK,
+ -1);
+ }
+ }
+ if ((eventsToDisable & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0
+ && (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0)
+ {
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyBoundsListeners--;
+ if (parent != null)
+ parent.updateHierarchyListenerCount
+ (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
+ -1);
+ }
+ }
+
+ eventMask &= ~eventsToDisable;
+
+ // Only heavyweight peers handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ if (p != null)
+ p.setEventMask(eventMask);
+
+ }
+
+ /**
+ * This is called by the EventQueue if two events with the same event id
+ * and owner component are queued. Returns a new combined event, or null if
+ * no combining is done. The coelesced events are currently mouse moves
+ * (intermediate ones are discarded) and paint events (a merged paint is
+ * created in place of the two events).
+ *
+ * @param existingEvent the event on the queue
+ * @param newEvent the new event that might be entered on the queue
+ * @return null if both events are kept, or the replacement coelesced event
+ */
+ protected AWTEvent coalesceEvents(AWTEvent existingEvent, AWTEvent newEvent)
+ {
+ AWTEvent coalesced = null;
+ switch (existingEvent.id)
+ {
+ case MouseEvent.MOUSE_MOVED:
+ case MouseEvent.MOUSE_DRAGGED:
+ // Just drop the old (intermediate) event and return the new one.
+ MouseEvent me1 = (MouseEvent) existingEvent;
+ MouseEvent me2 = (MouseEvent) newEvent;
+ if (me1.getModifiers() == me2.getModifiers())
+ coalesced = newEvent;
+ break;
+ case PaintEvent.PAINT:
+ case PaintEvent.UPDATE:
+ // For heavyweights the EventQueue should ask the peer.
+ if (peer == null || peer instanceof LightweightPeer)
+ {
+ PaintEvent pe1 = (PaintEvent) existingEvent;
+ PaintEvent pe2 = (PaintEvent) newEvent;
+ Rectangle r1 = pe1.getUpdateRect();
+ Rectangle r2 = pe2.getUpdateRect();
+ if (r1.contains(r2))
+ coalesced = existingEvent;
+ else if (r2.contains(r1))
+ coalesced = newEvent;
+ }
+ else
+ {
+ // Replace the event and let the heavyweight figure out the expanding
+ // of the repaint area.
+ coalesced = newEvent;
+ }
+ break;
+ default:
+ coalesced = null;
+ }
+ return coalesced;
+ }
+
+ /**
+ * Processes the specified event. In this class, this method simply
+ * calls one of the more specific event handlers.
+ *
+ * @param e the event to process
+ * @throws NullPointerException if e is null
+ * @see #processComponentEvent(ComponentEvent)
+ * @see #processFocusEvent(FocusEvent)
+ * @see #processKeyEvent(KeyEvent)
+ * @see #processMouseEvent(MouseEvent)
+ * @see #processMouseMotionEvent(MouseEvent)
+ * @see #processInputMethodEvent(InputMethodEvent)
+ * @see #processHierarchyEvent(HierarchyEvent)
+ * @see #processMouseWheelEvent(MouseWheelEvent)
+ * @since 1.1
+ */
+ protected void processEvent(AWTEvent e)
+ {
+ /* Note: the order of these if statements are
+ important. Subclasses must be checked first. Eg. MouseEvent
+ must be checked before ComponentEvent, since a MouseEvent
+ object is also an instance of a ComponentEvent. */
+
+ if (e instanceof FocusEvent)
+ processFocusEvent((FocusEvent) e);
+ else if (e instanceof MouseWheelEvent)
+ processMouseWheelEvent((MouseWheelEvent) e);
+ else if (e instanceof MouseEvent)
+ {
+ if (e.id == MouseEvent.MOUSE_MOVED
+ || e.id == MouseEvent.MOUSE_DRAGGED)
+ processMouseMotionEvent((MouseEvent) e);
+ else
+ processMouseEvent((MouseEvent) e);
+ }
+ else if (e instanceof KeyEvent)
+ processKeyEvent((KeyEvent) e);
+ else if (e instanceof InputMethodEvent)
+ processInputMethodEvent((InputMethodEvent) e);
+ else if (e instanceof ComponentEvent)
+ processComponentEvent((ComponentEvent) e);
+ else if (e instanceof HierarchyEvent)
+ {
+ if (e.id == HierarchyEvent.HIERARCHY_CHANGED)
+ processHierarchyEvent((HierarchyEvent) e);
+ else
+ processHierarchyBoundsEvent((HierarchyEvent) e);
+ }
+ }
+
+ /**
+ * Called when a component event is dispatched and component events are
+ * enabled. This method passes the event along to any listeners
+ * that are attached.
+ *
+ * @param e the <code>ComponentEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see ComponentListener
+ * @see #addComponentListener(ComponentListener)
+ * @see #enableEvents(long)
+ * @since 1.1
+ */
+ protected void processComponentEvent(ComponentEvent e)
+ {
+ if (componentListener == null)
+ return;
+ switch (e.id)
+ {
+ case ComponentEvent.COMPONENT_HIDDEN:
+ componentListener.componentHidden(e);
+ break;
+ case ComponentEvent.COMPONENT_MOVED:
+ componentListener.componentMoved(e);
+ break;
+ case ComponentEvent.COMPONENT_RESIZED:
+ componentListener.componentResized(e);
+ break;
+ case ComponentEvent.COMPONENT_SHOWN:
+ componentListener.componentShown(e);
+ break;
+ }
+ }
+
+ /**
+ * Called when a focus event is dispatched and component events are
+ * enabled. This method passes the event along to any listeners
+ * that are attached.
+ *
+ * @param e the <code>FocusEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see FocusListener
+ * @see #addFocusListener(FocusListener)
+ * @see #enableEvents(long)
+ * @since 1.1
+ */
+ protected void processFocusEvent(FocusEvent e)
+ {
+ if (focusListener == null)
+ return;
+
+ switch (e.id)
+ {
+ case FocusEvent.FOCUS_GAINED:
+ focusListener.focusGained(e);
+ break;
+ case FocusEvent.FOCUS_LOST:
+ focusListener.focusLost(e);
+ break;
+ }
+ }
+
+ /**
+ * Called when a key event is dispatched and component events are
+ * enabled. This method passes the event along to any listeners
+ * that are attached.
+ *
+ * @param e the <code>KeyEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see KeyListener
+ * @see #addKeyListener(KeyListener)
+ * @see #enableEvents(long)
+ * @since 1.1
+ */
+ protected void processKeyEvent(KeyEvent e)
+ {
+ if (keyListener == null)
+ return;
+ switch (e.id)
+ {
+ case KeyEvent.KEY_PRESSED:
+ keyListener.keyPressed(e);
+ break;
+ case KeyEvent.KEY_RELEASED:
+ keyListener.keyReleased(e);
+ break;
+ case KeyEvent.KEY_TYPED:
+ keyListener.keyTyped(e);
+ break;
+ }
+ }
+
+ /**
+ * Called when a regular mouse event is dispatched and component events are
+ * enabled. This method passes the event along to any listeners
+ * that are attached.
+ *
+ * @param e the <code>MouseEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see MouseListener
+ * @see #addMouseListener(MouseListener)
+ * @see #enableEvents(long)
+ * @since 1.1
+ */
+ protected void processMouseEvent(MouseEvent e)
+ {
+ if (mouseListener == null)
+ return;
+ switch (e.id)
+ {
+ case MouseEvent.MOUSE_CLICKED:
+ mouseListener.mouseClicked(e);
+ break;
+ case MouseEvent.MOUSE_ENTERED:
+ if( isLightweight() )
+ setCursor( getCursor() );
+ mouseListener.mouseEntered(e);
+ break;
+ case MouseEvent.MOUSE_EXITED:
+ mouseListener.mouseExited(e);
+ break;
+ case MouseEvent.MOUSE_PRESSED:
+ mouseListener.mousePressed(e);
+ break;
+ case MouseEvent.MOUSE_RELEASED:
+ mouseListener.mouseReleased(e);
+ break;
+ }
+ }
+
+ /**
+ * Called when a mouse motion event is dispatched and component events are
+ * enabled. This method passes the event along to any listeners
+ * that are attached.
+ *
+ * @param e the <code>MouseMotionEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see MouseMotionListener
+ * @see #addMouseMotionListener(MouseMotionListener)
+ * @see #enableEvents(long)
+ * @since 1.1
+ */
+ protected void processMouseMotionEvent(MouseEvent e)
+ {
+ if (mouseMotionListener == null)
+ return;
+ switch (e.id)
+ {
+ case MouseEvent.MOUSE_DRAGGED:
+ mouseMotionListener.mouseDragged(e);
+ break;
+ case MouseEvent.MOUSE_MOVED:
+ mouseMotionListener.mouseMoved(e);
+ break;
+ }
+ e.consume();
+ }
+
+ /**
+ * Called when a mouse wheel event is dispatched and component events are
+ * enabled. This method passes the event along to any listeners that are
+ * attached.
+ *
+ * @param e the <code>MouseWheelEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see MouseWheelListener
+ * @see #addMouseWheelListener(MouseWheelListener)
+ * @see #enableEvents(long)
+ * @since 1.4
+ */
+ protected void processMouseWheelEvent(MouseWheelEvent e)
+ {
+ if (mouseWheelListener != null
+ && e.id == MouseEvent.MOUSE_WHEEL)
+ {
+ mouseWheelListener.mouseWheelMoved(e);
+ e.consume();
+ }
+ }
+
+ /**
+ * Called when an input method event is dispatched and component events are
+ * enabled. This method passes the event along to any listeners that are
+ * attached.
+ *
+ * @param e the <code>InputMethodEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see InputMethodListener
+ * @see #addInputMethodListener(InputMethodListener)
+ * @see #enableEvents(long)
+ * @since 1.2
+ */
+ protected void processInputMethodEvent(InputMethodEvent e)
+ {
+ if (inputMethodListener == null)
+ return;
+ switch (e.id)
+ {
+ case InputMethodEvent.CARET_POSITION_CHANGED:
+ inputMethodListener.caretPositionChanged(e);
+ break;
+ case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED:
+ inputMethodListener.inputMethodTextChanged(e);
+ break;
+ }
+ }
+
+ /**
+ * Called when a hierarchy change event is dispatched and component events
+ * are enabled. This method passes the event along to any listeners that are
+ * attached.
+ *
+ * @param e the <code>HierarchyEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see HierarchyListener
+ * @see #addHierarchyListener(HierarchyListener)
+ * @see #enableEvents(long)
+ * @since 1.3
+ */
+ protected void processHierarchyEvent(HierarchyEvent e)
+ {
+ if (hierarchyListener == null)
+ return;
+ if (e.id == HierarchyEvent.HIERARCHY_CHANGED)
+ hierarchyListener.hierarchyChanged(e);
+ }
+
+ /**
+ * Called when a hierarchy bounds event is dispatched and component events
+ * are enabled. This method passes the event along to any listeners that are
+ * attached.
+ *
+ * @param e the <code>HierarchyEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see HierarchyBoundsListener
+ * @see #addHierarchyBoundsListener(HierarchyBoundsListener)
+ * @see #enableEvents(long)
+ * @since 1.3
+ */
+ protected void processHierarchyBoundsEvent(HierarchyEvent e)
+ {
+ if (hierarchyBoundsListener == null)
+ return;
+ switch (e.id)
+ {
+ case HierarchyEvent.ANCESTOR_MOVED:
+ hierarchyBoundsListener.ancestorMoved(e);
+ break;
+ case HierarchyEvent.ANCESTOR_RESIZED:
+ hierarchyBoundsListener.ancestorResized(e);
+ break;
+ }
+ }
+
+ /**
+ * AWT 1.0 event handler.
+ *
+ * This method calls one of the event-specific handler methods. For
+ * example for key events, either {@link #keyDown(Event,int)}
+ * or {@link #keyUp(Event,int)} is called. A derived
+ * component can override one of these event-specific methods if it
+ * only needs to handle certain event types. Otherwise it can
+ * override handleEvent itself and handle any event.
+ *
+ * @param evt the event to handle
+ * @return true if the event was handled, false otherwise
+ * @deprecated use {@link #processEvent(AWTEvent)} instead
+ */
+ public boolean handleEvent (Event evt)
+ {
+ switch (evt.id)
+ {
+ // Handle key events.
+ case Event.KEY_ACTION:
+ case Event.KEY_PRESS:
+ return keyDown (evt, evt.key);
+ case Event.KEY_ACTION_RELEASE:
+ case Event.KEY_RELEASE:
+ return keyUp (evt, evt.key);
+
+ // Handle mouse events.
+ case Event.MOUSE_DOWN:
+ return mouseDown (evt, evt.x, evt.y);
+ case Event.MOUSE_UP:
+ return mouseUp (evt, evt.x, evt.y);
+ case Event.MOUSE_MOVE:
+ return mouseMove (evt, evt.x, evt.y);
+ case Event.MOUSE_DRAG:
+ return mouseDrag (evt, evt.x, evt.y);
+ case Event.MOUSE_ENTER:
+ return mouseEnter (evt, evt.x, evt.y);
+ case Event.MOUSE_EXIT:
+ return mouseExit (evt, evt.x, evt.y);
+
+ // Handle focus events.
+ case Event.GOT_FOCUS:
+ return gotFocus (evt, evt.arg);
+ case Event.LOST_FOCUS:
+ return lostFocus (evt, evt.arg);
+
+ // Handle action event.
+ case Event.ACTION_EVENT:
+ return action (evt, evt.arg);
+ }
+ // Unknown event.
+ return false;
+ }
+
+ /**
+ * AWT 1.0 MOUSE_DOWN event handler. This method is meant to be
+ * overridden by components providing their own MOUSE_DOWN handler.
+ * The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param x the x coordinate, ignored
+ * @param y the y coordinate, ignored
+ * @return false
+ * @deprecated use {@link #processMouseEvent(MouseEvent)} instead
+ */
+ public boolean mouseDown(Event evt, int x, int y)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 MOUSE_DRAG event handler. This method is meant to be
+ * overridden by components providing their own MOUSE_DRAG handler.
+ * The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param x the x coordinate, ignored
+ * @param y the y coordinate, ignored
+ * @return false
+ * @deprecated use {@link #processMouseMotionEvent(MouseEvent)} instead
+ */
+ public boolean mouseDrag(Event evt, int x, int y)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 MOUSE_UP event handler. This method is meant to be
+ * overridden by components providing their own MOUSE_UP handler.
+ * The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param x the x coordinate, ignored
+ * @param y the y coordinate, ignored
+ * @return false
+ * @deprecated use {@link #processMouseEvent(MouseEvent)} instead
+ */
+ public boolean mouseUp(Event evt, int x, int y)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 MOUSE_MOVE event handler. This method is meant to be
+ * overridden by components providing their own MOUSE_MOVE handler.
+ * The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param x the x coordinate, ignored
+ * @param y the y coordinate, ignored
+ * @return false
+ * @deprecated use {@link #processMouseMotionEvent(MouseEvent)} instead
+ */
+ public boolean mouseMove(Event evt, int x, int y)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 MOUSE_ENTER event handler. This method is meant to be
+ * overridden by components providing their own MOUSE_ENTER handler.
+ * The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param x the x coordinate, ignored
+ * @param y the y coordinate, ignored
+ * @return false
+ * @deprecated use {@link #processMouseEvent(MouseEvent)} instead
+ */
+ public boolean mouseEnter(Event evt, int x, int y)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 MOUSE_EXIT event handler. This method is meant to be
+ * overridden by components providing their own MOUSE_EXIT handler.
+ * The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param x the x coordinate, ignored
+ * @param y the y coordinate, ignored
+ * @return false
+ * @deprecated use {@link #processMouseEvent(MouseEvent)} instead
+ */
+ public boolean mouseExit(Event evt, int x, int y)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 KEY_PRESS and KEY_ACTION event handler. This method is
+ * meant to be overridden by components providing their own key
+ * press handler. The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param key the key pressed, ignored
+ * @return false
+ * @deprecated use {@link #processKeyEvent(KeyEvent)} instead
+ */
+ public boolean keyDown(Event evt, int key)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 KEY_RELEASE and KEY_ACTION_RELEASE event handler. This
+ * method is meant to be overridden by components providing their
+ * own key release handler. The default implementation simply
+ * returns false.
+ *
+ * @param evt the event to handle
+ * @param key the key pressed, ignored
+ * @return false
+ * @deprecated use {@link #processKeyEvent(KeyEvent)} instead
+ */
+ public boolean keyUp(Event evt, int key)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 ACTION_EVENT event handler. This method is meant to be
+ * overridden by components providing their own action event
+ * handler. The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param what the object acted on, ignored
+ * @return false
+ * @deprecated in classes which support actions, use
+ * <code>processActionEvent(ActionEvent)</code> instead
+ */
+ public boolean action(Event evt, Object what)
+ {
+ return false;
+ }
+
+ /**
+ * Called when the parent of this Component is made visible or when
+ * the Component is added to an already visible Container and needs
+ * to be shown. A native peer - if any - is created at this
+ * time. This method is called automatically by the AWT system and
+ * should not be called by user level code.
+ *
+ * @see #isDisplayable()
+ * @see #removeNotify()
+ */
+ public void addNotify()
+ {
+ // We need to lock the tree here to avoid races and inconsistencies.
+ synchronized (getTreeLock())
+ {
+ if (peer == null)
+ peer = getToolkit().createComponent(this);
+ else if (parent != null && parent.isLightweight())
+ new HeavyweightInLightweightListener(parent);
+ // Now that all the children has gotten their peers, we should
+ // have the event mask needed for this component and its
+ //lightweight subcomponents.
+ peer.setEventMask(eventMask);
+
+ // We used to leave the invalidate() to the peer. However, I put it
+ // back here for 2 reasons: 1) The RI does call invalidate() from
+ // addNotify(); 2) The peer shouldn't be bother with validation too
+ // much.
+ invalidate();
+
+ if (dropTarget != null)
+ dropTarget.addNotify(peer);
+
+ // Fetch the peerFont for later installation in validate().
+ peerFont = getFont();
+
+ // Notify hierarchy listeners.
+ long flags = HierarchyEvent.DISPLAYABILITY_CHANGED;
+ if (isHierarchyVisible())
+ flags |= HierarchyEvent.SHOWING_CHANGED;
+ fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, this, parent,
+ flags);
+ }
+ }
+
+ /**
+ * Called to inform this component is has been removed from its
+ * container. Its native peer - if any - is destroyed at this time.
+ * This method is called automatically by the AWT system and should
+ * not be called by user level code.
+ *
+ * @see #isDisplayable()
+ * @see #addNotify()
+ */
+ public void removeNotify()
+ {
+ // We need to lock the tree here to avoid races and inconsistencies.
+ synchronized (getTreeLock())
+ {
+ // We null our peer field before disposing of it, such that if we're
+ // not the event dispatch thread and the dispatch thread is awoken by
+ // the dispose call, there will be no race checking the peer's null
+ // status.
+
+ ComponentPeer tmp = peer;
+ peer = null;
+ peerFont = null;
+ if (tmp != null)
+ {
+ tmp.hide();
+ tmp.dispose();
+ }
+
+ // Notify hierarchy listeners.
+ long flags = HierarchyEvent.DISPLAYABILITY_CHANGED;
+ if (isHierarchyVisible())
+ flags |= HierarchyEvent.SHOWING_CHANGED;
+ fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, this, parent,
+ flags);
+ }
+ }
+
+ /**
+ * AWT 1.0 GOT_FOCUS event handler. This method is meant to be
+ * overridden by components providing their own GOT_FOCUS handler.
+ * The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param what the Object focused, ignored
+ * @return false
+ * @deprecated use {@link #processFocusEvent(FocusEvent)} instead
+ */
+ public boolean gotFocus(Event evt, Object what)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 LOST_FOCUS event handler. This method is meant to be
+ * overridden by components providing their own LOST_FOCUS handler.
+ * The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param what the Object focused, ignored
+ * @return false
+ * @deprecated use {@link #processFocusEvent(FocusEvent)} instead
+ */
+ public boolean lostFocus(Event evt, Object what)
+ {
+ return false;
+ }
+
+ /**
+ * Tests whether or not this component is in the group that can be
+ * traversed using the keyboard traversal mechanism (such as the TAB key).
+ *
+ * @return true if the component is traversed via the TAB key
+ * @see #setFocusable(boolean)
+ * @since 1.1
+ * @deprecated use {@link #isFocusable()} instead
+ */
+ public boolean isFocusTraversable()
+ {
+ return enabled && visible && (peer == null || isLightweight() || peer.isFocusTraversable());
+ }
+
+ /**
+ * Tests if this component can receive focus.
+ *
+ * @return true if this component can receive focus
+ * @since 1.4
+ */
+ public boolean isFocusable()
+ {
+ return focusable;
+ }
+
+ /**
+ * Specify whether this component can receive focus. This method also
+ * sets the {@link #isFocusTraversableOverridden} field to 1, which
+ * appears to be the undocumented way {@link
+ * DefaultFocusTraversalPolicy#accept(Component)} determines whether to
+ * respect the {@link #isFocusable()} method of the component.
+ *
+ * @param focusable the new focusable status
+ * @since 1.4
+ */
+ public void setFocusable(boolean focusable)
+ {
+ firePropertyChange("focusable", this.focusable, focusable);
+ this.focusable = focusable;
+ this.isFocusTraversableOverridden = 1;
+ }
+
+ /**
+ * Sets the focus traversal keys for one of the three focus
+ * traversal directions supported by Components:
+ * {@link KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS},
+ * {@link KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS}, or
+ * {@link KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS}. Normally, the
+ * default values should match the operating system's native
+ * choices. To disable a given traversal, use
+ * <code>Collections.EMPTY_SET</code>. The event dispatcher will
+ * consume PRESSED, RELEASED, and TYPED events for the specified
+ * key, although focus can only transfer on PRESSED or RELEASED.
+ *
+ * <p>The defaults are:
+ * <table>
+ * <th><td>Identifier</td><td>Meaning</td><td>Default</td></th>
+ * <tr><td>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</td>
+ * <td>Normal forward traversal</td>
+ * <td>TAB on KEY_PRESSED, Ctrl-TAB on KEY_PRESSED</td></tr>
+ * <tr><td>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</td>
+ * <td>Normal backward traversal</td>
+ * <td>Shift-TAB on KEY_PRESSED, Ctrl-Shift-TAB on KEY_PRESSED</td></tr>
+ * <tr><td>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</td>
+ * <td>Go up a traversal cycle</td><td>None</td></tr>
+ * </table>
+ *
+ * If keystrokes is null, this component's focus traversal key set
+ * is inherited from one of its ancestors. If none of its ancestors
+ * has its own set of focus traversal keys, the focus traversal keys
+ * are set to the defaults retrieved from the current
+ * KeyboardFocusManager. If not null, the set must contain only
+ * AWTKeyStrokes that are not already focus keys and are not
+ * KEY_TYPED events.
+ *
+ * @param id one of FORWARD_TRAVERSAL_KEYS, BACKWARD_TRAVERSAL_KEYS, or
+ * UP_CYCLE_TRAVERSAL_KEYS
+ * @param keystrokes a set of keys, or null
+ * @throws IllegalArgumentException if id or keystrokes is invalid
+ * @see #getFocusTraversalKeys(int)
+ * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
+ * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
+ * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
+ * @since 1.4
+ */
+ public void setFocusTraversalKeys(int id,
+ Set<? extends AWTKeyStroke> keystrokes)
+ {
+ if (keystrokes == null)
+ {
+ Container parent = getParent ();
+
+ while (parent != null)
+ {
+ if (parent.areFocusTraversalKeysSet (id))
+ {
+ keystrokes = parent.getFocusTraversalKeys (id);
+ break;
+ }
+ parent = parent.getParent ();
+ }
+
+ if (keystrokes == null)
+ keystrokes = KeyboardFocusManager.getCurrentKeyboardFocusManager ().
+ getDefaultFocusTraversalKeys (id);
+ }
+
+ Set sa;
+ Set sb;
+ String name;
+ switch (id)
+ {
+ case KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS:
+ sa = getFocusTraversalKeys
+ (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
+ sb = getFocusTraversalKeys
+ (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
+ name = "forwardFocusTraversalKeys";
+ break;
+ case KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS:
+ sa = getFocusTraversalKeys
+ (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
+ sb = getFocusTraversalKeys
+ (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
+ name = "backwardFocusTraversalKeys";
+ break;
+ case KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS:
+ sa = getFocusTraversalKeys
+ (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
+ sb = getFocusTraversalKeys
+ (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
+ name = "upCycleFocusTraversalKeys";
+ break;
+ default:
+ throw new IllegalArgumentException ();
+ }
+
+ int i = keystrokes.size ();
+ Iterator iter = keystrokes.iterator ();
+
+ while (--i >= 0)
+ {
+ Object o = iter.next ();
+ if (!(o instanceof AWTKeyStroke)
+ || sa.contains (o) || sb.contains (o)
+ || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED)
+ throw new IllegalArgumentException ();
+ }
+
+ if (focusTraversalKeys == null)
+ focusTraversalKeys = new Set[3];
+
+ keystrokes = Collections.unmodifiableSet (new HashSet (keystrokes));
+ firePropertyChange (name, focusTraversalKeys[id], keystrokes);
+
+ focusTraversalKeys[id] = keystrokes;
+ }
+
+ /**
+ * Returns the set of keys for a given focus traversal action, as
+ * defined in <code>setFocusTraversalKeys</code>. If not set, this
+ * is inherited from the parent component, which may have gotten it
+ * from the KeyboardFocusManager.
+ *
+ * @param id one of FORWARD_TRAVERSAL_KEYS, BACKWARD_TRAVERSAL_KEYS,
+ * or UP_CYCLE_TRAVERSAL_KEYS
+ *
+ * @return set of traversal keys
+ *
+ * @throws IllegalArgumentException if id is invalid
+ *
+ * @see #setFocusTraversalKeys (int, Set)
+ * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
+ * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
+ * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
+ *
+ * @since 1.4
+ */
+ public Set<AWTKeyStroke> getFocusTraversalKeys (int id)
+ {
+ if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS)
+ throw new IllegalArgumentException();
+
+ Set<AWTKeyStroke> s = null;
+
+ if (focusTraversalKeys != null)
+ s = focusTraversalKeys[id];
+
+ if (s == null && parent != null)
+ s = parent.getFocusTraversalKeys (id);
+
+ return s == null ? (KeyboardFocusManager.getCurrentKeyboardFocusManager()
+ .getDefaultFocusTraversalKeys(id)) : s;
+ }
+
+ /**
+ * Tests whether the focus traversal keys for a given action are explicitly
+ * set or inherited.
+ *
+ * @param id one of FORWARD_TRAVERSAL_KEYS, BACKWARD_TRAVERSAL_KEYS,
+ * or UP_CYCLE_TRAVERSAL_KEYS
+ * @return true if that set is explicitly specified
+ * @throws IllegalArgumentException if id is invalid
+ * @see #getFocusTraversalKeys (int)
+ * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
+ * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
+ * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
+ * @since 1.4
+ */
+ public boolean areFocusTraversalKeysSet (int id)
+ {
+ if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS)
+ throw new IllegalArgumentException ();
+
+ return focusTraversalKeys != null && focusTraversalKeys[id] != null;
+ }
+
+ /**
+ * Enable or disable focus traversal keys on this Component. If
+ * they are, then the keyboard focus manager consumes and acts on
+ * key press and release events that trigger focus traversal, and
+ * discards the corresponding key typed events. If focus traversal
+ * keys are disabled, then all key events that would otherwise
+ * trigger focus traversal are sent to this Component.
+ *
+ * @param focusTraversalKeysEnabled the new value of the flag
+ * @see #getFocusTraversalKeysEnabled ()
+ * @see #setFocusTraversalKeys (int, Set)
+ * @see #getFocusTraversalKeys (int)
+ * @since 1.4
+ */
+ public void setFocusTraversalKeysEnabled (boolean focusTraversalKeysEnabled)
+ {
+ firePropertyChange ("focusTraversalKeysEnabled",
+ this.focusTraversalKeysEnabled,
+ focusTraversalKeysEnabled);
+ this.focusTraversalKeysEnabled = focusTraversalKeysEnabled;
+ }
+
+ /**
+ * Check whether or not focus traversal keys are enabled on this
+ * Component. If they are, then the keyboard focus manager consumes
+ * and acts on key press and release events that trigger focus
+ * traversal, and discards the corresponding key typed events. If
+ * focus traversal keys are disabled, then all key events that would
+ * otherwise trigger focus traversal are sent to this Component.
+ *
+ * @return true if focus traversal keys are enabled
+ * @see #setFocusTraversalKeysEnabled (boolean)
+ * @see #setFocusTraversalKeys (int, Set)
+ * @see #getFocusTraversalKeys (int)
+ * @since 1.4
+ */
+ public boolean getFocusTraversalKeysEnabled ()
+ {
+ return focusTraversalKeysEnabled;
+ }
+
+ /**
+ * Request that this Component be given the keyboard input focus and
+ * that its top-level ancestor become the focused Window.
+ *
+ * For the request to be granted, the Component must be focusable,
+ * displayable and showing and the top-level Window to which it
+ * belongs must be focusable. If the request is initially denied on
+ * the basis that the top-level Window is not focusable, the request
+ * will be remembered and granted when the Window does become
+ * focused.
+ *
+ * Never assume that this Component is the focus owner until it
+ * receives a FOCUS_GAINED event.
+ *
+ * The behaviour of this method is platform-dependent.
+ * {@link #requestFocusInWindow()} should be used instead.
+ *
+ * @see #requestFocusInWindow ()
+ * @see FocusEvent
+ * @see #addFocusListener (FocusListener)
+ * @see #isFocusable ()
+ * @see #isDisplayable ()
+ * @see KeyboardFocusManager#clearGlobalFocusOwner ()
+ */
+ public void requestFocus ()
+ {
+ requestFocusImpl(false, true);
+ }
+
+ /**
+ * Request that this Component be given the keyboard input focus and
+ * that its top-level ancestor become the focused Window.
+ *
+ * For the request to be granted, the Component must be focusable,
+ * displayable and showing and the top-level Window to which it
+ * belongs must be focusable. If the request is initially denied on
+ * the basis that the top-level Window is not focusable, the request
+ * will be remembered and granted when the Window does become
+ * focused.
+ *
+ * Never assume that this Component is the focus owner until it
+ * receives a FOCUS_GAINED event.
+ *
+ * The behaviour of this method is platform-dependent.
+ * {@link #requestFocusInWindow()} should be used instead.
+ *
+ * If the return value is false, the request is guaranteed to fail.
+ * If the return value is true, the request will succeed unless it
+ * is vetoed or something in the native windowing system intervenes,
+ * preventing this Component's top-level ancestor from becoming
+ * focused. This method is meant to be called by derived
+ * lightweight Components that want to avoid unnecessary repainting
+ * when they know a given focus transfer need only be temporary.
+ *
+ * @param temporary true if the focus request is temporary
+ * @return true if the request has a chance of success
+ * @see #requestFocusInWindow ()
+ * @see FocusEvent
+ * @see #addFocusListener (FocusListener)
+ * @see #isFocusable ()
+ * @see #isDisplayable ()
+ * @see KeyboardFocusManager#clearGlobalFocusOwner ()
+ * @since 1.4
+ */
+ protected boolean requestFocus (boolean temporary)
+ {
+ return requestFocusImpl(temporary, true);
+ }
+
+ /**
+ * Request that this component be given the keyboard input focus, if
+ * its top-level ancestor is the currently focused Window. A
+ * <code>FOCUS_GAINED</code> event will be fired if and only if this
+ * request is successful. To be successful, the component must be
+ * displayable, showing, and focusable, and its ancestor top-level
+ * Window must be focused.
+ *
+ * If the return value is false, the request is guaranteed to fail.
+ * If the return value is true, the request will succeed unless it
+ * is vetoed or something in the native windowing system intervenes,
+ * preventing this Component's top-level ancestor from becoming
+ * focused.
+ *
+ * @return true if the request has a chance of success
+ * @see #requestFocus ()
+ * @see FocusEvent
+ * @see #addFocusListener (FocusListener)
+ * @see #isFocusable ()
+ * @see #isDisplayable ()
+ * @see KeyboardFocusManager#clearGlobalFocusOwner ()
+ * @since 1.4
+ */
+ public boolean requestFocusInWindow ()
+ {
+ return requestFocusImpl(false, false);
+ }
+
+ /**
+ * Request that this component be given the keyboard input focus, if
+ * its top-level ancestor is the currently focused Window. A
+ * <code>FOCUS_GAINED</code> event will be fired if and only if this
+ * request is successful. To be successful, the component must be
+ * displayable, showing, and focusable, and its ancestor top-level
+ * Window must be focused.
+ *
+ * If the return value is false, the request is guaranteed to fail.
+ * If the return value is true, the request will succeed unless it
+ * is vetoed or something in the native windowing system intervenes,
+ * preventing this Component's top-level ancestor from becoming
+ * focused. This method is meant to be called by derived
+ * lightweight Components that want to avoid unnecessary repainting
+ * when they know a given focus transfer need only be temporary.
+ *
+ * @param temporary true if the focus request is temporary
+ * @return true if the request has a chance of success
+ * @see #requestFocus ()
+ * @see FocusEvent
+ * @see #addFocusListener (FocusListener)
+ * @see #isFocusable ()
+ * @see #isDisplayable ()
+ * @see KeyboardFocusManager#clearGlobalFocusOwner ()
+ * @since 1.4
+ */
+ protected boolean requestFocusInWindow (boolean temporary)
+ {
+ return requestFocusImpl(temporary, false);
+ }
+
+ /**
+ * Helper method for all 4 requestFocus variants.
+ *
+ * @param temporary indicates if the focus change is temporary
+ * @param focusWindow indicates if the window focus may be changed
+ *
+ * @return <code>false</code> if the request has been definitely denied,
+ * <code>true</code> otherwise
+ */
+ private boolean requestFocusImpl(boolean temporary, boolean focusWindow)
+ {
+ boolean retval = false;
+
+ // Don't try to focus non-focusable and non-visible components.
+ if (isFocusable() && isVisible())
+ {
+ ComponentPeer myPeer = peer;
+ if (peer != null)
+ {
+ // Find Window ancestor and find out if we're showing while
+ // doing this.
+ boolean showing = true;
+ Component window = this;
+ while (! (window instanceof Window))
+ {
+ if (! window.isVisible())
+ showing = false;
+ window = window.parent;
+ }
+ // Don't allow focus when there is no window or the window
+ // is not focusable.
+ if (window != null && ((Window) window).isFocusableWindow()
+ && showing)
+ {
+ // Search for nearest heavy ancestor (including this
+ // component).
+ Component heavyweightParent = this;
+ while (heavyweightParent.peer instanceof LightweightPeer)
+ heavyweightParent = heavyweightParent.parent;
+
+ // Don't allow focus on lightweight components without
+ // visible heavyweight ancestor
+ if (heavyweightParent != null && heavyweightParent.isVisible())
+ {
+ // Don't allow focus when heavyweightParent has no peer.
+ myPeer = heavyweightParent.peer;
+ if (myPeer != null)
+ {
+ // Register lightweight focus request.
+ if (heavyweightParent != this)
+ {
+ KeyboardFocusManager
+ .addLightweightFocusRequest(heavyweightParent,
+ this);
+ }
+
+ // Try to focus the component.
+ long time = EventQueue.getMostRecentEventTime();
+ boolean success = myPeer.requestFocus(this, temporary,
+ focusWindow,
+ time);
+ if (! success)
+ {
+ // Dequeue key events if focus request failed.
+ KeyboardFocusManager kfm =
+ KeyboardFocusManager.getCurrentKeyboardFocusManager();
+ kfm.dequeueKeyEvents(time, this);
+ }
+ retval = success;
+ }
+ }
+ }
+ }
+ }
+ return retval;
+ }
+
+ /**
+ * Transfers focus to the next component in the focus traversal
+ * order, as though this were the current focus owner.
+ *
+ * @see #requestFocus()
+ * @since 1.1
+ */
+ public void transferFocus ()
+ {
+ nextFocus ();
+ }
+
+ /**
+ * Returns the root container that owns the focus cycle where this
+ * component resides. A focus cycle root is in two cycles, one as
+ * the ancestor, and one as the focusable element; this call always
+ * returns the ancestor.
+ *
+ * @return the ancestor container that owns the focus cycle
+ * @since 1.4
+ */
+ public Container getFocusCycleRootAncestor ()
+ {
+ Container parent = getParent ();
+
+ while (parent != null && !parent.isFocusCycleRoot())
+ parent = parent.getParent ();
+
+ return parent;
+ }
+
+ /**
+ * Tests if the container is the ancestor of the focus cycle that
+ * this component belongs to.
+ *
+ * @param c the container to test
+ * @return true if c is the focus cycle root
+ * @since 1.4
+ */
+ public boolean isFocusCycleRoot (Container c)
+ {
+ return c == getFocusCycleRootAncestor ();
+ }
+
+ /**
+ * AWT 1.0 focus event processor. Transfers focus to the next
+ * component in the focus traversal order, as though this were the
+ * current focus owner.
+ *
+ * @deprecated use {@link #transferFocus ()} instead
+ */
+ public void nextFocus ()
+ {
+ // Find the nearest valid (== showing && focusable && enabled) focus
+ // cycle root ancestor and the focused component in it.
+ Container focusRoot = getFocusCycleRootAncestor();
+ Component focusComp = this;
+ while (focusRoot != null
+ && ! (focusRoot.isShowing() && focusRoot.isFocusable()
+ && focusRoot.isEnabled()))
+ {
+ focusComp = focusRoot;
+ focusRoot = focusComp.getFocusCycleRootAncestor();
+ }
+
+ if (focusRoot != null)
+ {
+ // First try to get the componentBefore from the policy.
+ FocusTraversalPolicy policy = focusRoot.getFocusTraversalPolicy();
+ Component nextFocus = policy.getComponentAfter(focusRoot, focusComp);
+
+ // If this fails, then ask for the defaultComponent.
+ if (nextFocus == null)
+ nextFocus = policy.getDefaultComponent(focusRoot);
+
+ // Request focus on this component, if not null.
+ if (nextFocus != null)
+ nextFocus.requestFocus();
+ }
+ }
+
+ /**
+ * Transfers focus to the previous component in the focus traversal
+ * order, as though this were the current focus owner.
+ *
+ * @see #requestFocus ()
+ * @since 1.4
+ */
+ public void transferFocusBackward ()
+ {
+ // Find the nearest valid (== showing && focusable && enabled) focus
+ // cycle root ancestor and the focused component in it.
+ Container focusRoot = getFocusCycleRootAncestor();
+ Component focusComp = this;
+ while (focusRoot != null
+ && ! (focusRoot.isShowing() && focusRoot.isFocusable()
+ && focusRoot.isEnabled()))
+ {
+ focusComp = focusRoot;
+ focusRoot = focusComp.getFocusCycleRootAncestor();
+ }
+
+ if (focusRoot != null)
+ {
+ // First try to get the componentBefore from the policy.
+ FocusTraversalPolicy policy = focusRoot.getFocusTraversalPolicy();
+ Component nextFocus = policy.getComponentBefore(focusRoot, focusComp);
+
+ // If this fails, then ask for the defaultComponent.
+ if (nextFocus == null)
+ nextFocus = policy.getDefaultComponent(focusRoot);
+
+ // Request focus on this component, if not null.
+ if (nextFocus != null)
+ nextFocus.requestFocus();
+ }
+ }
+
+ /**
+ * Transfers focus to the focus cycle root of this component.
+ * However, if this is a Window, the default focus owner in the
+ * window in the current focus cycle is focused instead.
+ *
+ * @see #requestFocus()
+ * @see #isFocusCycleRoot(Container)
+ * @since 1.4
+ */
+ public void transferFocusUpCycle ()
+ {
+ // Find the nearest focus cycle root ancestor that is itself
+ // focusable, showing and enabled.
+ Container focusCycleRoot = getFocusCycleRootAncestor();
+ while (focusCycleRoot != null &&
+ ! (focusCycleRoot.isShowing() && focusCycleRoot.isFocusable()
+ && focusCycleRoot.isEnabled()))
+ {
+ focusCycleRoot = focusCycleRoot.getFocusCycleRootAncestor();
+ }
+
+ KeyboardFocusManager fm =
+ KeyboardFocusManager.getCurrentKeyboardFocusManager();
+
+ if (focusCycleRoot != null)
+ {
+ // If we found a focus cycle root, then we make this the new
+ // focused component, and make it's focus cycle root the new
+ // global focus cycle root. If the found root has no focus cycle
+ // root ancestor itself, then the component will be both the focused
+ // component and the new global focus cycle root.
+ Container focusCycleAncestor =
+ focusCycleRoot.getFocusCycleRootAncestor();
+ Container globalFocusCycleRoot;
+ if (focusCycleAncestor == null)
+ globalFocusCycleRoot = focusCycleRoot;
+ else
+ globalFocusCycleRoot = focusCycleAncestor;
+
+ fm.setGlobalCurrentFocusCycleRoot(globalFocusCycleRoot);
+ focusCycleRoot.requestFocus();
+ }
+ else
+ {
+ // If this component has no applicable focus cycle root, we try
+ // find the nearest window and set this as the new global focus cycle
+ // root and the default focus component of this window the new focused
+ // component.
+ Container cont;
+ if (this instanceof Container)
+ cont = (Container) this;
+ else
+ cont = getParent();
+
+ while (cont != null && !(cont instanceof Window))
+ cont = cont.getParent();
+
+ if (cont != null)
+ {
+ FocusTraversalPolicy policy = cont.getFocusTraversalPolicy();
+ Component focusComp = policy.getDefaultComponent(cont);
+ if (focusComp != null)
+ {
+ fm.setGlobalCurrentFocusCycleRoot(cont);
+ focusComp.requestFocus();
+ }
+ }
+ }
+ }
+
+ /**
+ * Tests if this component is the focus owner. Use {@link
+ * #isFocusOwner ()} instead.
+ *
+ * @return true if this component owns focus
+ * @since 1.2
+ */
+ public boolean hasFocus ()
+ {
+ KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
+
+ Component focusOwner = manager.getFocusOwner ();
+
+ return this == focusOwner;
+ }
+
+ /**
+ * Tests if this component is the focus owner.
+ *
+ * @return true if this component owns focus
+ * @since 1.4
+ */
+ public boolean isFocusOwner()
+ {
+ return hasFocus ();
+ }
+
+ /**
+ * Adds the specified popup menu to this component.
+ *
+ * @param popup the popup menu to be added
+ *
+ * @see #remove(MenuComponent)
+ *
+ * @since 1.1
+ */
+ public synchronized void add(PopupMenu popup)
+ {
+ if (popups == null)
+ popups = new Vector();
+ popups.add(popup);
+
+ if (popup.parent != null)
+ popup.parent.remove(popup);
+ popup.parent = this;
+ if (peer != null)
+ popup.addNotify();
+ }
+
+ /**
+ * Removes the specified popup menu from this component.
+ *
+ * @param popup the popup menu to remove
+ * @see #add(PopupMenu)
+ * @since 1.1
+ */
+ public synchronized void remove(MenuComponent popup)
+ {
+ if (popups != null)
+ popups.remove(popup);
+ }
+
+ /**
+ * Returns a debugging string representing this component. The string may
+ * be empty but not null.
+ *
+ * @return a string representing this component
+ */
+ protected String paramString()
+ {
+ CPStringBuilder param = new CPStringBuilder();
+ String name = getName();
+ if (name != null)
+ param.append(name).append(",");
+ param.append(x).append(",").append(y).append(",").append(width)
+ .append("x").append(height);
+ if (! isValid())
+ param.append(",invalid");
+ if (! isVisible())
+ param.append(",invisible");
+ if (! isEnabled())
+ param.append(",disabled");
+ if (! isOpaque())
+ param.append(",translucent");
+ if (isDoubleBuffered())
+ param.append(",doublebuffered");
+ if (parent == null)
+ param.append(",parent=null");
+ else
+ param.append(",parent=").append(parent.getName());
+ return param.toString();
+ }
+
+ /**
+ * Returns a string representation of this component. This is implemented
+ * as <code>getClass().getName() + '[' + paramString() + ']'</code>.
+ *
+ * @return a string representation of this component
+ */
+ public String toString()
+ {
+ return getClass().getName() + '[' + paramString() + ']';
+ }
+
+ /**
+ * Prints a listing of this component to <code>System.out</code>.
+ *
+ * @see #list(PrintStream)
+ */
+ public void list()
+ {
+ list(System.out, 0);
+ }
+
+ /**
+ * Prints a listing of this component to the specified print stream.
+ *
+ * @param out the <code>PrintStream</code> to print to
+ */
+ public void list(PrintStream out)
+ {
+ list(out, 0);
+ }
+
+ /**
+ * Prints a listing of this component to the specified print stream,
+ * starting at the specified indentation point.
+ *
+ * @param out the <code>PrintStream</code> to print to
+ * @param indent the indentation point
+ */
+ public void list(PrintStream out, int indent)
+ {
+ for (int i = 0; i < indent; ++i)
+ out.print(' ');
+ out.println(toString());
+ }
+
+ /**
+ * Prints a listing of this component to the specified print writer.
+ *
+ * @param out the <code>PrintWrinter</code> to print to
+ * @since 1.1
+ */
+ public void list(PrintWriter out)
+ {
+ list(out, 0);
+ }
+
+ /**
+ * Prints a listing of this component to the specified print writer,
+ * starting at the specified indentation point.
+ *
+ * @param out the <code>PrintWriter</code> to print to
+ * @param indent the indentation point
+ * @since 1.1
+ */
+ public void list(PrintWriter out, int indent)
+ {
+ for (int i = 0; i < indent; ++i)
+ out.print(' ');
+ out.println(toString());
+ }
+
+ /**
+ * Adds the specified property listener to this component. This is harmless
+ * if the listener is null, but if the listener has already been registered,
+ * it will now be registered twice. The property listener ignores inherited
+ * properties. Recognized properties include:<br>
+ * <ul>
+ * <li>the font (<code>"font"</code>)</li>
+ * <li>the background color (<code>"background"</code>)</li>
+ * <li>the foreground color (<code>"foreground"</code>)</li>
+ * <li>the focusability (<code>"focusable"</code>)</li>
+ * <li>the focus key traversal enabled state
+ * (<code>"focusTraversalKeysEnabled"</code>)</li>
+ * <li>the set of forward traversal keys
+ * (<code>"forwardFocusTraversalKeys"</code>)</li>
+ * <li>the set of backward traversal keys
+ * (<code>"backwardFocusTraversalKeys"</code>)</li>
+ * <li>the set of up-cycle traversal keys
+ * (<code>"upCycleFocusTraversalKeys"</code>)</li>
+ * </ul>
+ *
+ * @param listener the new listener to add
+ * @see #removePropertyChangeListener(PropertyChangeListener)
+ * @see #getPropertyChangeListeners()
+ * @see #addPropertyChangeListener(String, PropertyChangeListener)
+ * @since 1.1
+ */
+ public void addPropertyChangeListener(PropertyChangeListener listener)
+ {
+ if (changeSupport == null)
+ changeSupport = new PropertyChangeSupport(this);
+ changeSupport.addPropertyChangeListener(listener);
+ }
+
+ /**
+ * Removes the specified property listener from the component. This is
+ * harmless if the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see #addPropertyChangeListener(PropertyChangeListener)
+ * @see #getPropertyChangeListeners()
+ * @see #removePropertyChangeListener(String, PropertyChangeListener)
+ * @since 1.1
+ */
+ public void removePropertyChangeListener(PropertyChangeListener listener)
+ {
+ if (changeSupport != null)
+ changeSupport.removePropertyChangeListener(listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addPropertyChangeListener(PropertyChangeListener)
+ * @see #removePropertyChangeListener(PropertyChangeListener)
+ * @see #getPropertyChangeListeners(String)
+ * @since 1.4
+ */
+ public PropertyChangeListener[] getPropertyChangeListeners()
+ {
+ return changeSupport == null ? new PropertyChangeListener[0]
+ : changeSupport.getPropertyChangeListeners();
+ }
+
+ /**
+ * Adds the specified property listener to this component. This is harmless
+ * if the listener is null, but if the listener has already been registered,
+ * it will now be registered twice. The property listener ignores inherited
+ * properties. The listener is keyed to a single property. Recognized
+ * properties include:<br>
+ * <ul>
+ * <li>the font (<code>"font"</code>)</li>
+ * <li>the background color (<code>"background"</code>)</li>
+ * <li>the foreground color (<code>"foreground"</code>)</li>
+ * <li>the focusability (<code>"focusable"</code>)</li>
+ * <li>the focus key traversal enabled state
+ * (<code>"focusTraversalKeysEnabled"</code>)</li>
+ * <li>the set of forward traversal keys
+ * (<code>"forwardFocusTraversalKeys"</code>)</li>
+p * <li>the set of backward traversal keys
+ * (<code>"backwardFocusTraversalKeys"</code>)</li>
+ * <li>the set of up-cycle traversal keys
+ * (<code>"upCycleFocusTraversalKeys"</code>)</li>
+ * </ul>
+ *
+ * @param propertyName the property name to filter on
+ * @param listener the new listener to add
+ * @see #removePropertyChangeListener(String, PropertyChangeListener)
+ * @see #getPropertyChangeListeners(String)
+ * @see #addPropertyChangeListener(PropertyChangeListener)
+ * @since 1.1
+ */
+ public void addPropertyChangeListener(String propertyName,
+ PropertyChangeListener listener)
+ {
+ if (changeSupport == null)
+ changeSupport = new PropertyChangeSupport(this);
+ changeSupport.addPropertyChangeListener(propertyName, listener);
+ }
+
+ /**
+ * Removes the specified property listener on a particular property from
+ * the component. This is harmless if the listener was not previously
+ * registered.
+ *
+ * @param propertyName the property name to filter on
+ * @param listener the listener to remove
+ * @see #addPropertyChangeListener(String, PropertyChangeListener)
+ * @see #getPropertyChangeListeners(String)
+ * @see #removePropertyChangeListener(PropertyChangeListener)
+ * @since 1.1
+ */
+ public void removePropertyChangeListener(String propertyName,
+ PropertyChangeListener listener)
+ {
+ if (changeSupport != null)
+ changeSupport.removePropertyChangeListener(propertyName, listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners on the named property that
+ * are registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addPropertyChangeListener(String, PropertyChangeListener)
+ * @see #removePropertyChangeListener(String, PropertyChangeListener)
+ * @see #getPropertyChangeListeners()
+ * @since 1.4
+ */
+ public PropertyChangeListener[] getPropertyChangeListeners(String property)
+ {
+ return changeSupport == null ? new PropertyChangeListener[0]
+ : changeSupport.getPropertyChangeListeners(property);
+ }
+
+ /**
+ * Report a change in a bound property to any registered property listeners.
+ *
+ * @param propertyName the property that changed
+ * @param oldValue the old property value
+ * @param newValue the new property value
+ */
+ protected void firePropertyChange(String propertyName, Object oldValue,
+ Object newValue)
+ {
+ if (changeSupport != null)
+ changeSupport.firePropertyChange(propertyName, oldValue, newValue);
+ }
+
+ /**
+ * Report a change in a bound property to any registered property listeners.
+ *
+ * @param propertyName the property that changed
+ * @param oldValue the old property value
+ * @param newValue the new property value
+ */
+ protected void firePropertyChange(String propertyName, boolean oldValue,
+ boolean newValue)
+ {
+ if (changeSupport != null)
+ changeSupport.firePropertyChange(propertyName, oldValue, newValue);
+ }
+
+ /**
+ * Report a change in a bound property to any registered property listeners.
+ *
+ * @param propertyName the property that changed
+ * @param oldValue the old property value
+ * @param newValue the new property value
+ */
+ protected void firePropertyChange(String propertyName, int oldValue,
+ int newValue)
+ {
+ if (changeSupport != null)
+ changeSupport.firePropertyChange(propertyName, oldValue, newValue);
+ }
+
+ /**
+ * Report a change in a bound property to any registered property listeners.
+ *
+ * @param propertyName the property that changed
+ * @param oldValue the old property value
+ * @param newValue the new property value
+ *
+ * @since 1.5
+ */
+ public void firePropertyChange(String propertyName, byte oldValue,
+ byte newValue)
+ {
+ if (changeSupport != null)
+ changeSupport.firePropertyChange(propertyName, new Byte(oldValue),
+ new Byte(newValue));
+ }
+
+ /**
+ * Report a change in a bound property to any registered property listeners.
+ *
+ * @param propertyName the property that changed
+ * @param oldValue the old property value
+ * @param newValue the new property value
+ *
+ * @since 1.5
+ */
+ public void firePropertyChange(String propertyName, char oldValue,
+ char newValue)
+ {
+ if (changeSupport != null)
+ changeSupport.firePropertyChange(propertyName, new Character(oldValue),
+ new Character(newValue));
+ }
+
+ /**
+ * Report a change in a bound property to any registered property listeners.
+ *
+ * @param propertyName the property that changed
+ * @param oldValue the old property value
+ * @param newValue the new property value
+ *
+ * @since 1.5
+ */
+ public void firePropertyChange(String propertyName, short oldValue,
+ short newValue)
+ {
+ if (changeSupport != null)
+ changeSupport.firePropertyChange(propertyName, new Short(oldValue),
+ new Short(newValue));
+ }
+
+ /**
+ * Report a change in a bound property to any registered property listeners.
+ *
+ * @param propertyName the property that changed
+ * @param oldValue the old property value
+ * @param newValue the new property value
+ *
+ * @since 1.5
+ */
+ public void firePropertyChange(String propertyName, long oldValue,
+ long newValue)
+ {
+ if (changeSupport != null)
+ changeSupport.firePropertyChange(propertyName, new Long(oldValue),
+ new Long(newValue));
+ }
+
+ /**
+ * Report a change in a bound property to any registered property listeners.
+ *
+ * @param propertyName the property that changed
+ * @param oldValue the old property value
+ * @param newValue the new property value
+ *
+ * @since 1.5
+ */
+ public void firePropertyChange(String propertyName, float oldValue,
+ float newValue)
+ {
+ if (changeSupport != null)
+ changeSupport.firePropertyChange(propertyName, new Float(oldValue),
+ new Float(newValue));
+ }
+
+
+ /**
+ * Report a change in a bound property to any registered property listeners.
+ *
+ * @param propertyName the property that changed
+ * @param oldValue the old property value
+ * @param newValue the new property value
+ *
+ * @since 1.5
+ */
+ public void firePropertyChange(String propertyName, double oldValue,
+ double newValue)
+ {
+ if (changeSupport != null)
+ changeSupport.firePropertyChange(propertyName, new Double(oldValue),
+ new Double(newValue));
+ }
+
+ /**
+ * Sets the text layout orientation of this component. New components default
+ * to UNKNOWN (which behaves like LEFT_TO_RIGHT). This method affects only
+ * the current component, while
+ * {@link #applyComponentOrientation(ComponentOrientation)} affects the
+ * entire hierarchy.
+ *
+ * @param o the new orientation (<code>null</code> is accepted)
+ * @see #getComponentOrientation()
+ */
+ public void setComponentOrientation(ComponentOrientation o)
+ {
+
+ ComponentOrientation oldOrientation = componentOrientation;
+ componentOrientation = o;
+ firePropertyChange("componentOrientation", oldOrientation, o);
+ }
+
+ /**
+ * Determines the text layout orientation used by this component.
+ *
+ * @return the component orientation (this can be <code>null</code>)
+ * @see #setComponentOrientation(ComponentOrientation)
+ */
+ public ComponentOrientation getComponentOrientation()
+ {
+ return componentOrientation;
+ }
+
+ /**
+ * Sets the text layout orientation of this component. New components default
+ * to UNKNOWN (which behaves like LEFT_TO_RIGHT). This method affects the
+ * entire hierarchy, while
+ * {@link #setComponentOrientation(ComponentOrientation)} affects only the
+ * current component.
+ *
+ * @param o the new orientation
+ * @throws NullPointerException if o is null
+ * @see #getComponentOrientation()
+ * @since 1.4
+ */
+ public void applyComponentOrientation(ComponentOrientation o)
+ {
+ setComponentOrientation(o);
+ }
+
+ /**
+ * Returns the accessibility framework context of this class. Component is
+ * not accessible, so the default implementation returns null. Subclasses
+ * must override this behavior, and return an appropriate subclass of
+ * {@link AccessibleAWTComponent}.
+ *
+ * @return the accessibility context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ return null;
+ }
+
+
+ // Helper methods; some are package visible for use by subclasses.
+
+ /**
+ * Subclasses should override this to return unique component names like
+ * "menuitem0".
+ *
+ * @return the generated name for this component
+ */
+ String generateName()
+ {
+ // Component is abstract.
+ return null;
+ }
+
+ /**
+ * Sets the peer for this component.
+ *
+ * @param peer the new peer
+ */
+ final void setPeer(ComponentPeer peer)
+ {
+ this.peer = peer;
+ }
+
+ /**
+ * Translate an AWT 1.1 event ({@link AWTEvent}) into an AWT 1.0
+ * event ({@link Event}).
+ *
+ * @param e an AWT 1.1 event to translate
+ *
+ * @return an AWT 1.0 event representing e
+ */
+ static Event translateEvent (AWTEvent e)
+ {
+ Object target = e.getSource ();
+ Event translated = null;
+
+ if (e instanceof WindowEvent)
+ {
+ WindowEvent we = (WindowEvent) e;
+ int id = we.id;
+ int newId = 0;
+
+ switch (id)
+ {
+ case WindowEvent.WINDOW_DEICONIFIED:
+ newId = Event.WINDOW_DEICONIFY;
+ break;
+ case WindowEvent.WINDOW_CLOSED:
+ case WindowEvent.WINDOW_CLOSING:
+ newId = Event.WINDOW_DESTROY;
+ break;
+ case WindowEvent.WINDOW_ICONIFIED:
+ newId = Event.WINDOW_ICONIFY;
+ break;
+ case WindowEvent.WINDOW_GAINED_FOCUS:
+ newId = Event.GOT_FOCUS;
+ break;
+ case WindowEvent.WINDOW_LOST_FOCUS:
+ newId = Event.LOST_FOCUS;
+ break;
+ default:
+ return null;
+ }
+
+ translated = new Event(target, 0, newId, 0, 0, 0, 0);
+ }
+ else if (e instanceof InputEvent)
+ {
+ InputEvent ie = (InputEvent) e;
+ long when = ie.getWhen ();
+
+ int oldID = 0;
+ int id = e.getID ();
+
+ int oldMods = 0;
+ int mods = ie.getModifiersEx ();
+
+ if ((mods & InputEvent.BUTTON2_DOWN_MASK) != 0)
+ oldMods |= Event.META_MASK;
+ else if ((mods & InputEvent.BUTTON3_DOWN_MASK) != 0)
+ oldMods |= Event.ALT_MASK;
+
+ if ((mods & InputEvent.SHIFT_DOWN_MASK) != 0)
+ oldMods |= Event.SHIFT_MASK;
+
+ if ((mods & InputEvent.CTRL_DOWN_MASK) != 0)
+ oldMods |= Event.CTRL_MASK;
+
+ if ((mods & InputEvent.META_DOWN_MASK) != 0)
+ oldMods |= Event.META_MASK;
+
+ if ((mods & InputEvent.ALT_DOWN_MASK) != 0)
+ oldMods |= Event.ALT_MASK;
+
+ if (e instanceof MouseEvent && !ignoreOldMouseEvents())
+ {
+ if (id == MouseEvent.MOUSE_PRESSED)
+ oldID = Event.MOUSE_DOWN;
+ else if (id == MouseEvent.MOUSE_RELEASED)
+ oldID = Event.MOUSE_UP;
+ else if (id == MouseEvent.MOUSE_MOVED)
+ oldID = Event.MOUSE_MOVE;
+ else if (id == MouseEvent.MOUSE_DRAGGED)
+ oldID = Event.MOUSE_DRAG;
+ else if (id == MouseEvent.MOUSE_ENTERED)
+ oldID = Event.MOUSE_ENTER;
+ else if (id == MouseEvent.MOUSE_EXITED)
+ oldID = Event.MOUSE_EXIT;
+ else
+ // No analogous AWT 1.0 mouse event.
+ return null;
+
+ MouseEvent me = (MouseEvent) e;
+
+ translated = new Event (target, when, oldID,
+ me.getX (), me.getY (), 0, oldMods);
+ }
+ else if (e instanceof KeyEvent)
+ {
+ if (id == KeyEvent.KEY_PRESSED)
+ oldID = Event.KEY_PRESS;
+ else if (e.getID () == KeyEvent.KEY_RELEASED)
+ oldID = Event.KEY_RELEASE;
+ else
+ // No analogous AWT 1.0 key event.
+ return null;
+
+ int oldKey = 0;
+ int newKey = ((KeyEvent) e).getKeyCode ();
+ switch (newKey)
+ {
+ case KeyEvent.VK_BACK_SPACE:
+ oldKey = Event.BACK_SPACE;
+ break;
+ case KeyEvent.VK_CAPS_LOCK:
+ oldKey = Event.CAPS_LOCK;
+ break;
+ case KeyEvent.VK_DELETE:
+ oldKey = Event.DELETE;
+ break;
+ case KeyEvent.VK_DOWN:
+ case KeyEvent.VK_KP_DOWN:
+ oldKey = Event.DOWN;
+ break;
+ case KeyEvent.VK_END:
+ oldKey = Event.END;
+ break;
+ case KeyEvent.VK_ENTER:
+ oldKey = Event.ENTER;
+ break;
+ case KeyEvent.VK_ESCAPE:
+ oldKey = Event.ESCAPE;
+ break;
+ case KeyEvent.VK_F1:
+ oldKey = Event.F1;
+ break;
+ case KeyEvent.VK_F10:
+ oldKey = Event.F10;
+ break;
+ case KeyEvent.VK_F11:
+ oldKey = Event.F11;
+ break;
+ case KeyEvent.VK_F12:
+ oldKey = Event.F12;
+ break;
+ case KeyEvent.VK_F2:
+ oldKey = Event.F2;
+ break;
+ case KeyEvent.VK_F3:
+ oldKey = Event.F3;
+ break;
+ case KeyEvent.VK_F4:
+ oldKey = Event.F4;
+ break;
+ case KeyEvent.VK_F5:
+ oldKey = Event.F5;
+ break;
+ case KeyEvent.VK_F6:
+ oldKey = Event.F6;
+ break;
+ case KeyEvent.VK_F7:
+ oldKey = Event.F7;
+ break;
+ case KeyEvent.VK_F8:
+ oldKey = Event.F8;
+ break;
+ case KeyEvent.VK_F9:
+ oldKey = Event.F9;
+ break;
+ case KeyEvent.VK_HOME:
+ oldKey = Event.HOME;
+ break;
+ case KeyEvent.VK_INSERT:
+ oldKey = Event.INSERT;
+ break;
+ case KeyEvent.VK_LEFT:
+ case KeyEvent.VK_KP_LEFT:
+ oldKey = Event.LEFT;
+ break;
+ case KeyEvent.VK_NUM_LOCK:
+ oldKey = Event.NUM_LOCK;
+ break;
+ case KeyEvent.VK_PAUSE:
+ oldKey = Event.PAUSE;
+ break;
+ case KeyEvent.VK_PAGE_DOWN:
+ oldKey = Event.PGDN;
+ break;
+ case KeyEvent.VK_PAGE_UP:
+ oldKey = Event.PGUP;
+ break;
+ case KeyEvent.VK_PRINTSCREEN:
+ oldKey = Event.PRINT_SCREEN;
+ break;
+ case KeyEvent.VK_RIGHT:
+ case KeyEvent.VK_KP_RIGHT:
+ oldKey = Event.RIGHT;
+ break;
+ case KeyEvent.VK_SCROLL_LOCK:
+ oldKey = Event.SCROLL_LOCK;
+ break;
+ case KeyEvent.VK_TAB:
+ oldKey = Event.TAB;
+ break;
+ case KeyEvent.VK_UP:
+ case KeyEvent.VK_KP_UP:
+ oldKey = Event.UP;
+ break;
+ default:
+ oldKey = ((KeyEvent) e).getKeyChar();
+ }
+
+ translated = new Event (target, when, oldID,
+ 0, 0, oldKey, oldMods);
+ }
+ }
+ else if (e instanceof AdjustmentEvent)
+ {
+ AdjustmentEvent ae = (AdjustmentEvent) e;
+ int type = ae.getAdjustmentType();
+ int oldType;
+ if (type == AdjustmentEvent.BLOCK_DECREMENT)
+ oldType = Event.SCROLL_PAGE_UP;
+ else if (type == AdjustmentEvent.BLOCK_INCREMENT)
+ oldType = Event.SCROLL_PAGE_DOWN;
+ else if (type == AdjustmentEvent.TRACK)
+ oldType = Event.SCROLL_ABSOLUTE;
+ else if (type == AdjustmentEvent.UNIT_DECREMENT)
+ oldType = Event.SCROLL_LINE_UP;
+ else if (type == AdjustmentEvent.UNIT_INCREMENT)
+ oldType = Event.SCROLL_LINE_DOWN;
+ else
+ oldType = type;
+ translated = new Event(target, oldType, new Integer(ae.getValue()));
+ }
+ else if (e instanceof ActionEvent)
+ translated = new Event (target, Event.ACTION_EVENT,
+ ((ActionEvent) e).getActionCommand ());
+
+ return translated;
+ }
+
+ /**
+ * Implementation of dispatchEvent. Allows trusted package classes
+ * to dispatch additional events first. This implementation first
+ * translates <code>e</code> to an AWT 1.0 event and sends the
+ * result to {@link #postEvent}. If the AWT 1.0 event is not
+ * handled, and events of type <code>e</code> are enabled for this
+ * component, e is passed on to {@link #processEvent}.
+ *
+ * @param e the event to dispatch
+ */
+ void dispatchEventImpl(AWTEvent e)
+ {
+ // Update the component's knowledge about the size.
+ // Important: Please look at the big comment in ComponentReshapeEvent
+ // to learn why we did it this way. If you change this code, make
+ // sure that the peer->AWT bounds update still works.
+ // (for instance: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29448 )
+ if (e instanceof ComponentReshapeEvent)
+ {
+ ComponentReshapeEvent reshape = (ComponentReshapeEvent) e;
+ x = reshape.x;
+ y = reshape.y;
+ width = reshape.width;
+ height = reshape.height;
+ return;
+ }
+
+ // Retarget focus events before dispatching it to the KeyboardFocusManager
+ // in order to handle lightweight components properly.
+ boolean dispatched = false;
+ if (! e.isFocusManagerEvent)
+ {
+ e = KeyboardFocusManager.retargetFocusEvent(e);
+ dispatched = KeyboardFocusManager.getCurrentKeyboardFocusManager()
+ .dispatchEvent(e);
+ }
+
+ if (! dispatched)
+ {
+ // Give toolkit a chance to dispatch the event
+ // to globally registered listeners.
+ Toolkit.getDefaultToolkit().globalDispatchEvent(e);
+
+ if (newEventsOnly)
+ {
+ if (eventTypeEnabled(e.id))
+ processEvent(e);
+ }
+ else
+ {
+ Event oldEvent = translateEvent(e);
+ if (oldEvent != null)
+ postEvent (oldEvent);
+ }
+ if (peer != null)
+ peer.handleEvent(e);
+ }
+ }
+
+ /**
+ * Tells whether or not an event type is enabled.
+ */
+ boolean eventTypeEnabled (int type)
+ {
+ if (type > AWTEvent.RESERVED_ID_MAX)
+ return true;
+
+ switch (type)
+ {
+ case HierarchyEvent.HIERARCHY_CHANGED:
+ return (hierarchyListener != null
+ || (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0);
+
+ case HierarchyEvent.ANCESTOR_MOVED:
+ case HierarchyEvent.ANCESTOR_RESIZED:
+ return (hierarchyBoundsListener != null
+ || (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0);
+
+ case ComponentEvent.COMPONENT_HIDDEN:
+ case ComponentEvent.COMPONENT_MOVED:
+ case ComponentEvent.COMPONENT_RESIZED:
+ case ComponentEvent.COMPONENT_SHOWN:
+ return (componentListener != null
+ || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0);
+
+ case KeyEvent.KEY_PRESSED:
+ case KeyEvent.KEY_RELEASED:
+ case KeyEvent.KEY_TYPED:
+ return (keyListener != null
+ || (eventMask & AWTEvent.KEY_EVENT_MASK) != 0);
+
+ case MouseEvent.MOUSE_CLICKED:
+ case MouseEvent.MOUSE_ENTERED:
+ case MouseEvent.MOUSE_EXITED:
+ case MouseEvent.MOUSE_PRESSED:
+ case MouseEvent.MOUSE_RELEASED:
+ return (mouseListener != null
+ || (eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0);
+ case MouseEvent.MOUSE_MOVED:
+ case MouseEvent.MOUSE_DRAGGED:
+ return (mouseMotionListener != null
+ || (eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0);
+ case MouseEvent.MOUSE_WHEEL:
+ return (mouseWheelListener != null
+ || (eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0);
+
+ case FocusEvent.FOCUS_GAINED:
+ case FocusEvent.FOCUS_LOST:
+ return (focusListener != null
+ || (eventMask & AWTEvent.FOCUS_EVENT_MASK) != 0);
+
+ case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED:
+ case InputMethodEvent.CARET_POSITION_CHANGED:
+ return (inputMethodListener != null
+ || (eventMask & AWTEvent.INPUT_METHOD_EVENT_MASK) != 0);
+
+ case PaintEvent.PAINT:
+ case PaintEvent.UPDATE:
+ return (eventMask & AWTEvent.PAINT_EVENT_MASK) != 0;
+
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Returns <code>true</code> when this component and all of its ancestors
+ * are visible, <code>false</code> otherwise.
+ *
+ * @return <code>true</code> when this component and all of its ancestors
+ * are visible, <code>false</code> otherwise
+ */
+ boolean isHierarchyVisible()
+ {
+ boolean visible = isVisible();
+ Component comp = parent;
+ while (comp != null && visible)
+ {
+ comp = comp.parent;
+ if (comp != null)
+ visible = visible && comp.isVisible();
+ }
+ return visible;
+ }
+
+ /**
+ * Returns the mouse pointer position relative to this Component's
+ * top-left corner.
+ *
+ * @return relative mouse pointer position
+ *
+ * @throws HeadlessException if in a headless environment
+ */
+ public Point getMousePosition() throws HeadlessException
+ {
+ return getMousePositionHelper(true);
+ }
+
+ Point getMousePositionHelper(boolean allowChildren) throws HeadlessException
+ {
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException("can't get mouse position"
+ + " in headless environment");
+ if (!isShowing())
+ return null;
+
+ Component parent = this;
+ int windowRelativeXOffset = 0;
+ int windowRelativeYOffset = 0;
+ while (parent != null && !(parent instanceof Window))
+ {
+ windowRelativeXOffset += parent.getX();
+ windowRelativeYOffset += parent.getY();
+ parent = parent.getParent();
+ }
+ if (parent == null)
+ return null;
+
+ Window window = (Window) parent;
+ if (!Toolkit.getDefaultToolkit()
+ .getMouseInfoPeer().isWindowUnderMouse(window))
+ return null;
+
+ PointerInfo info = MouseInfo.getPointerInfo();
+ Point mouseLocation = info.getLocation();
+ Point windowLocation = window.getLocationOnScreen();
+
+ int x = mouseLocation.x - windowLocation.x;
+ int y = mouseLocation.y - windowLocation.y;
+
+ if (!mouseOverComponent(window.getComponentAt(x, y), allowChildren))
+ return null;
+
+ return new Point(x - windowRelativeXOffset, y - windowRelativeYOffset);
+ }
+
+ boolean mouseOverComponent(Component component, boolean allowChildren)
+ {
+ return component == this;
+ }
+
+ /**
+ * This method is used to implement transferFocus(). CHILD is the child
+ * making the request. This is overridden by Container; when called for an
+ * ordinary component there is no child and so we always return null.
+ *
+ * FIXME: is this still needed, in light of focus traversal policies?
+ *
+ * @param child the component making the request
+ * @return the next component to focus on
+ */
+ Component findNextFocusComponent(Component child)
+ {
+ return null;
+ }
+
+ /**
+ * Deserializes this component. This regenerates all serializable listeners
+ * which were registered originally.
+ *
+ * @param s the stream to read from
+ * @throws ClassNotFoundException if deserialization fails
+ * @throws IOException if the stream fails
+ */
+ private void readObject(ObjectInputStream s)
+ throws ClassNotFoundException, IOException
+ {
+ s.defaultReadObject();
+ String key = (String) s.readObject();
+ while (key != null)
+ {
+ Object listener = s.readObject();
+ if ("componentL".equals(key))
+ addComponentListener((ComponentListener) listener);
+ else if ("focusL".equals(key))
+ addFocusListener((FocusListener) listener);
+ else if ("keyL".equals(key))
+ addKeyListener((KeyListener) listener);
+ else if ("mouseL".equals(key))
+ addMouseListener((MouseListener) listener);
+ else if ("mouseMotionL".equals(key))
+ addMouseMotionListener((MouseMotionListener) listener);
+ else if ("inputMethodL".equals(key))
+ addInputMethodListener((InputMethodListener) listener);
+ else if ("hierarchyL".equals(key))
+ addHierarchyListener((HierarchyListener) listener);
+ else if ("hierarchyBoundsL".equals(key))
+ addHierarchyBoundsListener((HierarchyBoundsListener) listener);
+ else if ("mouseWheelL".equals(key))
+ addMouseWheelListener((MouseWheelListener) listener);
+ key = (String) s.readObject();
+ }
+ }
+
+ /**
+ * Serializes this component. This ignores all listeners which do not
+ * implement Serializable, but includes those that do.
+ *
+ * @param s the stream to write to
+ * @throws IOException if the stream fails
+ */
+ private void writeObject(ObjectOutputStream s) throws IOException
+ {
+ s.defaultWriteObject();
+ AWTEventMulticaster.save(s, "componentL", componentListener);
+ AWTEventMulticaster.save(s, "focusL", focusListener);
+ AWTEventMulticaster.save(s, "keyL", keyListener);
+ AWTEventMulticaster.save(s, "mouseL", mouseListener);
+ AWTEventMulticaster.save(s, "mouseMotionL", mouseMotionListener);
+ AWTEventMulticaster.save(s, "inputMethodL", inputMethodListener);
+ AWTEventMulticaster.save(s, "hierarchyL", hierarchyListener);
+ AWTEventMulticaster.save(s, "hierarchyBoundsL", hierarchyBoundsListener);
+ AWTEventMulticaster.save(s, "mouseWheelL", mouseWheelListener);
+ s.writeObject(null);
+ }
+
+
+ // Nested classes.
+
+ /**
+ * This class fixes the bounds for a Heavyweight component that
+ * is placed inside a Lightweight container. When the lightweight is
+ * moved or resized, setBounds for the lightweight peer does nothing.
+ * Therefore, it was never moved on the screen. This class is
+ * attached to the lightweight, and it adjusts the position and size
+ * of the peer when notified.
+ * This is the same for show and hide.
+ */
+ class HeavyweightInLightweightListener
+ implements ComponentListener
+ {
+
+ /**
+ * Constructor. Adds component listener to lightweight parent.
+ *
+ * @param parent - the lightweight container.
+ */
+ public HeavyweightInLightweightListener(Container parent)
+ {
+ parent.addComponentListener(this);
+ }
+
+ /**
+ * This method is called when the component is resized.
+ *
+ * @param event the <code>ComponentEvent</code> indicating the resize
+ */
+ public void componentResized(ComponentEvent event)
+ {
+ // Nothing to do here, componentMoved will be called.
+ }
+
+ /**
+ * This method is called when the component is moved.
+ *
+ * @param event the <code>ComponentEvent</code> indicating the move
+ */
+ public void componentMoved(ComponentEvent event)
+ {
+ if (peer != null)
+ peer.setBounds(x, y, width, height);
+ }
+
+ /**
+ * This method is called when the component is made visible.
+ *
+ * @param event the <code>ComponentEvent</code> indicating the visibility
+ */
+ public void componentShown(ComponentEvent event)
+ {
+ if (isShowing())
+ peer.show();
+ }
+
+ /**
+ * This method is called when the component is hidden.
+ *
+ * @param event the <code>ComponentEvent</code> indicating the visibility
+ */
+ public void componentHidden(ComponentEvent event)
+ {
+ if (isShowing())
+ peer.hide();
+ }
+ }
+
+ /**
+ * This class provides accessibility support for subclasses of container.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.3
+ * @status updated to 1.4
+ */
+ protected abstract class AccessibleAWTComponent extends AccessibleContext
+ implements Serializable, AccessibleComponent
+ {
+ /**
+ * Compatible with JDK 1.3+.
+ */
+ private static final long serialVersionUID = 642321655757800191L;
+
+ /**
+ * Converts show/hide events to PropertyChange events, and is registered
+ * as a component listener on this component.
+ *
+ * @serial the component handler
+ */
+ protected ComponentListener accessibleAWTComponentHandler
+ = new AccessibleAWTComponentHandler();
+
+ /**
+ * Converts focus events to PropertyChange events, and is registered
+ * as a focus listener on this component.
+ *
+ * @serial the focus handler
+ */
+ protected FocusListener accessibleAWTFocusHandler
+ = new AccessibleAWTFocusHandler();
+
+ /**
+ * The default constructor.
+ */
+ protected AccessibleAWTComponent()
+ {
+ Component.this.addComponentListener(accessibleAWTComponentHandler);
+ Component.this.addFocusListener(accessibleAWTFocusHandler);
+ }
+
+ /**
+ * Adds a global property change listener to the accessible component.
+ *
+ * @param l the listener to add
+ * @see #ACCESSIBLE_NAME_PROPERTY
+ * @see #ACCESSIBLE_DESCRIPTION_PROPERTY
+ * @see #ACCESSIBLE_STATE_PROPERTY
+ * @see #ACCESSIBLE_VALUE_PROPERTY
+ * @see #ACCESSIBLE_SELECTION_PROPERTY
+ * @see #ACCESSIBLE_TEXT_PROPERTY
+ * @see #ACCESSIBLE_VISIBLE_DATA_PROPERTY
+ */
+ public void addPropertyChangeListener(PropertyChangeListener l)
+ {
+ Component.this.addPropertyChangeListener(l);
+ super.addPropertyChangeListener(l);
+ }
+
+ /**
+ * Removes a global property change listener from this accessible
+ * component.
+ *
+ * @param l the listener to remove
+ */
+ public void removePropertyChangeListener(PropertyChangeListener l)
+ {
+ Component.this.removePropertyChangeListener(l);
+ super.removePropertyChangeListener(l);
+ }
+
+ /**
+ * Returns the accessible name of this component. It is almost always
+ * wrong to return getName(), since it is not localized. In fact, for
+ * things like buttons, this should be the text of the button, not the
+ * name of the object. The tooltip text might also be appropriate.
+ *
+ * @return the name
+ * @see #setAccessibleName(String)
+ */
+ public String getAccessibleName()
+ {
+ return accessibleName;
+ }
+
+ /**
+ * Returns a brief description of this accessible context. This should
+ * be localized.
+ *
+ * @return a description of this component
+ * @see #setAccessibleDescription(String)
+ */
+ public String getAccessibleDescription()
+ {
+ return accessibleDescription;
+ }
+
+ /**
+ * Returns the role of this component.
+ *
+ * @return the accessible role
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.AWT_COMPONENT;
+ }
+
+ /**
+ * Returns a state set describing this component's state.
+ *
+ * @return a new state set
+ * @see AccessibleState
+ */
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ AccessibleStateSet s = new AccessibleStateSet();
+ if (Component.this.isEnabled())
+ s.add(AccessibleState.ENABLED);
+ if (isFocusable())
+ s.add(AccessibleState.FOCUSABLE);
+ if (isFocusOwner())
+ s.add(AccessibleState.FOCUSED);
+ // Note: While the java.awt.Component has an 'opaque' property, it
+ // seems that it is not added to the accessible state set here, even
+ // if this property is true. However, it is handled for
+ // javax.swing.JComponent, so we add it there.
+ if (Component.this.isShowing())
+ s.add(AccessibleState.SHOWING);
+ if (Component.this.isVisible())
+ s.add(AccessibleState.VISIBLE);
+ return s;
+ }
+
+ /**
+ * Returns the parent of this component, if it is accessible.
+ *
+ * @return the accessible parent
+ */
+ public Accessible getAccessibleParent()
+ {
+ if (accessibleParent == null)
+ {
+ Container parent = getParent();
+ accessibleParent = parent instanceof Accessible
+ ? (Accessible) parent : null;
+ }
+ return accessibleParent;
+ }
+
+ /**
+ * Returns the index of this component in its accessible parent.
+ *
+ * @return the index, or -1 if the parent is not accessible
+ * @see #getAccessibleParent()
+ */
+ public int getAccessibleIndexInParent()
+ {
+ if (getAccessibleParent() == null)
+ return -1;
+ AccessibleContext context
+ = ((Component) accessibleParent).getAccessibleContext();
+ if (context == null)
+ return -1;
+ for (int i = context.getAccessibleChildrenCount(); --i >= 0; )
+ if (context.getAccessibleChild(i) == Component.this)
+ return i;
+ return -1;
+ }
+
+ /**
+ * Returns the number of children of this component which implement
+ * Accessible. Subclasses must override this if they can have children.
+ *
+ * @return the number of accessible children, default 0
+ */
+ public int getAccessibleChildrenCount()
+ {
+ return 0;
+ }
+
+ /**
+ * Returns the ith accessible child. Subclasses must override this if
+ * they can have children.
+ *
+ * @return the ith accessible child, or null
+ * @see #getAccessibleChildrenCount()
+ */
+ public Accessible getAccessibleChild(int i)
+ {
+ return null;
+ }
+
+ /**
+ * Returns the locale of this component.
+ *
+ * @return the locale
+ * @throws IllegalComponentStateException if the locale is unknown
+ */
+ public Locale getLocale()
+ {
+ return Component.this.getLocale();
+ }
+
+ /**
+ * Returns this, since it is an accessible component.
+ *
+ * @return the accessible component
+ */
+ public AccessibleComponent getAccessibleComponent()
+ {
+ return this;
+ }
+
+ /**
+ * Gets the background color.
+ *
+ * @return the background color
+ * @see #setBackground(Color)
+ */
+ public Color getBackground()
+ {
+ return Component.this.getBackground();
+ }
+
+ /**
+ * Sets the background color.
+ *
+ * @param c the background color
+ * @see #getBackground()
+ * @see #isOpaque()
+ */
+ public void setBackground(Color c)
+ {
+ Component.this.setBackground(c);
+ }
+
+ /**
+ * Gets the foreground color.
+ *
+ * @return the foreground color
+ * @see #setForeground(Color)
+ */
+ public Color getForeground()
+ {
+ return Component.this.getForeground();
+ }
+
+ /**
+ * Sets the foreground color.
+ *
+ * @param c the foreground color
+ * @see #getForeground()
+ */
+ public void setForeground(Color c)
+ {
+ Component.this.setForeground(c);
+ }
+
+ /**
+ * Gets the cursor.
+ *
+ * @return the cursor
+ * @see #setCursor(Cursor)
+ */
+ public Cursor getCursor()
+ {
+ return Component.this.getCursor();
+ }
+
+ /**
+ * Sets the cursor.
+ *
+ * @param cursor the cursor
+ * @see #getCursor()
+ */
+ public void setCursor(Cursor cursor)
+ {
+ Component.this.setCursor(cursor);
+ }
+
+ /**
+ * Gets the font.
+ *
+ * @return the font
+ * @see #setFont(Font)
+ */
+ public Font getFont()
+ {
+ return Component.this.getFont();
+ }
+
+ /**
+ * Sets the font.
+ *
+ * @param f the font
+ * @see #getFont()
+ */
+ public void setFont(Font f)
+ {
+ Component.this.setFont(f);
+ }
+
+ /**
+ * Gets the font metrics for a font.
+ *
+ * @param f the font to look up
+ * @return its metrics
+ * @throws NullPointerException if f is null
+ * @see #getFont()
+ */
+ public FontMetrics getFontMetrics(Font f)
+ {
+ return Component.this.getFontMetrics(f);
+ }
+
+ /**
+ * Tests if the component is enabled.
+ *
+ * @return true if the component is enabled
+ * @see #setEnabled(boolean)
+ * @see #getAccessibleStateSet()
+ * @see AccessibleState#ENABLED
+ */
+ public boolean isEnabled()
+ {
+ return Component.this.isEnabled();
+ }
+
+ /**
+ * Set whether the component is enabled.
+ *
+ * @param b the new enabled status
+ * @see #isEnabled()
+ */
+ public void setEnabled(boolean b)
+ {
+ Component.this.setEnabled(b);
+ }
+
+ /**
+ * Test whether the component is visible (not necesarily showing).
+ *
+ * @return true if it is visible
+ * @see #setVisible(boolean)
+ * @see #getAccessibleStateSet()
+ * @see AccessibleState#VISIBLE
+ */
+ public boolean isVisible()
+ {
+ return Component.this.isVisible();
+ }
+
+ /**
+ * Sets the visibility of this component.
+ *
+ * @param b the desired visibility
+ * @see #isVisible()
+ */
+ public void setVisible(boolean b)
+ {
+ Component.this.setVisible(b);
+ }
+
+ /**
+ * Tests if the component is showing.
+ *
+ * @return true if this is showing
+ */
+ public boolean isShowing()
+ {
+ return Component.this.isShowing();
+ }
+
+ /**
+ * Tests if the point is contained in this component.
+ *
+ * @param p the point to check
+ * @return true if it is contained
+ * @throws NullPointerException if p is null
+ */
+ public boolean contains(Point p)
+ {
+ return Component.this.contains(p.x, p.y);
+ }
+
+ /**
+ * Returns the location of this object on the screen, or null if it is
+ * not showing.
+ *
+ * @return the location relative to screen coordinates, if showing
+ * @see #getBounds()
+ * @see #getLocation()
+ */
+ public Point getLocationOnScreen()
+ {
+ return Component.this.isShowing() ? Component.this.getLocationOnScreen()
+ : null;
+ }
+
+ /**
+ * Returns the location of this object relative to its parent's coordinate
+ * system, or null if it is not showing.
+ *
+ * @return the location
+ * @see #getBounds()
+ * @see #getLocationOnScreen()
+ */
+ public Point getLocation()
+ {
+ return Component.this.getLocation();
+ }
+
+ /**
+ * Sets the location of this relative to its parent's coordinate system.
+ *
+ * @param p the location
+ * @throws NullPointerException if p is null
+ * @see #getLocation()
+ */
+ public void setLocation(Point p)
+ {
+ Component.this.setLocation(p.x, p.y);
+ }
+
+ /**
+ * Gets the bounds of this component, or null if it is not on screen.
+ *
+ * @return the bounds
+ * @see #contains(Point)
+ * @see #setBounds(Rectangle)
+ */
+ public Rectangle getBounds()
+ {
+ return Component.this.getBounds();
+ }
+
+ /**
+ * Sets the bounds of this component.
+ *
+ * @param r the bounds
+ * @throws NullPointerException if r is null
+ * @see #getBounds()
+ */
+ public void setBounds(Rectangle r)
+ {
+ Component.this.setBounds(r.x, r.y, r.width, r.height);
+ }
+
+ /**
+ * Gets the size of this component, or null if it is not showing.
+ *
+ * @return the size
+ * @see #setSize(Dimension)
+ */
+ public Dimension getSize()
+ {
+ return Component.this.getSize();
+ }
+
+ /**
+ * Sets the size of this component.
+ *
+ * @param d the size
+ * @throws NullPointerException if d is null
+ * @see #getSize()
+ */
+ public void setSize(Dimension d)
+ {
+ Component.this.setSize(d.width, d.height);
+ }
+
+ /**
+ * Returns the Accessible child at a point relative to the coordinate
+ * system of this component, if one exists, or null. Since components
+ * have no children, subclasses must override this to get anything besides
+ * null.
+ *
+ * @param p the point to check
+ * @return the accessible child at that point
+ * @throws NullPointerException if p is null
+ */
+ public Accessible getAccessibleAt(Point p)
+ {
+ return null;
+ }
+
+ /**
+ * Tests whether this component can accept focus.
+ *
+ * @return true if this is focus traversable
+ * @see #getAccessibleStateSet ()
+ * @see AccessibleState#FOCUSABLE
+ * @see AccessibleState#FOCUSED
+ */
+ public boolean isFocusTraversable ()
+ {
+ return Component.this.isFocusTraversable ();
+ }
+
+ /**
+ * Requests focus for this component.
+ *
+ * @see #isFocusTraversable ()
+ */
+ public void requestFocus ()
+ {
+ Component.this.requestFocus ();
+ }
+
+ /**
+ * Adds a focus listener.
+ *
+ * @param l the listener to add
+ */
+ public void addFocusListener(FocusListener l)
+ {
+ Component.this.addFocusListener(l);
+ }
+
+ /**
+ * Removes a focus listener.
+ *
+ * @param l the listener to remove
+ */
+ public void removeFocusListener(FocusListener l)
+ {
+ Component.this.removeFocusListener(l);
+ }
+
+ /**
+ * Converts component changes into property changes.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.3
+ * @status updated to 1.4
+ */
+ protected class AccessibleAWTComponentHandler implements ComponentListener
+ {
+ /**
+ * Default constructor.
+ */
+ protected AccessibleAWTComponentHandler()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Convert a component hidden to a property change.
+ *
+ * @param e the event to convert
+ */
+ public void componentHidden(ComponentEvent e)
+ {
+ AccessibleAWTComponent.this.firePropertyChange
+ (ACCESSIBLE_STATE_PROPERTY, AccessibleState.VISIBLE, null);
+ }
+
+ /**
+ * Convert a component shown to a property change.
+ *
+ * @param e the event to convert
+ */
+ public void componentShown(ComponentEvent e)
+ {
+ AccessibleAWTComponent.this.firePropertyChange
+ (ACCESSIBLE_STATE_PROPERTY, null, AccessibleState.VISIBLE);
+ }
+
+ /**
+ * Moving a component does not affect properties.
+ *
+ * @param e ignored
+ */
+ public void componentMoved(ComponentEvent e)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Resizing a component does not affect properties.
+ *
+ * @param e ignored
+ */
+ public void componentResized(ComponentEvent e)
+ {
+ // Nothing to do here.
+ }
+ } // class AccessibleAWTComponentHandler
+
+ /**
+ * Converts focus changes into property changes.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.3
+ * @status updated to 1.4
+ */
+ protected class AccessibleAWTFocusHandler implements FocusListener
+ {
+ /**
+ * Default constructor.
+ */
+ protected AccessibleAWTFocusHandler()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Convert a focus gained to a property change.
+ *
+ * @param e the event to convert
+ */
+ public void focusGained(FocusEvent e)
+ {
+ AccessibleAWTComponent.this.firePropertyChange
+ (ACCESSIBLE_STATE_PROPERTY, null, AccessibleState.FOCUSED);
+ }
+
+ /**
+ * Convert a focus lost to a property change.
+ *
+ * @param e the event to convert
+ */
+ public void focusLost(FocusEvent e)
+ {
+ AccessibleAWTComponent.this.firePropertyChange
+ (ACCESSIBLE_STATE_PROPERTY, AccessibleState.FOCUSED, null);
+ }
+ } // class AccessibleAWTComponentHandler
+ } // class AccessibleAWTComponent
+
+ /**
+ * This class provides support for blitting offscreen surfaces to a
+ * component.
+ *
+ * @see BufferStrategy
+ *
+ * @since 1.4
+ */
+ protected class BltBufferStrategy extends BufferStrategy
+ {
+ /**
+ * The capabilities of the image buffer.
+ */
+ protected BufferCapabilities caps;
+
+ /**
+ * The back buffers used in this strategy.
+ */
+ protected VolatileImage[] backBuffers;
+
+ /**
+ * Whether or not the image buffer resources are allocated and
+ * ready to be drawn into.
+ */
+ protected boolean validatedContents;
+
+ /**
+ * The width of the back buffers.
+ */
+ protected int width;
+
+ /**
+ * The height of the back buffers.
+ */
+ protected int height;
+
+ /**
+ * The front buffer.
+ */
+ private VolatileImage frontBuffer;
+
+ /**
+ * Creates a blitting buffer strategy.
+ *
+ * @param numBuffers the number of buffers, including the front
+ * buffer
+ * @param caps the capabilities of this strategy
+ */
+ protected BltBufferStrategy(int numBuffers, BufferCapabilities caps)
+ {
+ this.caps = caps;
+ createBackBuffers(numBuffers - 1);
+ width = getWidth();
+ height = getHeight();
+ }
+
+ /**
+ * Initializes the backBuffers field with an array of numBuffers
+ * VolatileImages.
+ *
+ * @param numBuffers the number of backbuffers to create
+ */
+ protected void createBackBuffers(int numBuffers)
+ {
+ GraphicsConfiguration c =
+ GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice().getDefaultConfiguration();
+
+ backBuffers = new VolatileImage[numBuffers];
+
+ for (int i = 0; i < numBuffers; i++)
+ backBuffers[i] = c.createCompatibleVolatileImage(width, height);
+ }
+
+ /**
+ * Retrieves the capabilities of this buffer strategy.
+ *
+ * @return the capabilities of this buffer strategy
+ */
+ public BufferCapabilities getCapabilities()
+ {
+ return caps;
+ }
+
+ /**
+ * Retrieves a graphics object that can be used to draw into this
+ * strategy's image buffer.
+ *
+ * @return a graphics object
+ */
+ public Graphics getDrawGraphics()
+ {
+ // Return the backmost buffer's graphics.
+ return backBuffers[0].getGraphics();
+ }
+
+ /**
+ * Bring the contents of the back buffer to the front buffer.
+ */
+ public void show()
+ {
+ GraphicsConfiguration c =
+ GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice().getDefaultConfiguration();
+
+ // draw the front buffer.
+ getGraphics().drawImage(backBuffers[backBuffers.length - 1],
+ width, height, null);
+
+ BufferCapabilities.FlipContents f = getCapabilities().getFlipContents();
+
+ // blit the back buffers.
+ for (int i = backBuffers.length - 1; i > 0 ; i--)
+ backBuffers[i] = backBuffers[i - 1];
+
+ // create new backmost buffer.
+ if (f == BufferCapabilities.FlipContents.UNDEFINED)
+ backBuffers[0] = c.createCompatibleVolatileImage(width, height);
+
+ // create new backmost buffer and clear it to the background
+ // color.
+ if (f == BufferCapabilities.FlipContents.BACKGROUND)
+ {
+ backBuffers[0] = c.createCompatibleVolatileImage(width, height);
+ backBuffers[0].getGraphics().clearRect(0, 0, width, height);
+ }
+
+ // FIXME: set the backmost buffer to the prior contents of the
+ // front buffer. How do we retrieve the contents of the front
+ // buffer?
+ //
+ // if (f == BufferCapabilities.FlipContents.PRIOR)
+
+ // set the backmost buffer to a copy of the new front buffer.
+ if (f == BufferCapabilities.FlipContents.COPIED)
+ backBuffers[0] = backBuffers[backBuffers.length - 1];
+ }
+
+ /**
+ * Re-create the image buffer resources if they've been lost.
+ */
+ protected void revalidate()
+ {
+ GraphicsConfiguration c =
+ GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice().getDefaultConfiguration();
+
+ for (int i = 0; i < backBuffers.length; i++)
+ {
+ int result = backBuffers[i].validate(c);
+ if (result == VolatileImage.IMAGE_INCOMPATIBLE)
+ backBuffers[i] = c.createCompatibleVolatileImage(width, height);
+ }
+ validatedContents = true;
+ }
+
+ /**
+ * Returns whether or not the image buffer resources have been
+ * lost.
+ *
+ * @return true if the resources have been lost, false otherwise
+ */
+ public boolean contentsLost()
+ {
+ for (int i = 0; i < backBuffers.length; i++)
+ {
+ if (backBuffers[i].contentsLost())
+ {
+ validatedContents = false;
+ return true;
+ }
+ }
+ // we know that the buffer resources are valid now because we
+ // just checked them
+ validatedContents = true;
+ return false;
+ }
+
+ /**
+ * Returns whether or not the image buffer resources have been
+ * restored.
+ *
+ * @return true if the resources have been restored, false
+ * otherwise
+ */
+ public boolean contentsRestored()
+ {
+ GraphicsConfiguration c =
+ GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice().getDefaultConfiguration();
+
+ boolean imageRestored = false;
+
+ for (int i = 0; i < backBuffers.length; i++)
+ {
+ int result = backBuffers[i].validate(c);
+ if (result == VolatileImage.IMAGE_RESTORED)
+ imageRestored = true;
+ else if (result == VolatileImage.IMAGE_INCOMPATIBLE)
+ return false;
+ }
+ // we know that the buffer resources are valid now because we
+ // just checked them
+ validatedContents = true;
+ return imageRestored;
+ }
+ }
+
+ /**
+ * This class provides support for flipping component buffers. It
+ * can only be used on Canvases and Windows.
+ *
+ * @since 1.4
+ */
+ protected class FlipBufferStrategy extends BufferStrategy
+ {
+ /**
+ * The number of buffers.
+ */
+ protected int numBuffers;
+
+ /**
+ * The capabilities of this buffering strategy.
+ */
+ protected BufferCapabilities caps;
+
+ /**
+ * An Image reference to the drawing buffer.
+ */
+ protected Image drawBuffer;
+
+ /**
+ * A VolatileImage reference to the drawing buffer.
+ */
+ protected VolatileImage drawVBuffer;
+
+ /**
+ * Whether or not the image buffer resources are allocated and
+ * ready to be drawn into.
+ */
+ protected boolean validatedContents;
+
+ /**
+ * The width of the back buffer.
+ */
+ private int width;
+
+ /**
+ * The height of the back buffer.
+ */
+ private int height;
+
+ /**
+ * Creates a flipping buffer strategy. The only supported
+ * strategy for FlipBufferStrategy itself is a double-buffer page
+ * flipping strategy. It forms the basis for more complex derived
+ * strategies.
+ *
+ * @param numBuffers the number of buffers
+ * @param caps the capabilities of this buffering strategy
+ *
+ * @throws AWTException if the requested
+ * number-of-buffers/capabilities combination is not supported
+ */
+ protected FlipBufferStrategy(int numBuffers, BufferCapabilities caps)
+ throws AWTException
+ {
+ this.caps = caps;
+ width = getWidth();
+ height = getHeight();
+
+ if (numBuffers > 1)
+ createBuffers(numBuffers, caps);
+ else
+ {
+ drawVBuffer = peer.createVolatileImage(width, height);
+ drawBuffer = drawVBuffer;
+ }
+ }
+
+ /**
+ * Creates a multi-buffer flipping strategy. The number of
+ * buffers must be greater than one and the buffer capabilities
+ * must specify page flipping.
+ *
+ * @param numBuffers the number of flipping buffers; must be
+ * greater than one
+ * @param caps the buffering capabilities; caps.isPageFlipping()
+ * must return true
+ *
+ * @throws IllegalArgumentException if numBuffers is not greater
+ * than one or if the page flipping capability is not requested
+ *
+ * @throws AWTException if the requested flipping strategy is not
+ * supported
+ */
+ protected void createBuffers(int numBuffers, BufferCapabilities caps)
+ throws AWTException
+ {
+ if (numBuffers <= 1)
+ throw new IllegalArgumentException("FlipBufferStrategy.createBuffers:"
+ + " numBuffers must be greater than"
+ + " one.");
+
+ if (!caps.isPageFlipping())
+ throw new IllegalArgumentException("FlipBufferStrategy.createBuffers:"
+ + " flipping must be a specified"
+ + " capability.");
+
+ peer.createBuffers(numBuffers, caps);
+ }
+
+ /**
+ * Return a direct reference to the back buffer image.
+ *
+ * @return a direct reference to the back buffer image.
+ */
+ protected Image getBackBuffer()
+ {
+ return peer.getBackBuffer();
+ }
+
+ /**
+ * Perform a flip operation to transfer the contents of the back
+ * buffer to the front buffer.
+ */
+ protected void flip(BufferCapabilities.FlipContents flipAction)
+ {
+ peer.flip(flipAction);
+ }
+
+ /**
+ * Release the back buffer's resources.
+ */
+ protected void destroyBuffers()
+ {
+ peer.destroyBuffers();
+ }
+
+ /**
+ * Retrieves the capabilities of this buffer strategy.
+ *
+ * @return the capabilities of this buffer strategy
+ */
+ public BufferCapabilities getCapabilities()
+ {
+ return caps;
+ }
+
+ /**
+ * Retrieves a graphics object that can be used to draw into this
+ * strategy's image buffer.
+ *
+ * @return a graphics object
+ */
+ public Graphics getDrawGraphics()
+ {
+ return drawVBuffer.getGraphics();
+ }
+
+ /**
+ * Re-create the image buffer resources if they've been lost.
+ */
+ protected void revalidate()
+ {
+ GraphicsConfiguration c =
+ GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice().getDefaultConfiguration();
+
+ if (drawVBuffer.validate(c) == VolatileImage.IMAGE_INCOMPATIBLE)
+ drawVBuffer = peer.createVolatileImage(width, height);
+ validatedContents = true;
+ }
+
+ /**
+ * Returns whether or not the image buffer resources have been
+ * lost.
+ *
+ * @return true if the resources have been lost, false otherwise
+ */
+ public boolean contentsLost()
+ {
+ if (drawVBuffer.contentsLost())
+ {
+ validatedContents = false;
+ return true;
+ }
+ // we know that the buffer resources are valid now because we
+ // just checked them
+ validatedContents = true;
+ return false;
+ }
+
+ /**
+ * Returns whether or not the image buffer resources have been
+ * restored.
+ *
+ * @return true if the resources have been restored, false
+ * otherwise
+ */
+ public boolean contentsRestored()
+ {
+ GraphicsConfiguration c =
+ GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice().getDefaultConfiguration();
+
+ int result = drawVBuffer.validate(c);
+
+ boolean imageRestored = false;
+
+ if (result == VolatileImage.IMAGE_RESTORED)
+ imageRestored = true;
+ else if (result == VolatileImage.IMAGE_INCOMPATIBLE)
+ return false;
+
+ // we know that the buffer resources are valid now because we
+ // just checked them
+ validatedContents = true;
+ return imageRestored;
+ }
+
+ /**
+ * Bring the contents of the back buffer to the front buffer.
+ */
+ public void show()
+ {
+ flip(caps.getFlipContents());
+ }
+ }
+}
diff --git a/libjava/classpath/java/awt/ComponentOrientation.java b/libjava/classpath/java/awt/ComponentOrientation.java
new file mode 100644
index 000000000..69b14c755
--- /dev/null
+++ b/libjava/classpath/java/awt/ComponentOrientation.java
@@ -0,0 +1,215 @@
+/* ComponentOrientation.java -- describes a component's orientation
+ Copyright (C) 2000, 2001, 2002 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.io.Serializable;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * This class is used to differentiate different orientations for text layout.
+ * It controls whether text flows left-to-right or right-to-left, and whether
+ * lines are horizontal or vertical, as in this table:<br>
+ * <pre>
+ * LT RT TL TR
+ * A B C C B A A D G G D A
+ * D E F F E D B E H H E B
+ * G H I I H G C F I I F C
+ * </pre>
+ * <b>LT</b> languages are most common (left-to-right lines, top-to-bottom).
+ * This includes Western European languages, and optionally includes Japanese,
+ * Chinese, and Korean. <b>RT</b> languages (right-to-left lines,
+ * top-to-bottom) are mainly middle eastern, such as Hebrew and Arabic.
+ * <b>TR</b> languages flow top-to-bottom in a line, right-to-left, and are
+ * the basis of Japanese, Chinese, and Korean. Finally, <b>TL</b> languages
+ * flow top-to-bottom in a line, left-to-right, as in Mongolian.
+ *
+ * <p>This is a pretty poor excuse for a type-safe enum, since it is not
+ * guaranteed that orientation objects are unique (thanks to serialization),
+ * yet there is no equals() method. You would be wise to compare the output
+ * of isHorizontal() and isLeftToRight() rather than comparing objects with
+ * ==, especially since more constants may be added in the future.
+ *
+ * @author Bryce McKinlay (bryce@albatross.co.nz)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public final class ComponentOrientation implements Serializable
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -4113291392143563828L;
+
+ /** Constant for unknown orientation. */
+ private static final int UNKNOWN_ID = 1;
+
+ /** Constant for horizontal line orientation. */
+ private static final int HORIZONTAL_ID = 2;
+
+ /** Constant for left-to-right orientation. */
+ private static final int LEFT_TO_RIGHT_ID = 4;
+
+ /**
+ * Items run left to right, and lines flow top to bottom. Examples: English,
+ * French.
+ */
+ public static final ComponentOrientation LEFT_TO_RIGHT
+ = new ComponentOrientation(HORIZONTAL_ID | LEFT_TO_RIGHT_ID);
+
+ /**
+ * Items run right to left, and lines flow top to bottom. Examples: Arabic,
+ * Hebrew.
+ */
+ public static final ComponentOrientation RIGHT_TO_LEFT
+ = new ComponentOrientation(HORIZONTAL_ID);
+
+ /**
+ * The orientation is unknown for the locale. For backwards compatibility,
+ * this behaves like LEFT_TO_RIGHT in the instance methods.
+ */
+ public static final ComponentOrientation UNKNOWN
+ = new ComponentOrientation(UNKNOWN_ID | HORIZONTAL_ID | LEFT_TO_RIGHT_ID);
+
+ /**
+ * The orientation of this object; bitwise-or of unknown (1), horizontal (2),
+ * and left-to-right (4).
+ *
+ * @serial the orientation
+ */
+ private final int orientation;
+
+ /**
+ * Construct a given orientation.
+ *
+ * @param orientation the orientation
+ */
+ private ComponentOrientation(int orientation)
+ {
+ this.orientation = orientation;
+ }
+
+ /**
+ * Returns true if the lines are horizontal, in which case lines flow
+ * top-to-bottom. For example, English, Hebrew. Counterexamples: Japanese,
+ * Chinese, Korean, Mongolian.
+ *
+ * @return true if this orientation has horizontal lines
+ */
+ public boolean isHorizontal()
+ {
+ return (orientation & HORIZONTAL_ID) != 0;
+ }
+
+ /**
+ * If isHorizontal() returns true, then this determines whether items in
+ * the line flow left-to-right. If isHorizontal() returns false, items in
+ * a line flow top-to-bottom, and this determines if lines flow
+ * left-to-right.
+ *
+ * @return true if this orientation flows left-to-right
+ */
+ public boolean isLeftToRight()
+ {
+ return (orientation & LEFT_TO_RIGHT_ID) != 0;
+ }
+
+ /**
+ * Gets an orientation appropriate for the locale.
+ *
+ * @param locale the locale
+ * @return the orientation for that locale
+ * @throws NullPointerException if locale is null
+ */
+ public static ComponentOrientation getOrientation(Locale locale)
+ {
+ // Based on iterating over all languages defined in JDK 1.4, this behavior
+ // matches Sun's. However, it makes me wonder if any non-horizontal
+ // orientations even exist, as it sure contradicts their documentation.
+ String language = locale.getLanguage();
+ if ("ar".equals(language) || "fa".equals(language) || "iw".equals(language)
+ || "ur".equals(language))
+ return RIGHT_TO_LEFT;
+ return LEFT_TO_RIGHT;
+ }
+
+ /**
+ * Gets an orientation from a resource bundle. This tries the following:
+ *
+ * <ul>
+ * <li>Use the key "Orientation" to find an instance of ComponentOrientation
+ * in the bundle.</li>
+ * <li>Get the locale of the resource bundle, and get the orientation of
+ * that locale.</li>
+ * <li>Give up and get the orientation of the default locale.</li>
+ * </ul>
+ *
+ * @param bdl the bundle to use
+ * @return the orientation
+ * @throws NullPointerException if bdl is null
+ * @deprecated use {@link #getOrientation(Locale)} instead
+ */
+ public static ComponentOrientation getOrientation(ResourceBundle bdl)
+ {
+ ComponentOrientation r;
+ try
+ {
+ r = (ComponentOrientation) bdl.getObject("Orientation");
+ if (r != null)
+ return r;
+ }
+ catch (MissingResourceException ignored)
+ {
+ }
+ catch (ClassCastException ignored)
+ {
+ }
+ try
+ {
+ r = getOrientation(bdl.getLocale());
+ if (r != null)
+ return r;
+ }
+ catch (Exception ignored)
+ {
+ }
+ return getOrientation(Locale.getDefault());
+ }
+} // class ComponentOrientation
diff --git a/libjava/classpath/java/awt/Composite.java b/libjava/classpath/java/awt/Composite.java
new file mode 100644
index 000000000..ca3abe4d1
--- /dev/null
+++ b/libjava/classpath/java/awt/Composite.java
@@ -0,0 +1,73 @@
+/* Composite.java -- graphics formed from composite layers
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.image.ColorModel;
+
+/**
+ * This interface is for graphics which are formed as composites of others.
+ * It combines {@link Graphics2D} shapes according to defined rules to form
+ * the new image. Implementations of this interface must be immutable, because
+ * they are not cloned when a Graphics2D container is cloned.
+ *
+ * <p>Since this can expose pixels to untrusted code, there is a security
+ * check on custom objects, <code>readDisplayPixels</code>, to prevent leaking
+ * restricted information graphically.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see AlphaComposite
+ * @see CompositeContext
+ * @see Graphics2D#setComposite(Composite)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface Composite
+{
+ /**
+ * Create a context state for performing the compositing operation. Several
+ * contexts may exist for this object, in a multi-threaded environment.
+ *
+ * @param srcColorModel the color model of the source
+ * @param dstColorModel the color model of the destination
+ * @param hints hints for choosing between rendering alternatives
+ */
+ CompositeContext createContext(ColorModel srcColorModel,
+ ColorModel dstColorModel,
+ RenderingHints hints);
+} // interface Composite
diff --git a/libjava/classpath/java/awt/CompositeContext.java b/libjava/classpath/java/awt/CompositeContext.java
new file mode 100644
index 000000000..018a27071
--- /dev/null
+++ b/libjava/classpath/java/awt/CompositeContext.java
@@ -0,0 +1,71 @@
+/* Composite.java -- the context for compositing graphics layers
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+
+/**
+ * This interface provides an optimized environment for compositing graphics.
+ * Several such contexts may exist for a given <code>Composite</code> object.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Composite
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface CompositeContext
+{
+ /**
+ * Release resources allocated for the compositing.
+ */
+ void dispose();
+
+ /**
+ * Compose the two source images into the composite image. The destination
+ * can be the same as one of the two inputs, and the destination must be
+ * compatible with the ColorModel chosen in {@link Composite#createContext}.
+ *
+ * @param src the lower image source in compositing
+ * @param dstIn the upper image source in compositing
+ * @param dstOut the destination for the composite
+ * @see Composite
+ */
+ void compose(Raster src, Raster dstIn, WritableRaster dstOut);
+} // interface CompositeContext
diff --git a/libjava/classpath/java/awt/Container.java b/libjava/classpath/java/awt/Container.java
new file mode 100644
index 000000000..7e596f10a
--- /dev/null
+++ b/libjava/classpath/java/awt/Container.java
@@ -0,0 +1,2370 @@
+/* Container.java -- parent container class in AWT
+ Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.awt.event.ContainerEvent;
+import java.awt.event.ContainerListener;
+import java.awt.event.HierarchyEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.peer.ComponentPeer;
+import java.awt.peer.ContainerPeer;
+import java.awt.peer.LightweightPeer;
+import java.beans.PropertyChangeListener;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.EventListener;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.accessibility.Accessible;
+
+/**
+ * A generic window toolkit object that acts as a container for other objects.
+ * Components are tracked in a list, and new elements are at the end of the
+ * list or bottom of the stacking order.
+ *
+ * @author original author unknown
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ *
+ * @since 1.0
+ *
+ * @status still missing 1.4 support, some generics from 1.5
+ */
+public class Container extends Component
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 4613797578919906343L;
+
+ /* Serialized fields from the serialization spec. */
+ int ncomponents;
+ Component[] component;
+ LayoutManager layoutMgr;
+
+ /**
+ * @since 1.4
+ */
+ boolean focusCycleRoot;
+
+ /**
+ * Indicates if this container provides a focus traversal policy.
+ *
+ * @since 1.5
+ */
+ private boolean focusTraversalPolicyProvider;
+
+ int containerSerializedDataVersion;
+
+ /* Anything else is non-serializable, and should be declared "transient". */
+ transient ContainerListener containerListener;
+
+ /** The focus traversal policy that determines how focus is
+ transferred between this Container and its children. */
+ private FocusTraversalPolicy focusTraversalPolicy;
+
+ /**
+ * The focus traversal keys, if not inherited from the parent or default
+ * keyboard manager. These sets will contain only AWTKeyStrokes that
+ * represent press and release events to use as focus control.
+ *
+ * @see #getFocusTraversalKeys(int)
+ * @see #setFocusTraversalKeys(int, Set)
+ * @since 1.4
+ */
+ transient Set[] focusTraversalKeys;
+
+ /**
+ * Default constructor for subclasses.
+ */
+ public Container()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the number of components in this container.
+ *
+ * @return The number of components in this container.
+ */
+ public int getComponentCount()
+ {
+ return countComponents ();
+ }
+
+ /**
+ * Returns the number of components in this container.
+ *
+ * @return The number of components in this container.
+ *
+ * @deprecated use {@link #getComponentCount()} instead
+ */
+ public int countComponents()
+ {
+ return ncomponents;
+ }
+
+ /**
+ * Returns the component at the specified index.
+ *
+ * @param n The index of the component to retrieve.
+ *
+ * @return The requested component.
+ *
+ * @throws ArrayIndexOutOfBoundsException If the specified index is invalid
+ */
+ public Component getComponent(int n)
+ {
+ synchronized (getTreeLock ())
+ {
+ if (n < 0 || n >= ncomponents)
+ throw new ArrayIndexOutOfBoundsException("no such component");
+
+ return component[n];
+ }
+ }
+
+ /**
+ * Returns an array of the components in this container.
+ *
+ * @return The components in this container.
+ */
+ public Component[] getComponents()
+ {
+ synchronized (getTreeLock ())
+ {
+ Component[] result = new Component[ncomponents];
+
+ if (ncomponents > 0)
+ System.arraycopy(component, 0, result, 0, ncomponents);
+
+ return result;
+ }
+ }
+
+ /**
+ * Returns the insets for this container, which is the space used for
+ * borders, the margin, etc.
+ *
+ * @return The insets for this container.
+ */
+ public Insets getInsets()
+ {
+ return insets ();
+ }
+
+ /**
+ * Returns the insets for this container, which is the space used for
+ * borders, the margin, etc.
+ *
+ * @return The insets for this container.
+ * @deprecated use {@link #getInsets()} instead
+ */
+ public Insets insets()
+ {
+ Insets i;
+ if (peer == null || peer instanceof LightweightPeer)
+ i = new Insets (0, 0, 0, 0);
+ else
+ i = ((ContainerPeer) peer).getInsets ();
+ return i;
+ }
+
+ /**
+ * Adds the specified component to this container at the end of the
+ * component list.
+ *
+ * @param comp The component to add to the container.
+ *
+ * @return The same component that was added.
+ */
+ public Component add(Component comp)
+ {
+ addImpl(comp, null, -1);
+ return comp;
+ }
+
+ /**
+ * Adds the specified component to the container at the end of the
+ * component list. This method should not be used. Instead, use
+ * <code>add(Component, Object)</code>.
+ *
+ * @param name The name of the component to be added.
+ * @param comp The component to be added.
+ *
+ * @return The same component that was added.
+ *
+ * @see #add(Component,Object)
+ */
+ public Component add(String name, Component comp)
+ {
+ addImpl(comp, name, -1);
+ return comp;
+ }
+
+ /**
+ * Adds the specified component to this container at the specified index
+ * in the component list.
+ *
+ * @param comp The component to be added.
+ * @param index The index in the component list to insert this child
+ * at, or -1 to add at the end of the list.
+ *
+ * @return The same component that was added.
+ *
+ * @throws ArrayIndexOutOfBoundsException If the specified index is invalid.
+ */
+ public Component add(Component comp, int index)
+ {
+ addImpl(comp, null, index);
+ return comp;
+ }
+
+ /**
+ * Adds the specified component to this container at the end of the
+ * component list. The layout manager will use the specified constraints
+ * when laying out this component.
+ *
+ * @param comp The component to be added to this container.
+ * @param constraints The layout constraints for this component.
+ */
+ public void add(Component comp, Object constraints)
+ {
+ addImpl(comp, constraints, -1);
+ }
+
+ /**
+ * Adds the specified component to this container at the specified index
+ * in the component list. The layout manager will use the specified
+ * constraints when layout out this component.
+ *
+ * @param comp The component to be added.
+ * @param constraints The layout constraints for this component.
+ * @param index The index in the component list to insert this child
+ * at, or -1 to add at the end of the list.
+ *
+ * @throws ArrayIndexOutOfBoundsException If the specified index is invalid.
+ */
+ public void add(Component comp, Object constraints, int index)
+ {
+ addImpl(comp, constraints, index);
+ }
+
+ /**
+ * This method is called by all the <code>add()</code> methods to perform
+ * the actual adding of the component. Subclasses who wish to perform
+ * their own processing when a component is added should override this
+ * method. Any subclass doing this must call the superclass version of
+ * this method in order to ensure proper functioning of the container.
+ *
+ * @param comp The component to be added.
+ * @param constraints The layout constraints for this component, or
+ * <code>null</code> if there are no constraints.
+ * @param index The index in the component list to insert this child
+ * at, or -1 to add at the end of the list.
+ *
+ * @throws ArrayIndexOutOfBoundsException If the specified index is invalid.
+ */
+ protected void addImpl(Component comp, Object constraints, int index)
+ {
+ synchronized (getTreeLock ())
+ {
+ if (index > ncomponents
+ || (index < 0 && index != -1)
+ || comp instanceof Window
+ || (comp instanceof Container
+ && ((Container) comp).isAncestorOf(this)))
+ throw new IllegalArgumentException();
+
+ // Reparent component, and make sure component is instantiated if
+ // we are.
+ if (comp.parent != null)
+ comp.parent.remove(comp);
+
+ if (component == null)
+ component = new Component[4]; // FIXME, better initial size?
+
+ // This isn't the most efficient implementation. We could do less
+ // copying when growing the array. It probably doesn't matter.
+ if (ncomponents >= component.length)
+ {
+ int nl = component.length * 2;
+ Component[] c = new Component[nl];
+ System.arraycopy(component, 0, c, 0, ncomponents);
+ component = c;
+ }
+
+ if (index == -1)
+ component[ncomponents++] = comp;
+ else
+ {
+ System.arraycopy(component, index, component, index + 1,
+ ncomponents - index);
+ component[index] = comp;
+ ++ncomponents;
+ }
+
+ // Give the new component a parent.
+ comp.parent = this;
+
+ // Update the counter for Hierarchy(Bounds)Listeners.
+ int childHierarchyListeners = comp.numHierarchyListeners;
+ if (childHierarchyListeners > 0)
+ updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
+ childHierarchyListeners);
+ int childHierarchyBoundsListeners = comp.numHierarchyBoundsListeners;
+ if (childHierarchyBoundsListeners > 0)
+ updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
+ childHierarchyListeners);
+
+ // Invalidate the layout of this container.
+ if (valid)
+ invalidate();
+
+ // Create the peer _after_ the component has been added, so that
+ // the peer gets to know about the component hierarchy.
+ if (peer != null)
+ {
+ // Notify the component that it has a new parent.
+ comp.addNotify();
+ }
+
+ // Notify the layout manager.
+ if (layoutMgr != null)
+ {
+ // If we have a LayoutManager2 the constraints are "real",
+ // otherwise they are the "name" of the Component to add.
+ if (layoutMgr instanceof LayoutManager2)
+ {
+ LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
+ lm2.addLayoutComponent(comp, constraints);
+ }
+ else if (constraints instanceof String)
+ layoutMgr.addLayoutComponent((String) constraints, comp);
+ else
+ layoutMgr.addLayoutComponent("", comp);
+ }
+
+ // We previously only sent an event when this container is showing.
+ // Also, the event was posted to the event queue. A Mauve test shows
+ // that this event is not delivered using the event queue and it is
+ // also sent when the container is not showing.
+ if (containerListener != null
+ || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0)
+ {
+ ContainerEvent ce = new ContainerEvent(this,
+ ContainerEvent.COMPONENT_ADDED,
+ comp);
+ dispatchEvent(ce);
+ }
+
+ // Notify hierarchy listeners.
+ comp.fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, comp,
+ this, HierarchyEvent.PARENT_CHANGED);
+ }
+ }
+
+ /**
+ * Removes the component at the specified index from this container.
+ *
+ * @param index The index of the component to remove.
+ */
+ public void remove(int index)
+ {
+ synchronized (getTreeLock ())
+ {
+ if (index < 0 || index >= ncomponents)
+ throw new ArrayIndexOutOfBoundsException();
+
+ Component r = component[index];
+ if (peer != null)
+ r.removeNotify();
+
+ if (layoutMgr != null)
+ layoutMgr.removeLayoutComponent(r);
+
+ // Update the counter for Hierarchy(Bounds)Listeners.
+ int childHierarchyListeners = r.numHierarchyListeners;
+ if (childHierarchyListeners > 0)
+ updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
+ -childHierarchyListeners);
+ int childHierarchyBoundsListeners = r.numHierarchyBoundsListeners;
+ if (childHierarchyBoundsListeners > 0)
+ updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
+ -childHierarchyListeners);
+
+ r.parent = null;
+
+ System.arraycopy(component, index + 1, component, index,
+ ncomponents - index - 1);
+ component[--ncomponents] = null;
+
+ if (valid)
+ invalidate();
+
+ if (containerListener != null
+ || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0)
+ {
+ // Post event to notify of removing the component.
+ ContainerEvent ce = new ContainerEvent(this,
+ ContainerEvent.COMPONENT_REMOVED,
+ r);
+ dispatchEvent(ce);
+ }
+
+ // Notify hierarchy listeners.
+ r.fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, r,
+ this, HierarchyEvent.PARENT_CHANGED);
+ }
+ }
+
+ /**
+ * Removes the specified component from this container.
+ *
+ * @param comp The component to remove from this container.
+ */
+ public void remove(Component comp)
+ {
+ synchronized (getTreeLock ())
+ {
+ for (int i = 0; i < ncomponents; ++i)
+ {
+ if (component[i] == comp)
+ {
+ remove(i);
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes all components from this container.
+ */
+ public void removeAll()
+ {
+ synchronized (getTreeLock ())
+ {
+ // In order to allow the same bad tricks to be used as in RI
+ // this code has to stay exactly that way: In a real-life app
+ // a Container subclass implemented its own vector for
+ // subcomponents, supplied additional addXYZ() methods
+ // and overrode remove(int) and removeAll (the latter calling
+ // super.removeAll() ).
+ // By doing it this way, user code cannot prevent the correct
+ // removal of components.
+ while (ncomponents > 0)
+ {
+ ncomponents--;
+ Component r = component[ncomponents];
+ component[ncomponents] = null;
+
+ if (peer != null)
+ r.removeNotify();
+
+ if (layoutMgr != null)
+ layoutMgr.removeLayoutComponent(r);
+
+ r.parent = null;
+
+ // Send ContainerEvent if necessary.
+ if (containerListener != null
+ || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0)
+ {
+ // Post event to notify of removing the component.
+ ContainerEvent ce
+ = new ContainerEvent(this,
+ ContainerEvent.COMPONENT_REMOVED,
+ r);
+ dispatchEvent(ce);
+ }
+
+ // Update the counter for Hierarchy(Bounds)Listeners.
+ int childHierarchyListeners = r.numHierarchyListeners;
+ if (childHierarchyListeners > 0)
+ updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
+ -childHierarchyListeners);
+ int childHierarchyBoundsListeners = r.numHierarchyBoundsListeners;
+ if (childHierarchyBoundsListeners > 0)
+ updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
+ -childHierarchyListeners);
+
+
+ // Send HierarchyEvent if necessary.
+ fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, r, this,
+ HierarchyEvent.PARENT_CHANGED);
+
+ }
+
+ if (valid)
+ invalidate();
+ }
+ }
+
+ /**
+ * Returns the current layout manager for this container.
+ *
+ * @return The layout manager for this container.
+ */
+ public LayoutManager getLayout()
+ {
+ return layoutMgr;
+ }
+
+ /**
+ * Sets the layout manager for this container to the specified layout
+ * manager.
+ *
+ * @param mgr The new layout manager for this container.
+ */
+ public void setLayout(LayoutManager mgr)
+ {
+ layoutMgr = mgr;
+ if (valid)
+ invalidate();
+ }
+
+ /**
+ * Layout the components in this container.
+ */
+ public void doLayout()
+ {
+ layout ();
+ }
+
+ /**
+ * Layout the components in this container.
+ *
+ * @deprecated use {@link #doLayout()} instead
+ */
+ public void layout()
+ {
+ if (layoutMgr != null)
+ layoutMgr.layoutContainer (this);
+ }
+
+ /**
+ * Invalidates this container to indicate that it (and all parent
+ * containers) need to be laid out.
+ */
+ public void invalidate()
+ {
+ super.invalidate();
+ if (layoutMgr != null && layoutMgr instanceof LayoutManager2)
+ {
+ LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
+ lm2.invalidateLayout(this);
+ }
+ }
+
+ /**
+ * Re-lays out the components in this container.
+ */
+ public void validate()
+ {
+ ComponentPeer p = peer;
+ if (! valid && p != null)
+ {
+ ContainerPeer cPeer = null;
+ if (p instanceof ContainerPeer)
+ cPeer = (ContainerPeer) peer;
+ synchronized (getTreeLock ())
+ {
+ if (cPeer != null)
+ cPeer.beginValidate();
+ validateTree();
+ valid = true;
+ if (cPeer != null)
+ cPeer.endValidate();
+ }
+ }
+ }
+
+ /**
+ * Recursively invalidates the container tree.
+ */
+ private final void invalidateTree()
+ {
+ synchronized (getTreeLock())
+ {
+ for (int i = 0; i < ncomponents; i++)
+ {
+ Component comp = component[i];
+ if (comp instanceof Container)
+ ((Container) comp).invalidateTree();
+ else if (comp.valid)
+ comp.invalidate();
+ }
+ if (valid)
+ invalidate();
+ }
+ }
+
+ /**
+ * Recursively validates the container tree, recomputing any invalid
+ * layouts.
+ */
+ protected void validateTree()
+ {
+ if (!valid)
+ {
+ ContainerPeer cPeer = null;
+ if (peer instanceof ContainerPeer)
+ {
+ cPeer = (ContainerPeer) peer;
+ cPeer.beginLayout();
+ }
+
+ doLayout ();
+ for (int i = 0; i < ncomponents; ++i)
+ {
+ Component comp = component[i];
+
+ if (comp instanceof Container && ! (comp instanceof Window)
+ && ! comp.valid)
+ {
+ ((Container) comp).validateTree();
+ }
+ else
+ {
+ comp.validate();
+ }
+ }
+
+ if (cPeer != null)
+ {
+ cPeer = (ContainerPeer) peer;
+ cPeer.endLayout();
+ }
+ }
+
+ /* children will call invalidate() when they are layed out. It
+ is therefore important that valid is not set to true
+ until after the children have been layed out. */
+ valid = true;
+
+ }
+
+ public void setFont(Font f)
+ {
+ Font oldFont = getFont();
+ super.setFont(f);
+ Font newFont = getFont();
+ if (newFont != oldFont && (oldFont == null || ! oldFont.equals(newFont)))
+ {
+ invalidateTree();
+ }
+ }
+
+ /**
+ * Returns the preferred size of this container.
+ *
+ * @return The preferred size of this container.
+ */
+ public Dimension getPreferredSize()
+ {
+ return preferredSize ();
+ }
+
+ /**
+ * Returns the preferred size of this container.
+ *
+ * @return The preferred size of this container.
+ *
+ * @deprecated use {@link #getPreferredSize()} instead
+ */
+ public Dimension preferredSize()
+ {
+ Dimension size = prefSize;
+ // Try to return cached value if possible.
+ if (size == null || !(prefSizeSet || valid))
+ {
+ // Need to lock here.
+ synchronized (getTreeLock())
+ {
+ LayoutManager l = layoutMgr;
+ if (l != null)
+ prefSize = l.preferredLayoutSize(this);
+ else
+ prefSize = super.preferredSizeImpl();
+ size = prefSize;
+ }
+ }
+ if (size != null)
+ return new Dimension(size);
+ else
+ return size;
+ }
+
+ /**
+ * Returns the minimum size of this container.
+ *
+ * @return The minimum size of this container.
+ */
+ public Dimension getMinimumSize()
+ {
+ return minimumSize ();
+ }
+
+ /**
+ * Returns the minimum size of this container.
+ *
+ * @return The minimum size of this container.
+ *
+ * @deprecated use {@link #getMinimumSize()} instead
+ */
+ public Dimension minimumSize()
+ {
+ Dimension size = minSize;
+ // Try to return cached value if possible.
+ if (size == null || !(minSizeSet || valid))
+ {
+ // Need to lock here.
+ synchronized (getTreeLock())
+ {
+ LayoutManager l = layoutMgr;
+ if (l != null)
+ minSize = l.minimumLayoutSize(this);
+ else
+ minSize = super.minimumSizeImpl();
+ size = minSize;
+ }
+ }
+ if (size != null)
+ return new Dimension(size);
+ else
+ return size;
+ }
+
+ /**
+ * Returns the maximum size of this container.
+ *
+ * @return The maximum size of this container.
+ */
+ public Dimension getMaximumSize()
+ {
+ Dimension size = maxSize;
+ // Try to return cached value if possible.
+ if (size == null || !(maxSizeSet || valid))
+ {
+ // Need to lock here.
+ synchronized (getTreeLock())
+ {
+ LayoutManager l = layoutMgr;
+ if (l instanceof LayoutManager2)
+ maxSize = ((LayoutManager2) l).maximumLayoutSize(this);
+ else {
+ maxSize = super.maximumSizeImpl();
+ }
+ size = maxSize;
+ }
+ }
+ if (size != null)
+ return new Dimension(size);
+ else
+ return size;
+ }
+
+ /**
+ * Returns the preferred alignment along the X axis. This is a value
+ * between 0 and 1 where 0 represents alignment flush left and
+ * 1 means alignment flush right, and 0.5 means centered.
+ *
+ * @return The preferred alignment along the X axis.
+ */
+ public float getAlignmentX()
+ {
+ LayoutManager layout = getLayout();
+ float alignmentX = 0.0F;
+ if (layout != null && layout instanceof LayoutManager2)
+ {
+ synchronized (getTreeLock())
+ {
+ LayoutManager2 lm2 = (LayoutManager2) layout;
+ alignmentX = lm2.getLayoutAlignmentX(this);
+ }
+ }
+ else
+ alignmentX = super.getAlignmentX();
+ return alignmentX;
+ }
+
+ /**
+ * Returns the preferred alignment along the Y axis. This is a value
+ * between 0 and 1 where 0 represents alignment flush top and
+ * 1 means alignment flush bottom, and 0.5 means centered.
+ *
+ * @return The preferred alignment along the Y axis.
+ */
+ public float getAlignmentY()
+ {
+ LayoutManager layout = getLayout();
+ float alignmentY = 0.0F;
+ if (layout != null && layout instanceof LayoutManager2)
+ {
+ synchronized (getTreeLock())
+ {
+ LayoutManager2 lm2 = (LayoutManager2) layout;
+ alignmentY = lm2.getLayoutAlignmentY(this);
+ }
+ }
+ else
+ alignmentY = super.getAlignmentY();
+ return alignmentY;
+ }
+
+ /**
+ * Paints this container. The implementation of this method in this
+ * class forwards to any lightweight components in this container. If
+ * this method is subclassed, this method should still be invoked as
+ * a superclass method so that lightweight components are properly
+ * drawn.
+ *
+ * @param g - The graphics context for this paint job.
+ */
+ public void paint(Graphics g)
+ {
+ if (isShowing())
+ {
+ visitChildren(g, GfxPaintVisitor.INSTANCE, true);
+ }
+ }
+
+ /**
+ * Updates this container. The implementation of this method in this
+ * class forwards to any lightweight components in this container. If
+ * this method is subclassed, this method should still be invoked as
+ * a superclass method so that lightweight components are properly
+ * drawn.
+ *
+ * @param g The graphics context for this update.
+ *
+ * @specnote The specification suggests that this method forwards the
+ * update() call to all its lightweight children. Tests show
+ * that this is not done either in the JDK. The exact behaviour
+ * seems to be that the background is cleared in heavyweight
+ * Containers, and all other containers
+ * directly call paint(), causing the (lightweight) children to
+ * be painted.
+ */
+ public void update(Graphics g)
+ {
+ // It seems that the JDK clears the background of containers like Panel
+ // and Window (within this method) but not of 'plain' Containers or
+ // JComponents. This could
+ // lead to the assumption that it only clears heavyweight containers.
+ // However that is not quite true. In a test with a custom Container
+ // that overrides isLightweight() to return false, the background is
+ // also not cleared. So we do a check on !(peer instanceof LightweightPeer)
+ // instead.
+ if (isShowing())
+ {
+ ComponentPeer p = peer;
+ if (! (p instanceof LightweightPeer))
+ {
+ g.clearRect(0, 0, getWidth(), getHeight());
+ }
+ paint(g);
+ }
+ }
+
+ /**
+ * Prints this container. The implementation of this method in this
+ * class forwards to any lightweight components in this container. If
+ * this method is subclassed, this method should still be invoked as
+ * a superclass method so that lightweight components are properly
+ * drawn.
+ *
+ * @param g The graphics context for this print job.
+ */
+ public void print(Graphics g)
+ {
+ super.print(g);
+ visitChildren(g, GfxPrintVisitor.INSTANCE, true);
+ }
+
+ /**
+ * Paints all of the components in this container.
+ *
+ * @param g The graphics context for this paint job.
+ */
+ public void paintComponents(Graphics g)
+ {
+ if (isShowing())
+ visitChildren(g, GfxPaintAllVisitor.INSTANCE, false);
+ }
+
+ /**
+ * Prints all of the components in this container.
+ *
+ * @param g The graphics context for this print job.
+ */
+ public void printComponents(Graphics g)
+ {
+ super.paint(g);
+ visitChildren(g, GfxPrintAllVisitor.INSTANCE, true);
+ }
+
+ /**
+ * Adds the specified container listener to this object's list of
+ * container listeners.
+ *
+ * @param listener The listener to add.
+ */
+ public synchronized void addContainerListener(ContainerListener listener)
+ {
+ if (listener != null)
+ {
+ containerListener = AWTEventMulticaster.add(containerListener,
+ listener);
+ newEventsOnly = true;
+ }
+ }
+
+ /**
+ * Removes the specified container listener from this object's list of
+ * container listeners.
+ *
+ * @param listener The listener to remove.
+ */
+ public synchronized void removeContainerListener(ContainerListener listener)
+ {
+ containerListener = AWTEventMulticaster.remove(containerListener, listener);
+ }
+
+ /**
+ * @since 1.4
+ */
+ public synchronized ContainerListener[] getContainerListeners()
+ {
+ return (ContainerListener[])
+ AWTEventMulticaster.getListeners(containerListener,
+ ContainerListener.class);
+ }
+
+ /**
+ * Returns all registered {@link EventListener}s of the given
+ * <code>listenerType</code>.
+ *
+ * @param listenerType the class of listeners to filter (<code>null</code>
+ * not permitted).
+ *
+ * @return An array of registered listeners.
+ *
+ * @throws ClassCastException if <code>listenerType</code> does not implement
+ * the {@link EventListener} interface.
+ * @throws NullPointerException if <code>listenerType</code> is
+ * <code>null</code>.
+ *
+ * @see #getContainerListeners()
+ *
+ * @since 1.3
+ */
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
+ {
+ if (listenerType == ContainerListener.class)
+ return (T[]) getContainerListeners();
+ return super.getListeners(listenerType);
+ }
+
+ /**
+ * Processes the specified event. This method calls
+ * <code>processContainerEvent()</code> if this method is a
+ * <code>ContainerEvent</code>, otherwise it calls the superclass
+ * method.
+ *
+ * @param e The event to be processed.
+ */
+ protected void processEvent(AWTEvent e)
+ {
+ if (e instanceof ContainerEvent)
+ processContainerEvent((ContainerEvent) e);
+ else
+ super.processEvent(e);
+ }
+
+ /**
+ * Called when a container event occurs if container events are enabled.
+ * This method calls any registered listeners.
+ *
+ * @param e The event that occurred.
+ */
+ protected void processContainerEvent(ContainerEvent e)
+ {
+ if (containerListener == null)
+ return;
+ switch (e.id)
+ {
+ case ContainerEvent.COMPONENT_ADDED:
+ containerListener.componentAdded(e);
+ break;
+
+ case ContainerEvent.COMPONENT_REMOVED:
+ containerListener.componentRemoved(e);
+ break;
+ }
+ }
+
+ /**
+ * AWT 1.0 event processor.
+ *
+ * @param e The event that occurred.
+ *
+ * @deprecated use {@link #dispatchEvent(AWTEvent)} instead
+ */
+ public void deliverEvent(Event e)
+ {
+ if (!handleEvent (e))
+ {
+ synchronized (getTreeLock ())
+ {
+ Component parent = getParent ();
+
+ if (parent != null)
+ parent.deliverEvent (e);
+ }
+ }
+ }
+
+ /**
+ * Returns the component located at the specified point. This is done
+ * by checking whether or not a child component claims to contain this
+ * point. The first child component that does is returned. If no
+ * child component claims the point, the container itself is returned,
+ * unless the point does not exist within this container, in which
+ * case <code>null</code> is returned.
+ *
+ * When components overlap, the first component is returned. The component
+ * that is closest to (x, y), containing that location, is returned.
+ * Heavyweight components take precedence of lightweight components.
+ *
+ * This function does not ignore invisible components. If there is an invisible
+ * component at (x,y), it will be returned.
+ *
+ * @param x The X coordinate of the point.
+ * @param y The Y coordinate of the point.
+ *
+ * @return The component containing the specified point, or
+ * <code>null</code> if there is no such point.
+ */
+ public Component getComponentAt(int x, int y)
+ {
+ return locate (x, y);
+ }
+
+ /**
+ * Returns the mouse pointer position relative to this Container's
+ * top-left corner. If allowChildren is false, the mouse pointer
+ * must be directly over this container. If allowChildren is true,
+ * the mouse pointer may be over this container or any of its
+ * descendents.
+ *
+ * @param allowChildren true to allow descendents, false if pointer
+ * must be directly over Container.
+ *
+ * @return relative mouse pointer position
+ *
+ * @throws HeadlessException if in a headless environment
+ */
+ public Point getMousePosition(boolean allowChildren) throws HeadlessException
+ {
+ return super.getMousePositionHelper(allowChildren);
+ }
+
+ boolean mouseOverComponent(Component component, boolean allowChildren)
+ {
+ if (allowChildren)
+ return isAncestorOf(component);
+ else
+ return component == this;
+ }
+
+ /**
+ * Returns the component located at the specified point. This is done
+ * by checking whether or not a child component claims to contain this
+ * point. The first child component that does is returned. If no
+ * child component claims the point, the container itself is returned,
+ * unless the point does not exist within this container, in which
+ * case <code>null</code> is returned.
+ *
+ * When components overlap, the first component is returned. The component
+ * that is closest to (x, y), containing that location, is returned.
+ * Heavyweight components take precedence of lightweight components.
+ *
+ * This function does not ignore invisible components. If there is an invisible
+ * component at (x,y), it will be returned.
+ *
+ * @param x The x position of the point to return the component at.
+ * @param y The y position of the point to return the component at.
+ *
+ * @return The component containing the specified point, or <code>null</code>
+ * if there is no such point.
+ *
+ * @deprecated use {@link #getComponentAt(int, int)} instead
+ */
+ public Component locate(int x, int y)
+ {
+ synchronized (getTreeLock ())
+ {
+ if (!contains (x, y))
+ return null;
+
+ // First find the component closest to (x,y) that is a heavyweight.
+ for (int i = 0; i < ncomponents; ++i)
+ {
+ Component comp = component[i];
+ int x2 = x - comp.x;
+ int y2 = y - comp.y;
+ if (comp.contains (x2, y2) && !comp.isLightweight())
+ return comp;
+ }
+
+ // if a heavyweight component is not found, look for a lightweight
+ // closest to (x,y).
+ for (int i = 0; i < ncomponents; ++i)
+ {
+ Component comp = component[i];
+ int x2 = x - comp.x;
+ int y2 = y - comp.y;
+ if (comp.contains (x2, y2) && comp.isLightweight())
+ return comp;
+ }
+
+ return this;
+ }
+ }
+
+ /**
+ * Returns the component located at the specified point. This is done
+ * by checking whether or not a child component claims to contain this
+ * point. The first child component that does is returned. If no
+ * child component claims the point, the container itself is returned,
+ * unless the point does not exist within this container, in which
+ * case <code>null</code> is returned.
+ *
+ * The top-most child component is returned in the case where components overlap.
+ * This is determined by finding the component closest to (x,y) and contains
+ * that location. Heavyweight components take precedence of lightweight components.
+ *
+ * This function does not ignore invisible components. If there is an invisible
+ * component at (x,y), it will be returned.
+ *
+ * @param p The point to return the component at.
+ * @return The component containing the specified point, or <code>null</code>
+ * if there is no such point.
+ */
+ public Component getComponentAt(Point p)
+ {
+ return getComponentAt (p.x, p.y);
+ }
+
+ /**
+ * Locates the visible child component that contains the specified position.
+ * The top-most child component is returned in the case where there is overlap
+ * in the components. If the containing child component is a Container,
+ * this method will continue searching for the deepest nested child
+ * component. Components which are not visible are ignored during the search.
+ *
+ * findComponentAt differs from getComponentAt, because it recursively
+ * searches a Container's children.
+ *
+ * @param x - x coordinate
+ * @param y - y coordinate
+ * @return null if the component does not contain the position.
+ * If there is no child component at the requested point and the point is
+ * within the bounds of the container the container itself is returned.
+ */
+ public Component findComponentAt(int x, int y)
+ {
+ synchronized (getTreeLock ())
+ {
+ if (! contains(x, y))
+ return null;
+
+ for (int i = 0; i < ncomponents; ++i)
+ {
+ // Ignore invisible children...
+ if (!component[i].isVisible())
+ continue;
+
+ int x2 = x - component[i].x;
+ int y2 = y - component[i].y;
+ // We don't do the contains() check right away because
+ // findComponentAt would redundantly do it first thing.
+ if (component[i] instanceof Container)
+ {
+ Container k = (Container) component[i];
+ Component r = k.findComponentAt(x2, y2);
+ if (r != null)
+ return r;
+ }
+ else if (component[i].contains(x2, y2))
+ return component[i];
+ }
+
+ return this;
+ }
+ }
+
+ /**
+ * Locates the visible child component that contains the specified position.
+ * The top-most child component is returned in the case where there is overlap
+ * in the components. If the containing child component is a Container,
+ * this method will continue searching for the deepest nested child
+ * component. Components which are not visible are ignored during the search.
+ *
+ * findComponentAt differs from getComponentAt, because it recursively
+ * searches a Container's children.
+ *
+ * @param p - the component's location
+ * @return null if the component does not contain the position.
+ * If there is no child component at the requested point and the point is
+ * within the bounds of the container the container itself is returned.
+ */
+ public Component findComponentAt(Point p)
+ {
+ return findComponentAt(p.x, p.y);
+ }
+
+ /**
+ * Called when this container is added to another container to inform it
+ * to create its peer. Peers for any child components will also be
+ * created.
+ */
+ public void addNotify()
+ {
+ synchronized (getTreeLock())
+ {
+ super.addNotify();
+ addNotifyContainerChildren();
+ }
+ }
+
+ /**
+ * Called when this container is removed from its parent container to
+ * inform it to destroy its peer. This causes the peers of all child
+ * component to be destroyed as well.
+ */
+ public void removeNotify()
+ {
+ synchronized (getTreeLock ())
+ {
+ int ncomps = ncomponents;
+ Component[] comps = component;
+ for (int i = ncomps - 1; i >= 0; --i)
+ {
+ Component comp = comps[i];
+ if (comp != null)
+ comp.removeNotify();
+ }
+ super.removeNotify();
+ }
+ }
+
+ /**
+ * Tests whether or not the specified component is contained within
+ * this components subtree.
+ *
+ * @param comp The component to test.
+ *
+ * @return <code>true</code> if this container is an ancestor of the
+ * specified component, <code>false</code> otherwise.
+ */
+ public boolean isAncestorOf(Component comp)
+ {
+ synchronized (getTreeLock ())
+ {
+ while (true)
+ {
+ if (comp == null)
+ return false;
+ comp = comp.getParent();
+ if (comp == this)
+ return true;
+ }
+ }
+ }
+
+ /**
+ * Returns a string representing the state of this container for
+ * debugging purposes.
+ *
+ * @return A string representing the state of this container.
+ */
+ protected String paramString()
+ {
+ if (layoutMgr == null)
+ return super.paramString();
+
+ CPStringBuilder sb = new CPStringBuilder();
+ sb.append(super.paramString());
+ sb.append(",layout=");
+ sb.append(layoutMgr.getClass().getName());
+ return sb.toString();
+ }
+
+ /**
+ * Writes a listing of this container to the specified stream starting
+ * at the specified indentation point.
+ *
+ * @param out The <code>PrintStream</code> to write to.
+ * @param indent The indentation point.
+ */
+ public void list(PrintStream out, int indent)
+ {
+ synchronized (getTreeLock ())
+ {
+ super.list(out, indent);
+ for (int i = 0; i < ncomponents; ++i)
+ component[i].list(out, indent + 2);
+ }
+ }
+
+ /**
+ * Writes a listing of this container to the specified stream starting
+ * at the specified indentation point.
+ *
+ * @param out The <code>PrintWriter</code> to write to.
+ * @param indent The indentation point.
+ */
+ public void list(PrintWriter out, int indent)
+ {
+ synchronized (getTreeLock ())
+ {
+ super.list(out, indent);
+ for (int i = 0; i < ncomponents; ++i)
+ component[i].list(out, indent + 2);
+ }
+ }
+
+ /**
+ * Sets the focus traversal keys for a given traversal operation for this
+ * Container.
+ *
+ * @exception IllegalArgumentException If id is not one of
+ * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
+ * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
+ * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS,
+ * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS,
+ * or if keystrokes contains null, or if any Object in keystrokes is not an
+ * AWTKeyStroke, or if any keystroke represents a KEY_TYPED event, or if any
+ * keystroke already maps to another focus traversal operation for this
+ * Container.
+ *
+ * @since 1.4
+ */
+ public void setFocusTraversalKeys(int id,
+ Set<? extends AWTKeyStroke> keystrokes)
+ {
+ if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
+ throw new IllegalArgumentException ();
+
+ if (keystrokes == null)
+ {
+ Container parent = getParent ();
+
+ while (parent != null)
+ {
+ if (parent.areFocusTraversalKeysSet (id))
+ {
+ keystrokes = parent.getFocusTraversalKeys (id);
+ break;
+ }
+ parent = parent.getParent ();
+ }
+
+ if (keystrokes == null)
+ keystrokes = KeyboardFocusManager.getCurrentKeyboardFocusManager ().
+ getDefaultFocusTraversalKeys (id);
+ }
+
+ Set sa;
+ Set sb;
+ Set sc;
+ String name;
+ switch (id)
+ {
+ case KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS:
+ sa = getFocusTraversalKeys
+ (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
+ sb = getFocusTraversalKeys
+ (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
+ sc = getFocusTraversalKeys
+ (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
+ name = "forwardFocusTraversalKeys";
+ break;
+ case KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS:
+ sa = getFocusTraversalKeys
+ (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
+ sb = getFocusTraversalKeys
+ (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
+ sc = getFocusTraversalKeys
+ (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
+ name = "backwardFocusTraversalKeys";
+ break;
+ case KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS:
+ sa = getFocusTraversalKeys
+ (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
+ sb = getFocusTraversalKeys
+ (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
+ sc = getFocusTraversalKeys
+ (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
+ name = "upCycleFocusTraversalKeys";
+ break;
+ case KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS:
+ sa = getFocusTraversalKeys
+ (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
+ sb = getFocusTraversalKeys
+ (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
+ sc = getFocusTraversalKeys
+ (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
+ name = "downCycleFocusTraversalKeys";
+ break;
+ default:
+ throw new IllegalArgumentException ();
+ }
+
+ int i = keystrokes.size ();
+ Iterator iter = keystrokes.iterator ();
+
+ while (--i >= 0)
+ {
+ Object o = iter.next ();
+ if (!(o instanceof AWTKeyStroke)
+ || sa.contains (o) || sb.contains (o) || sc.contains (o)
+ || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED)
+ throw new IllegalArgumentException ();
+ }
+
+ if (focusTraversalKeys == null)
+ focusTraversalKeys = new Set[4];
+
+ keystrokes =
+ Collections.unmodifiableSet(new HashSet<AWTKeyStroke>(keystrokes));
+ firePropertyChange (name, focusTraversalKeys[id], keystrokes);
+
+ focusTraversalKeys[id] = keystrokes;
+ }
+
+ /**
+ * Returns the Set of focus traversal keys for a given traversal operation for
+ * this Container.
+ *
+ * @exception IllegalArgumentException If id is not one of
+ * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
+ * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
+ * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS,
+ * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS.
+ *
+ * @since 1.4
+ */
+ public Set<AWTKeyStroke> getFocusTraversalKeys (int id)
+ {
+ if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
+ throw new IllegalArgumentException ();
+
+ Set s = null;
+
+ if (focusTraversalKeys != null)
+ s = focusTraversalKeys[id];
+
+ if (s == null && parent != null)
+ s = parent.getFocusTraversalKeys (id);
+
+ return s == null ? (KeyboardFocusManager.getCurrentKeyboardFocusManager()
+ .getDefaultFocusTraversalKeys(id)) : s;
+ }
+
+ /**
+ * Returns whether the Set of focus traversal keys for the given focus
+ * traversal operation has been explicitly defined for this Container.
+ * If this method returns false, this Container is inheriting the Set from
+ * an ancestor, or from the current KeyboardFocusManager.
+ *
+ * @exception IllegalArgumentException If id is not one of
+ * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
+ * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
+ * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS,
+ * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS.
+ *
+ * @since 1.4
+ */
+ public boolean areFocusTraversalKeysSet (int id)
+ {
+ if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
+ throw new IllegalArgumentException ();
+
+ return focusTraversalKeys != null && focusTraversalKeys[id] != null;
+ }
+
+ /**
+ * Check whether the given Container is the focus cycle root of this
+ * Container's focus traversal cycle. If this Container is a focus
+ * cycle root itself, then it will be in two different focus cycles
+ * -- it's own, and that of its ancestor focus cycle root's. In
+ * that case, if <code>c</code> is either of those containers, this
+ * method will return true.
+ *
+ * @param c the candidate Container
+ *
+ * @return true if c is the focus cycle root of the focus traversal
+ * cycle to which this Container belongs, false otherwise
+ *
+ * @since 1.4
+ */
+ public boolean isFocusCycleRoot (Container c)
+ {
+ if (this == c
+ && isFocusCycleRoot ())
+ return true;
+
+ Container ancestor = getFocusCycleRootAncestor ();
+
+ if (c == ancestor)
+ return true;
+
+ return false;
+ }
+
+ /**
+ * If this Container is a focus cycle root, set the focus traversal
+ * policy that determines the focus traversal order for its
+ * children. If non-null, this policy will be inherited by all
+ * inferior focus cycle roots. If <code>policy</code> is null, this
+ * Container will inherit its policy from the closest ancestor focus
+ * cycle root that's had its policy set.
+ *
+ * @param policy the new focus traversal policy for this Container or null
+ *
+ * @since 1.4
+ */
+ public void setFocusTraversalPolicy (FocusTraversalPolicy policy)
+ {
+ focusTraversalPolicy = policy;
+ }
+
+ /**
+ * Return the focus traversal policy that determines the focus
+ * traversal order for this Container's children. This method
+ * returns null if this Container is not a focus cycle root. If the
+ * focus traversal policy has not been set explicitly, then this
+ * method will return an ancestor focus cycle root's policy instead.
+ *
+ * @return this Container's focus traversal policy or null
+ *
+ * @since 1.4
+ */
+ public FocusTraversalPolicy getFocusTraversalPolicy ()
+ {
+ if (!isFocusCycleRoot ())
+ return null;
+
+ if (focusTraversalPolicy == null)
+ {
+ Container ancestor = getFocusCycleRootAncestor ();
+
+ if (ancestor != this && ancestor != null)
+ return ancestor.getFocusTraversalPolicy ();
+ else
+ {
+ KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
+
+ return manager.getDefaultFocusTraversalPolicy ();
+ }
+ }
+ else
+ return focusTraversalPolicy;
+ }
+
+ /**
+ * Check whether this Container's focus traversal policy has been
+ * explicitly set. If it has not, then this Container will inherit
+ * its focus traversal policy from one of its ancestor focus cycle
+ * roots.
+ *
+ * @return true if focus traversal policy is set, false otherwise
+ */
+ public boolean isFocusTraversalPolicySet ()
+ {
+ return focusTraversalPolicy == null;
+ }
+
+ /**
+ * Set whether or not this Container is the root of a focus
+ * traversal cycle. This Container's focus traversal policy
+ * determines the order of focus traversal. Some policies prevent
+ * the focus from being transferred between two traversal cycles
+ * until an up or down traversal operation is performed. In that
+ * case, normal traversal (not up or down) is limited to this
+ * Container and all of this Container's descendents that are not
+ * descendents of inferior focus cycle roots. In the default case
+ * however, ContainerOrderFocusTraversalPolicy is in effect, and it
+ * supports implicit down-cycle traversal operations.
+ *
+ * @param focusCycleRoot true if this is a focus cycle root, false otherwise
+ *
+ * @since 1.4
+ */
+ public void setFocusCycleRoot (boolean focusCycleRoot)
+ {
+ this.focusCycleRoot = focusCycleRoot;
+ }
+
+ /**
+ * Set to <code>true</code> if this container provides a focus traversal
+ * policy, <code>false</code> when the root container's focus
+ * traversal policy should be used.
+ *
+ * @return <code>true</code> if this container provides a focus traversal
+ * policy, <code>false</code> when the root container's focus
+ * traversal policy should be used
+ *
+ * @see #setFocusTraversalPolicyProvider(boolean)
+ *
+ * @since 1.5
+ */
+ public final boolean isFocusTraversalPolicyProvider()
+ {
+ return focusTraversalPolicyProvider;
+ }
+
+ /**
+ * Set to <code>true</code> if this container provides a focus traversal
+ * policy, <code>false</code> when the root container's focus
+ * traversal policy should be used.
+ *
+ * @param b <code>true</code> if this container provides a focus traversal
+ * policy, <code>false</code> when the root container's focus
+ * traversal policy should be used
+ *
+ * @see #isFocusTraversalPolicyProvider()
+ *
+ * @since 1.5
+ */
+ public final void setFocusTraversalPolicyProvider(boolean b)
+ {
+ focusTraversalPolicyProvider = b;
+ }
+
+ /**
+ * Check whether this Container is a focus cycle root.
+ *
+ * @return true if this is a focus cycle root, false otherwise
+ *
+ * @since 1.4
+ */
+ public boolean isFocusCycleRoot ()
+ {
+ return focusCycleRoot;
+ }
+
+ /**
+ * Transfer focus down one focus traversal cycle. If this Container
+ * is a focus cycle root, then its default component becomes the
+ * focus owner, and this Container becomes the current focus cycle
+ * root. No traversal will occur if this Container is not a focus
+ * cycle root.
+ *
+ * @since 1.4
+ */
+ public void transferFocusDownCycle ()
+ {
+ if (isFocusCycleRoot())
+ {
+ KeyboardFocusManager fm =
+ KeyboardFocusManager.getCurrentKeyboardFocusManager();
+ fm.setGlobalCurrentFocusCycleRoot(this);
+ FocusTraversalPolicy policy = getFocusTraversalPolicy();
+ Component defaultComponent = policy.getDefaultComponent(this);
+ if (defaultComponent != null)
+ defaultComponent.requestFocus();
+ }
+ }
+
+ /**
+ * Sets the ComponentOrientation property of this container and all components
+ * contained within it.
+ *
+ * @exception NullPointerException If orientation is null
+ *
+ * @since 1.4
+ */
+ public void applyComponentOrientation (ComponentOrientation orientation)
+ {
+ if (orientation == null)
+ throw new NullPointerException();
+
+ setComponentOrientation(orientation);
+ for (int i = 0; i < ncomponents; i++)
+ {
+ if (component[i] instanceof Container)
+ ((Container) component[i]).applyComponentOrientation(orientation);
+ else
+ component[i].setComponentOrientation(orientation);
+ }
+ }
+
+ public void addPropertyChangeListener (PropertyChangeListener listener)
+ {
+ // TODO: Why is this overridden?
+ super.addPropertyChangeListener(listener);
+ }
+
+ public void addPropertyChangeListener (String propertyName,
+ PropertyChangeListener listener)
+ {
+ // TODO: Why is this overridden?
+ super.addPropertyChangeListener(propertyName, listener);
+ }
+
+
+ /**
+ * Sets the Z ordering for the component <code>comp</code> to
+ * <code>index</code>. Components with lower Z order paint above components
+ * with higher Z order.
+ *
+ * @param comp the component for which to change the Z ordering
+ * @param index the index to set
+ *
+ * @throws NullPointerException if <code>comp == null</code>
+ * @throws IllegalArgumentException if comp is an ancestor of this container
+ * @throws IllegalArgumentException if <code>index</code> is not in
+ * <code>[0, getComponentCount()]</code> for moving between
+ * containers or <code>[0, getComponentCount() - 1]</code> for moving
+ * inside this container
+ * @throws IllegalArgumentException if <code>comp == this</code>
+ * @throws IllegalArgumentException if <code>comp</code> is a
+ * <code>Window</code>
+ *
+ * @see #getComponentZOrder(Component)
+ *
+ * @since 1.5
+ */
+ public final void setComponentZOrder(Component comp, int index)
+ {
+ if (comp == null)
+ throw new NullPointerException("comp must not be null");
+ if (comp instanceof Container && ((Container) comp).isAncestorOf(this))
+ throw new IllegalArgumentException("comp must not be an ancestor of "
+ + "this");
+ if (comp instanceof Window)
+ throw new IllegalArgumentException("comp must not be a Window");
+
+ if (comp == this)
+ throw new IllegalArgumentException("cannot add component to itself");
+
+ synchronized (getTreeLock())
+ {
+ // FIXME: Implement reparenting.
+ if ( comp.getParent() != this)
+ throw new AssertionError("Reparenting is not implemented yet");
+ else
+ {
+ // Find current component index.
+ int currentIndex = getComponentZOrder(comp);
+ if (currentIndex < index)
+ {
+ System.arraycopy(component, currentIndex + 1, component,
+ currentIndex, index - currentIndex);
+ }
+ else
+ {
+ System.arraycopy(component, index, component, index + 1,
+ currentIndex - index);
+ }
+ component[index] = comp;
+ }
+ }
+ }
+
+ /**
+ * Returns the Z ordering index of <code>comp</code>. If <code>comp</code>
+ * is not a child component of this Container, this returns <code>-1</code>.
+ *
+ * @param comp the component for which to query the Z ordering
+ *
+ * @return the Z ordering index of <code>comp</code> or <code>-1</code> if
+ * <code>comp</code> is not a child of this Container
+ *
+ * @see #setComponentZOrder(Component, int)
+ *
+ * @since 1.5
+ */
+ public final int getComponentZOrder(Component comp)
+ {
+ synchronized (getTreeLock())
+ {
+ int index = -1;
+ if (component != null)
+ {
+ for (int i = 0; i < ncomponents; i++)
+ {
+ if (component[i] == comp)
+ {
+ index = i;
+ break;
+ }
+ }
+ }
+ return index;
+ }
+ }
+
+ // Hidden helper methods.
+
+ /**
+ * Perform a graphics operation on the children of this container.
+ * For each applicable child, the visitChild() method will be called
+ * to perform the graphics operation.
+ *
+ * @param gfx The graphics object that will be used to derive new
+ * graphics objects for the children.
+ *
+ * @param visitor Object encapsulating the graphics operation that
+ * should be performed.
+ *
+ * @param lightweightOnly If true, only lightweight components will
+ * be visited.
+ */
+ private void visitChildren(Graphics gfx, GfxVisitor visitor,
+ boolean lightweightOnly)
+ {
+ synchronized (getTreeLock())
+ {
+ for (int i = ncomponents - 1; i >= 0; --i)
+ {
+ Component comp = component[i];
+ boolean applicable = comp.isVisible()
+ && (comp.isLightweight() || ! lightweightOnly);
+
+ if (applicable)
+ visitChild(gfx, visitor, comp);
+ }
+ }
+ }
+
+ /**
+ * Perform a graphics operation on a child. A translated and clipped
+ * graphics object will be created, and the visit() method of the
+ * visitor will be called to perform the operation.
+ *
+ * @param gfx The graphics object that will be used to derive new
+ * graphics objects for the child.
+ *
+ * @param visitor Object encapsulating the graphics operation that
+ * should be performed.
+ *
+ * @param comp The child component that should be visited.
+ */
+ private void visitChild(Graphics gfx, GfxVisitor visitor,
+ Component comp)
+ {
+ Rectangle bounds = comp.getBounds();
+
+ if(!gfx.hitClip(bounds.x,bounds.y, bounds.width, bounds.height))
+ return;
+ Graphics g2 = gfx.create(bounds.x, bounds.y, bounds.width,
+ bounds.height);
+ try
+ {
+ g2.setFont(comp.getFont());
+ visitor.visit(comp, g2);
+ }
+ finally
+ {
+ g2.dispose();
+ }
+ }
+
+ /**
+ * Overridden to dispatch events to lightweight descendents.
+ *
+ * @param e the event to dispatch.
+ */
+ void dispatchEventImpl(AWTEvent e)
+ {
+ LightweightDispatcher dispatcher = LightweightDispatcher.getInstance();
+ if (! isLightweight() && dispatcher.dispatchEvent(e))
+ {
+ // Some lightweight descendent got this event dispatched. Consume
+ // it and let the peer handle it.
+ e.consume();
+ ComponentPeer p = peer;
+ if (p != null)
+ p.handleEvent(e);
+ }
+ else
+ {
+ super.dispatchEventImpl(e);
+ }
+ }
+
+ /**
+ * This is called by the lightweight dispatcher to avoid recursivly
+ * calling into the lightweight dispatcher.
+ *
+ * @param e the event to dispatch
+ *
+ * @see LightweightDispatcher#redispatch(MouseEvent, Component, int)
+ */
+ void dispatchNoLightweight(AWTEvent e)
+ {
+ super.dispatchEventImpl(e);
+ }
+
+ /**
+ * Tests if this container has an interest in the given event id.
+ *
+ * @param eventId The event id to check.
+ *
+ * @return <code>true</code> if a listener for the event id exists or
+ * if the eventMask is set for the event id.
+ *
+ * @see java.awt.Component#eventTypeEnabled(int)
+ */
+ boolean eventTypeEnabled(int eventId)
+ {
+ if(eventId <= ContainerEvent.CONTAINER_LAST
+ && eventId >= ContainerEvent.CONTAINER_FIRST)
+ return containerListener != null
+ || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0;
+ else
+ return super.eventTypeEnabled(eventId);
+ }
+
+ // This is used to implement Component.transferFocus.
+ Component findNextFocusComponent(Component child)
+ {
+ synchronized (getTreeLock ())
+ {
+ int start, end;
+ if (child != null)
+ {
+ for (start = 0; start < ncomponents; ++start)
+ {
+ if (component[start] == child)
+ break;
+ }
+ end = start;
+ // This special case lets us be sure to terminate.
+ if (end == 0)
+ end = ncomponents;
+ ++start;
+ }
+ else
+ {
+ start = 0;
+ end = ncomponents;
+ }
+
+ for (int j = start; j != end; ++j)
+ {
+ if (j >= ncomponents)
+ {
+ // The JCL says that we should wrap here. However, that
+ // seems wrong. To me it seems that focus order should be
+ // global within in given window. So instead if we reach
+ // the end we try to look in our parent, if we have one.
+ if (parent != null)
+ return parent.findNextFocusComponent(this);
+ j -= ncomponents;
+ }
+ if (component[j] instanceof Container)
+ {
+ Component c = component[j];
+ c = c.findNextFocusComponent(null);
+ if (c != null)
+ return c;
+ }
+ else if (component[j].isFocusTraversable())
+ return component[j];
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * Fires hierarchy events to the children of this container and this
+ * container itself. This overrides {@link Component#fireHierarchyEvent}
+ * in order to forward this event to all children.
+ */
+ void fireHierarchyEvent(int id, Component changed, Container parent,
+ long flags)
+ {
+ // Only propagate event if there is actually a listener waiting for it.
+ if ((id == HierarchyEvent.HIERARCHY_CHANGED && numHierarchyListeners > 0)
+ || ((id == HierarchyEvent.ANCESTOR_MOVED
+ || id == HierarchyEvent.ANCESTOR_RESIZED)
+ && numHierarchyBoundsListeners > 0))
+ {
+ for (int i = 0; i < ncomponents; i++)
+ component[i].fireHierarchyEvent(id, changed, parent, flags);
+ super.fireHierarchyEvent(id, changed, parent, flags);
+ }
+ }
+
+ /**
+ * Adjusts the number of hierarchy listeners of this container and all of
+ * its parents. This is called by the add/remove listener methods and
+ * structure changing methods in Container.
+ *
+ * @param type the type, either {@link AWTEvent#HIERARCHY_BOUNDS_EVENT_MASK}
+ * or {@link AWTEvent#HIERARCHY_EVENT_MASK}
+ * @param delta the number of listeners added or removed
+ */
+ void updateHierarchyListenerCount(long type, int delta)
+ {
+ if (type == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK)
+ numHierarchyBoundsListeners += delta;
+ else if (type == AWTEvent.HIERARCHY_EVENT_MASK)
+ numHierarchyListeners += delta;
+ else
+ assert false : "Should not reach here";
+
+ if (parent != null)
+ parent.updateHierarchyListenerCount(type, delta);
+ }
+
+ /**
+ * Notifies interested listeners about resizing or moving the container.
+ * This performs the super behaviour (sending component events) and
+ * additionally notifies any hierarchy bounds listeners on child components.
+ *
+ * @param resized true if the component has been resized, false otherwise
+ * @param moved true if the component has been moved, false otherwise
+ */
+ void notifyReshape(boolean resized, boolean moved)
+ {
+ // Notify component listeners.
+ super.notifyReshape(resized, moved);
+
+ if (ncomponents > 0)
+ {
+ // Notify hierarchy bounds listeners.
+ if (resized)
+ {
+ for (int i = 0; i < getComponentCount(); i++)
+ {
+ Component child = getComponent(i);
+ child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_RESIZED,
+ this, parent, 0);
+ }
+ }
+ if (moved)
+ {
+ for (int i = 0; i < getComponentCount(); i++)
+ {
+ Component child = getComponent(i);
+ child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_MOVED,
+ this, parent, 0);
+ }
+ }
+ }
+ }
+
+ private void addNotifyContainerChildren()
+ {
+ synchronized (getTreeLock ())
+ {
+ for (int i = ncomponents; --i >= 0; )
+ {
+ component[i].addNotify();
+ }
+ }
+ }
+
+ /**
+ * Deserialize this Container:
+ * <ol>
+ * <li>Read from the stream the default serializable fields.</li>
+ * <li>Read a list of serializable ContainerListeners as optional
+ * data. If the list is null, no listeners will be registered.</li>
+ * <li>Read this Container's FocusTraversalPolicy as optional data.
+ * If this is null, then this Container will use a
+ * DefaultFocusTraversalPolicy.</li>
+ * </ol>
+ *
+ * @param s the stream to read from
+ * @throws ClassNotFoundException if deserialization fails
+ * @throws IOException if the stream fails
+ */
+ private void readObject (ObjectInputStream s)
+ throws ClassNotFoundException, IOException
+ {
+ s.defaultReadObject ();
+ String key = (String) s.readObject ();
+ while (key != null)
+ {
+ Object object = s.readObject ();
+ if ("containerL".equals (key))
+ addContainerListener((ContainerListener) object);
+ // FIXME: under what key is the focus traversal policy stored?
+ else if ("focusTraversalPolicy".equals (key))
+ setFocusTraversalPolicy ((FocusTraversalPolicy) object);
+
+ key = (String) s.readObject();
+ }
+ }
+
+ /**
+ * Serialize this Container:
+ * <ol>
+ * <li>Write to the stream the default serializable fields.</li>
+ * <li>Write the list of serializable ContainerListeners as optional
+ * data.</li>
+ * <li>Write this Container's FocusTraversalPolicy as optional data.</li>
+ * </ol>
+ *
+ * @param s the stream to write to
+ * @throws IOException if the stream fails
+ */
+ private void writeObject (ObjectOutputStream s) throws IOException
+ {
+ s.defaultWriteObject ();
+ AWTEventMulticaster.save (s, "containerL", containerListener);
+ if (focusTraversalPolicy instanceof Serializable)
+ s.writeObject (focusTraversalPolicy);
+ else
+ s.writeObject (null);
+ }
+
+ // Nested classes.
+
+ /* The following classes are used in concert with the
+ visitChildren() method to implement all the graphics operations
+ that requires traversal of the containment hierarchy. */
+
+ abstract static class GfxVisitor
+ {
+ public abstract void visit(Component c, Graphics gfx);
+ }
+
+ static class GfxPaintVisitor extends GfxVisitor
+ {
+ public static final GfxVisitor INSTANCE = new GfxPaintVisitor();
+
+ public void visit(Component c, Graphics gfx)
+ {
+ c.paint(gfx);
+ }
+ }
+
+ static class GfxPrintVisitor extends GfxVisitor
+ {
+ public static final GfxVisitor INSTANCE = new GfxPrintVisitor();
+
+ public void visit(Component c, Graphics gfx)
+ {
+ c.print(gfx);
+ }
+ }
+
+ static class GfxPaintAllVisitor extends GfxVisitor
+ {
+ public static final GfxVisitor INSTANCE = new GfxPaintAllVisitor();
+
+ public void visit(Component c, Graphics gfx)
+ {
+ c.paintAll(gfx);
+ }
+ }
+
+ static class GfxPrintAllVisitor extends GfxVisitor
+ {
+ public static final GfxVisitor INSTANCE = new GfxPrintAllVisitor();
+
+ public void visit(Component c, Graphics gfx)
+ {
+ c.printAll(gfx);
+ }
+ }
+
+ /**
+ * This class provides accessibility support for subclasses of container.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ *
+ * @since 1.3
+ */
+ protected class AccessibleAWTContainer extends AccessibleAWTComponent
+ {
+ /**
+ * Compatible with JDK 1.4+.
+ */
+ private static final long serialVersionUID = 5081320404842566097L;
+
+ /**
+ * The handler to fire PropertyChange when children are added or removed.
+ *
+ * @serial the handler for property changes
+ */
+ protected ContainerListener accessibleContainerHandler
+ = new AccessibleContainerHandler();
+
+ /**
+ * The default constructor.
+ */
+ protected AccessibleAWTContainer()
+ {
+ Container.this.addContainerListener(accessibleContainerHandler);
+ }
+
+ /**
+ * Return the number of accessible children of the containing accessible
+ * object (at most the total number of its children).
+ *
+ * @return the number of accessible children
+ */
+ public int getAccessibleChildrenCount()
+ {
+ synchronized (getTreeLock ())
+ {
+ int count = 0;
+ int i = component == null ? 0 : component.length;
+ while (--i >= 0)
+ if (component[i] instanceof Accessible)
+ count++;
+ return count;
+ }
+ }
+
+ /**
+ * Return the nth accessible child of the containing accessible object.
+ *
+ * @param i the child to grab, zero-based
+ * @return the accessible child, or null
+ */
+ public Accessible getAccessibleChild(int i)
+ {
+ synchronized (getTreeLock ())
+ {
+ if (component == null)
+ return null;
+ int index = -1;
+ while (i >= 0 && ++index < component.length)
+ if (component[index] instanceof Accessible)
+ i--;
+ if (i < 0)
+ return (Accessible) component[index];
+ return null;
+ }
+ }
+
+ /**
+ * Return the accessible child located at point (in the parent's
+ * coordinates), if one exists.
+ *
+ * @param p the point to look at
+ *
+ * @return an accessible object at that point, or null
+ *
+ * @throws NullPointerException if p is null
+ */
+ public Accessible getAccessibleAt(Point p)
+ {
+ Component c = getComponentAt(p.x, p.y);
+ return c != Container.this && c instanceof Accessible ? (Accessible) c
+ : null;
+ }
+
+ /**
+ * This class fires a <code>PropertyChange</code> listener, if registered,
+ * when children are added or removed from the enclosing accessible object.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ *
+ * @since 1.3
+ */
+ protected class AccessibleContainerHandler implements ContainerListener
+ {
+ /**
+ * Default constructor.
+ */
+ protected AccessibleContainerHandler()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Fired when a component is added; forwards to the PropertyChange
+ * listener.
+ *
+ * @param e the container event for adding
+ */
+ public void componentAdded(ContainerEvent e)
+ {
+ AccessibleAWTContainer.this.firePropertyChange
+ (ACCESSIBLE_CHILD_PROPERTY, null, e.getChild());
+ }
+
+ /**
+ * Fired when a component is removed; forwards to the PropertyChange
+ * listener.
+ *
+ * @param e the container event for removing
+ */
+ public void componentRemoved(ContainerEvent e)
+ {
+ AccessibleAWTContainer.this.firePropertyChange
+ (ACCESSIBLE_CHILD_PROPERTY, e.getChild(), null);
+ }
+ } // class AccessibleContainerHandler
+ } // class AccessibleAWTContainer
+} // class Container
diff --git a/libjava/classpath/java/awt/ContainerOrderFocusTraversalPolicy.java b/libjava/classpath/java/awt/ContainerOrderFocusTraversalPolicy.java
new file mode 100644
index 000000000..3fa437db7
--- /dev/null
+++ b/libjava/classpath/java/awt/ContainerOrderFocusTraversalPolicy.java
@@ -0,0 +1,482 @@
+/* ContainerOrderFocusTraversalPolicy.java --
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.io.Serializable;
+
+/**
+ * ContainerOrderFocusTraversalPolicy defines a focus traversal order
+ * based on the order in which Components were packed in a Container.
+ * This policy performs a pre-order traversal of the Component
+ * hierarchy starting from a given focus cycle root. Portions of the
+ * hierarchy that are not visible and displayable are skipped.
+ *
+ * By default, this policy transfers focus down-cycle implicitly.
+ * That is, if a forward traversal is requested on a focus cycle root
+ * and the focus cycle root has focusable children, the focus will
+ * automatically be transfered down to the lower focus cycle.
+ *
+ * The default implementation of accept accepts only Components that
+ * are visible, displayable, enabled and focusable. Derived classes
+ * can override these acceptance criteria by overriding accept.
+ *
+ * @author Michael Koch
+ * @author Thomas Fitzsimmons (fitzsim@redhat.com)
+ * @since 1.4
+ */
+public class ContainerOrderFocusTraversalPolicy extends FocusTraversalPolicy
+ implements Serializable
+{
+ /**
+ * Compatible to JDK 1.4+
+ */
+ static final long serialVersionUID = 486933713763926351L;
+
+ /**
+ * True if implicit down cycling is enabled.
+ */
+ private boolean implicitDownCycleTraversal = true;
+
+ /**
+ * Creates the <code>ContainerOrderFocusTraversalPolicy</code> object.
+ */
+ public ContainerOrderFocusTraversalPolicy ()
+ {
+ // Nothing to do here
+ }
+
+ /**
+ * Returns the Component that should receive the focus after current.
+ * root must be a focus cycle root of current.
+ *
+ * @param root a focus cycle root of current
+ * @param current a (possibly indirect) child of root, or root itself
+ *
+ * @return the next Component in the focus traversal order for root,
+ * or null if no acceptable Component exists.
+ *
+ * @exception IllegalArgumentException If root is not a focus cycle
+ * root of current, or if either root or current is null.
+ */
+ public Component getComponentAfter (Container root, Component current)
+ {
+ if (root == null)
+ throw new IllegalArgumentException ("focus cycle root is null");
+ if (current == null)
+ throw new IllegalArgumentException ("current component is null");
+
+ if (!root.isFocusCycleRoot ())
+ throw new IllegalArgumentException ("root is not a focus cycle root");
+
+ Container ancestor = current.getFocusCycleRootAncestor ();
+ Container prevAncestor = ancestor;
+ while (ancestor != root)
+ {
+ ancestor = current.getFocusCycleRootAncestor ();
+ if (ancestor == prevAncestor)
+ {
+ // We've reached the top focus cycle root ancestor. Check
+ // if it is root.
+ if (ancestor == null)
+ ancestor = root;
+ else if (ancestor != root)
+ throw new IllegalArgumentException ("the given container is not"
+ + " a focus cycle root of the"
+ + " current component");
+ else
+ break;
+ }
+ prevAncestor = ancestor;
+ }
+
+ // FIXME: is this the right thing to do here? It moves the context
+ // for traversal up one focus traversal cycle. We'll need a test
+ // for this.
+ if ((Component) root == current)
+ root = current.getFocusCycleRootAncestor ();
+
+ // Check if we've reached the top of the component hierarchy. If
+ // so then we want to loop around to the first component in the
+ // focus traversal cycle.
+ if (current instanceof Window)
+ return getFirstComponent ((Container) current);
+
+ Container parent = current.getParent ();
+ synchronized (parent.getTreeLock ())
+ {
+ Component[] components = parent.getComponents ();
+ int componentIndex = 0;
+ int numComponents = parent.getComponentCount ();
+
+ // Find component's index.
+ for (int i = 0; i < numComponents; i++)
+ {
+ if (components[i].equals(current))
+ componentIndex = i;
+ }
+
+ // Search forward for the next acceptable component.
+ // Search through all components at least one time
+ // i.e. start at componentIndex + 1 --> nComponents -1 --> 0 ---> componentIndex
+ int i = componentIndex + 1;
+ int end = numComponents - 1;
+ Component next = getNextAvailableComponent(components, i, end);
+ if (next != null)
+ return next;
+
+ // Now check remainder of components from 0 to componentIndex
+ i = 0;
+ end = componentIndex;
+ next = getNextAvailableComponent(components, i, end);
+ if (next != null)
+ return next;
+
+ // No focusable components after current in its Container. So go
+ // to the next Component after current's Container (parent).
+ Component result = getComponentAfter (root, parent);
+ return result;
+ }
+ }
+
+ /**
+ * Gets the next available component in the array between the given range.
+ *
+ * @param components - the array of components.
+ * @param start - where to start
+ * @param end - where to end
+ * @return next component if found
+ */
+ private Component getNextAvailableComponent(Component[] components, int start, int end)
+ {
+ while (start <= end)
+ {
+ Component c = components[start];
+
+ if (c.visible && c.isDisplayable() && c.enabled && c.focusable)
+ return c;
+
+ if (c instanceof Container)
+ {
+ Component result = getFirstComponent((Container) c);
+
+ if (result != null && implicitDownCycleTraversal && result.visible
+ && result.isDisplayable() && result.enabled && result.focusable)
+ return result;
+ }
+ start++;
+ }
+
+ return null;
+ }
+
+ /**
+ * Gets the previous available component in the array between the given range.
+ *
+ * @param components - the array of components.
+ * @param start - where to start
+ * @param end - where to end
+ * @return previous component if found
+ */
+ Component getPrevAvailableComponent(Component[] components, int start, int end)
+ {
+ while (start >= end)
+ {
+ Component c = components[start];
+ if (c.visible && c.isDisplayable() && c.enabled && c.focusable)
+ return c;
+
+ if (c instanceof Container)
+ {
+ Component result = getLastComponent((Container) c);
+
+ if (result != null
+ && (result.visible && result.isDisplayable() && result.enabled && result.focusable))
+ return result;
+ }
+ start--;
+ }
+ return null;
+ }
+
+ /**
+ * Returns the Component that should receive the focus before
+ * <code>current</code>. <code>root</code> must be a focus cycle root of
+ * current.
+ *
+ * @param root a focus cycle root of current
+ * @param current a (possibly indirect) child of root, or root itself
+ * @return the previous Component in the focus traversal order for root, or
+ * null if no acceptable Component exists.
+ * @exception IllegalArgumentException If root is not a focus cycle root of
+ * current, or if either root or current is null.
+ */
+ public Component getComponentBefore (Container root, Component current)
+ {
+ if (root == null)
+ throw new IllegalArgumentException ("focus cycle root is null");
+ if (current == null)
+ throw new IllegalArgumentException ("current component is null");
+
+ if (!root.isFocusCycleRoot ())
+ throw new IllegalArgumentException ("root is not a focus cycle root");
+
+ Container ancestor = current.getFocusCycleRootAncestor ();
+ Container prevAncestor = ancestor;
+ while (ancestor != root)
+ {
+ ancestor = current.getFocusCycleRootAncestor ();
+ if (ancestor == prevAncestor)
+ {
+ // We've reached the top focus cycle root ancestor. Check
+ // if it is root.
+ if (ancestor == null)
+ ancestor = root;
+ else if (ancestor != root)
+ throw new IllegalArgumentException ("the given container is not"
+ + " a focus cycle root of the"
+ + " current component");
+ else
+ break;
+ }
+ prevAncestor = ancestor;
+ }
+
+ // FIXME: is this the right thing to do here? It moves the context
+ // for traversal up one focus traversal cycle. We'll need a test
+ // for this.
+ if ((Component) root == current)
+ root = current.getFocusCycleRootAncestor ();
+
+ // Check if we've reached the top of the component hierarchy. If
+ // so then we want to loop around to the last component in the
+ // focus traversal cycle.
+ if (current instanceof Window)
+ return getLastComponent ((Container) current);
+
+ Container parent = current.getParent ();
+
+ synchronized (parent.getTreeLock ())
+ {
+ Component[] components = parent.getComponents ();
+ int componentIndex = 0;
+ int numComponents = parent.getComponentCount ();
+
+ // Find component's index.
+ for (int i = 0; i < numComponents; i++)
+ {
+ if (components[i] == current)
+ componentIndex = i;
+ }
+
+ // Search through all components at least one time
+ // i.e. start at componentIndex - 1 --> 0 --> numComponents -1 ---> componentIndex
+ int i = componentIndex - 1;
+ int end = 0;
+ Component prev = getPrevAvailableComponent(components, i, end);
+ if (prev != null)
+ return prev;
+
+ // Now check remainder of components
+ i = numComponents -1;
+ end = componentIndex;
+ prev = getPrevAvailableComponent(components, i, end);
+ if (prev != null)
+ return prev;
+
+ // No focusable components before current in its Container. So go
+ // to the previous Component before current's Container (parent).
+ Component result = getComponentBefore (root, parent);
+
+ return result;
+ }
+ }
+
+ /**
+ * Returns the first Component of root that should receive the focus.
+ *
+ * @param root a focus cycle root
+ *
+ * @return the first Component in the focus traversal order for
+ * root, or null if no acceptable Component exists.
+ *
+ * @exception IllegalArgumentException If root is null.
+ */
+ public Component getFirstComponent(Container root)
+ {
+ if (root == null)
+ throw new IllegalArgumentException ();
+
+ if (!root.isVisible ()
+ || !root.isDisplayable ())
+ return null;
+
+ if (accept(root))
+ return root;
+
+ int ncomponents = root.getComponentCount();
+ for (int i = 0; i < ncomponents; i++)
+ {
+ Component component = root.getComponent(i);
+ if (component instanceof Container
+ && !((Container) component).isFocusCycleRoot())
+ {
+ Component first = null;
+ Container cont = (Container) component;
+ if (cont.isFocusTraversalPolicyProvider())
+ {
+ FocusTraversalPolicy childPol = cont.getFocusTraversalPolicy();
+ first = childPol.getFirstComponent(cont);
+ }
+ else
+ first = getFirstComponent(cont);
+ if (first != null)
+ return first;
+ }
+ else if (accept(component))
+ return component;
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the last Component of root that should receive the focus.
+ *
+ * @param root a focus cycle root
+ *
+ * @return the last Component in the focus traversal order for
+ * root, or null if no acceptable Component exists.
+ *
+ * @exception IllegalArgumentException If root is null.
+ */
+ public Component getLastComponent (Container root)
+ {
+ if (root == null)
+ throw new IllegalArgumentException ();
+
+ if (!root.isVisible ()
+ || !root.isDisplayable ())
+ return null;
+
+ if (root.visible && root.isDisplayable() && root.enabled
+ && root.focusable)
+ return root;
+
+ Component[] componentArray = root.getComponents ();
+
+ for (int i = componentArray.length - 1; i >= 0; i--)
+ {
+ Component component = componentArray [i];
+
+ if (component.visible && component.isDisplayable() && component.enabled
+ && component.focusable)
+ return component;
+
+ if (component instanceof Container)
+ {
+ Component result = getLastComponent ((Container) component);
+
+ if (result != null &&
+ result.visible && result.isDisplayable() && result.enabled
+ && result.focusable)
+ return result;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the default Component of root that should receive the focus.
+ *
+ * @param root a focus cycle root
+ *
+ * @return the default Component in the focus traversal order for
+ * root, or null if no acceptable Component exists.
+ *
+ * @exception IllegalArgumentException If root is null.
+ */
+ public Component getDefaultComponent (Container root)
+ {
+ return getFirstComponent (root);
+ }
+
+ /**
+ * Set whether or not implicit down cycling is enabled. If it is,
+ * then initiating a forward focus traversal operation onto a focus
+ * cycle root, the focus will be implicitly transferred into the
+ * root container's focus cycle.
+ *
+ * @param value the setting for implicit down cycling
+ */
+ public void setImplicitDownCycleTraversal (boolean value)
+ {
+ implicitDownCycleTraversal = value;
+ }
+
+ /**
+ * Check whether or not implicit down cycling is enabled. If it is,
+ * then initiating a forward focus traversal operation onto a focus
+ * cycle root, the focus will be implicitly transferred into the
+ * root container's focus cycle.
+ *
+ * @return true if the focus will be transferred down-cycle
+ * implicitly
+ */
+ public boolean getImplicitDownCycleTraversal ()
+ {
+ return implicitDownCycleTraversal;
+ }
+
+ /**
+ * Check whether the given Component is an acceptable target for the
+ * keyboard input focus.
+ *
+ * @param current the Component to check
+ *
+ * @return true if current is acceptable, false otherwise
+ */
+ protected boolean accept (Component current)
+ {
+ return (current.visible
+ && current.isDisplayable ()
+ && current.enabled
+ && current.focusable);
+ }
+}
diff --git a/libjava/classpath/java/awt/Cursor.java b/libjava/classpath/java/awt/Cursor.java
new file mode 100644
index 000000000..69d0e87f5
--- /dev/null
+++ b/libjava/classpath/java/awt/Cursor.java
@@ -0,0 +1,239 @@
+/* Copyright (C) 1999, 2000, 2002 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This class represents various predefined cursor types.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class Cursor implements java.io.Serializable
+{
+ static final long serialVersionUID = 8028237497568985504L;
+
+ /**
+ * Constant for the system default cursor type
+ */
+ public static final int DEFAULT_CURSOR = 0;
+
+ /**
+ * Constant for a cross-hair cursor.
+ */
+ public static final int CROSSHAIR_CURSOR = 1;
+
+ /**
+ * Constant for a cursor over a text field.
+ */
+ public static final int TEXT_CURSOR = 2;
+
+ /**
+ * Constant for a cursor to display while waiting for an action to complete.
+ */
+ public static final int WAIT_CURSOR = 3;
+
+ /**
+ * Cursor used over SW corner of window decorations.
+ */
+ public static final int SW_RESIZE_CURSOR = 4;
+
+ /**
+ * Cursor used over SE corner of window decorations.
+ */
+ public static final int SE_RESIZE_CURSOR = 5;
+
+ /**
+ * Cursor used over NW corner of window decorations.
+ */
+ public static final int NW_RESIZE_CURSOR = 6;
+
+ /**
+ * Cursor used over NE corner of window decorations.
+ */
+ public static final int NE_RESIZE_CURSOR = 7;
+
+ /**
+ * Cursor used over N edge of window decorations.
+ */
+ public static final int N_RESIZE_CURSOR = 8;
+
+ /**
+ * Cursor used over S edge of window decorations.
+ */
+ public static final int S_RESIZE_CURSOR = 9;
+
+ /**
+ * Cursor used over W edge of window decorations.
+ */
+ public static final int W_RESIZE_CURSOR = 10;
+
+ /**
+ * Cursor used over E edge of window decorations.
+ */
+ public static final int E_RESIZE_CURSOR = 11;
+
+ /**
+ * Constant for a hand cursor.
+ */
+ public static final int HAND_CURSOR = 12;
+
+ /**
+ * Constant for a cursor used during window move operations.
+ */
+ public static final int MOVE_CURSOR = 13;
+
+ private static String[] NAMES = { "Default Cursor", "Crosshair Cursor",
+ "Text Cursor", "Wait Cursor",
+ "Southwest Resize Cursor",
+ "Southeast Resize Cursor",
+ "Northwest Resize Cursor",
+ "Northeast Resize Cursor",
+ "North Resize Cursor", "South Resize Cursor",
+ "West Resize Cursor", "East Resize Cursor",
+ "Hand Cursor", "Move Cursor" };
+
+ public static final int CUSTOM_CURSOR = 0xFFFFFFFF;
+
+ private static final int PREDEFINED_COUNT = 14;
+
+ protected static Cursor[] predefined = new Cursor[PREDEFINED_COUNT];
+ protected String name;
+
+ /**
+ * @serial The numeric id of this cursor.
+ */
+ int type;
+
+ /**
+ * Initializes a new instance of <code>Cursor</code> with the specified
+ * type.
+ *
+ * @param type The cursor type.
+ *
+ * @exception IllegalArgumentException If the specified cursor type is invalid
+ */
+ public Cursor(int type)
+ {
+ if (type < 0 || type >= PREDEFINED_COUNT)
+ throw new IllegalArgumentException ("invalid cursor " + type);
+
+ this.type = type;
+
+ name = NAMES[type];
+
+ // FIXME: lookup?
+ }
+
+ /** This constructor is used internally only.
+ * Application code should call Toolkit.createCustomCursor().
+ */
+ protected Cursor(String name)
+ {
+ this.name = name;
+ this.type = CUSTOM_CURSOR;
+ }
+
+ /**
+ * Returns an instance of <code>Cursor</code> for one of the specified
+ * predetermined types.
+ *
+ * @param type The type contant from this class.
+ *
+ * @return The requested predefined cursor.
+ *
+ * @exception IllegalArgumentException If the constant is not one of the
+ * predefined cursor type constants from this class.
+ */
+ public static Cursor getPredefinedCursor(int type)
+ {
+ if (type < 0 || type >= PREDEFINED_COUNT)
+ throw new IllegalArgumentException ("invalid cursor " + type);
+ if (predefined[type] == null)
+ predefined[type] = new Cursor(type);
+ return predefined[type];
+ }
+
+ /**
+ * Retrieves the system specific custom Cursor named Cursor names are,
+ * for example: "Invalid.16x16".
+ *
+ * @exception AWTException
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true.
+ */
+ public static Cursor getSystemCustomCursor(String name)
+ throws AWTException
+ {
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException ();
+
+ // FIXME
+ return null;
+ }
+
+ /**
+ * Returns an instance of the system default cursor type.
+ *
+ * @return The system default cursor.
+ */
+ public static Cursor getDefaultCursor()
+ {
+ return getPredefinedCursor(DEFAULT_CURSOR);
+ }
+
+ /**
+ * Returns the numeric type identifier for this cursor.
+ *
+ * @return The cursor id.
+ */
+ public int getType()
+ {
+ return type;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public String toString()
+ {
+ return (this.getClass()
+ + "[type=" + getType()
+ + ",name=" + getName() + "]");
+ }
+}
diff --git a/libjava/classpath/java/awt/DefaultFocusTraversalPolicy.java b/libjava/classpath/java/awt/DefaultFocusTraversalPolicy.java
new file mode 100644
index 000000000..3f017c5a5
--- /dev/null
+++ b/libjava/classpath/java/awt/DefaultFocusTraversalPolicy.java
@@ -0,0 +1,111 @@
+/* DefaultFocusTraversalPolicy.java --
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * DefaultFocusTraversalPolicy is the default focus traversal policy
+ * used by Containers.
+ *
+ * This policy sharpens ContainerOrderFocusTraversalPolicy's
+ * acceptance criteria, to reject those Components that have
+ * unfocusable peers. Despite this extra strictness, this policy will
+ * always accept a Component that has explicitly been set focusable by
+ * any means.
+ *
+ * This AWT implementation assumes that the peers of the following
+ * Components are not focusable: Canvas, Panel, Label, ScrollPane,
+ * Scrollbar, Window, and any lightweight Component.
+ *
+ * A Component's focusability is independent of the focusability of
+ * its peer.
+ *
+ * @author Thomas Fitzsimmons (fitzsim@redhat.com)
+ * @since 1.4
+ */
+public class DefaultFocusTraversalPolicy
+ extends ContainerOrderFocusTraversalPolicy
+{
+ private static final long serialVersionUID = 8876966522510157497L;
+
+ /**
+ * Construct a default focus traversal policy.
+ */
+ public DefaultFocusTraversalPolicy ()
+ {
+ }
+
+ /**
+ * Check whether a given Component would be acceptable as a focus
+ * owner. The Component must be displayable, visible and enabled to
+ * be acceptable. If the Component's focus traversability has been
+ * overridden, by overriding Component.isFocusTraversable or
+ * Component.isFocusable, or by calling Component.setFocusable, then
+ * the Component will be accepted if it is focusable. If the
+ * Component uses the default focus traversable behaviour, then
+ * <code>comp</code> will always be rejected if it is a Canvas,
+ * Panel, Label, ScrollPane, Scrollbar, Window or lightweight
+ * Component.
+ *
+ * @param comp the Component to check
+ *
+ * @return true if the Component is an acceptable target for
+ * keyboard input focus, false otherwise
+ */
+ protected boolean accept (Component comp)
+ {
+ if (comp.visible
+ && comp.isDisplayable ()
+ && comp.enabled)
+ {
+ if (comp.isFocusTraversableOverridden != 0
+ && (comp.isFocusTraversable () || comp.isFocusable()))
+ return true;
+
+ if (!(comp instanceof Canvas
+ || comp instanceof Panel
+ || comp instanceof Label
+ || comp instanceof ScrollPane
+ || comp instanceof Scrollbar
+ || comp instanceof Window
+ || comp.isLightweight ()))
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/libjava/classpath/java/awt/DefaultKeyboardFocusManager.java b/libjava/classpath/java/awt/DefaultKeyboardFocusManager.java
new file mode 100644
index 000000000..f62e6e53e
--- /dev/null
+++ b/libjava/classpath/java/awt/DefaultKeyboardFocusManager.java
@@ -0,0 +1,566 @@
+/* DefaultKeyboardFocusManager.java --
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.FocusEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.WindowEvent;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+// FIXME: finish documentation
+public class DefaultKeyboardFocusManager extends KeyboardFocusManager
+{
+ /**
+ * This class models a request to delay the dispatch of events that
+ * arrive after a certain time, until a certain component becomes
+ * the focus owner.
+ */
+ private class EventDelayRequest implements Comparable
+ {
+ /** A {@link java.util.List} of {@link java.awt.event.KeyEvent}s
+ that are being delayed, pending this request's {@link
+ Component} receiving the keyboard focus. */
+ private LinkedList enqueuedKeyEvents = new LinkedList ();
+
+ /** An event timestamp. All events that arrive after this time
+ should be queued in the {@link #enqueuedKeyEvents} {@link
+ java.util.List}. */
+ public long timestamp;
+ /** When this {@link Component} becomes focused, all events
+ between this EventDelayRequest and the next one in will be
+ dispatched from {@link #enqueuedKeyEvents}. */
+ public Component focusedComp;
+
+ /**
+ * Construct a new EventDelayRequest.
+ *
+ * @param timestamp events that arrive after this time will be
+ * delayed
+ * @param focusedComp the Component that needs to receive focus
+ * before events are dispatched
+ */
+ public EventDelayRequest (long timestamp, Component focusedComp)
+ {
+ this.timestamp = timestamp;
+ this.focusedComp = focusedComp;
+ }
+
+ public int compareTo (Object o)
+ {
+ if (!(o instanceof EventDelayRequest))
+ throw new ClassCastException ();
+
+ EventDelayRequest request = (EventDelayRequest) o;
+
+ if (request.timestamp < timestamp)
+ return -1;
+ else if (request.timestamp == timestamp)
+ return 0;
+ else
+ return 1;
+ }
+
+ public boolean equals (Object o)
+ {
+ if (!(o instanceof EventDelayRequest) || o == null)
+ return false;
+
+ EventDelayRequest request = (EventDelayRequest) o;
+
+ return (request.timestamp == timestamp
+ && request.focusedComp == focusedComp);
+ }
+
+ public void enqueueEvent (KeyEvent e)
+ {
+ KeyEvent last = (KeyEvent) enqueuedKeyEvents.getLast ();
+ if (last != null && e.getWhen () < last.getWhen ())
+ throw new RuntimeException ("KeyEvents enqueued out-of-order");
+
+ if (e.getWhen () <= timestamp)
+ throw new RuntimeException ("KeyEvents enqueued before starting timestamp");
+
+ enqueuedKeyEvents.add (e);
+ }
+
+ public void dispatchEvents ()
+ {
+ int size = enqueuedKeyEvents.size ();
+ for (int i = 0; i < size; i++)
+ {
+ KeyEvent e = (KeyEvent) enqueuedKeyEvents.remove (0);
+ dispatchKeyEvent (e);
+ }
+ }
+
+ public void discardEvents ()
+ {
+ enqueuedKeyEvents.clear ();
+ }
+ }
+
+ /**
+ * This flag indicates for which focus traversal key release event we
+ * possibly wait, before letting any more KEY_TYPED events through.
+ */
+ private AWTKeyStroke waitForKeyStroke = null;
+
+ /** The {@link java.util.SortedSet} of current
+ * {@link EventDelayRequest}s. */
+ private SortedSet delayRequests = new TreeSet ();
+
+ public DefaultKeyboardFocusManager ()
+ {
+ }
+
+ public boolean dispatchEvent (AWTEvent e)
+ {
+ if (e instanceof WindowEvent)
+ {
+ Window target = (Window) e.getSource ();
+
+ if (e.id == WindowEvent.WINDOW_ACTIVATED)
+ setGlobalActiveWindow (target);
+ else if (e.id == WindowEvent.WINDOW_GAINED_FOCUS)
+ {
+ setGlobalFocusedWindow (target);
+ FocusTraversalPolicy p = target.getFocusTraversalPolicy();
+ Component toFocus = p.getInitialComponent(target);
+ if (toFocus != null)
+ toFocus.requestFocusInWindow();
+ }
+ else if (e.id != WindowEvent.WINDOW_LOST_FOCUS
+ && e.id != WindowEvent.WINDOW_DEACTIVATED)
+ return false;
+
+ redispatchEvent(target, e);
+ return true;
+ }
+ else if (e instanceof FocusEvent)
+ {
+ FocusEvent fe = (FocusEvent) e;
+ Component target = fe.getComponent ();
+
+ boolean retval = false;
+ if (e.id == FocusEvent.FOCUS_GAINED)
+ {
+ retval = handleFocusGained(fe);
+ }
+ else if (e.id == FocusEvent.FOCUS_LOST)
+ {
+ retval = handleFocusLost(fe);
+ }
+ return true;
+ }
+ else if (e instanceof KeyEvent)
+ {
+ // Loop through all registered KeyEventDispatchers, giving
+ // each a chance to handle this event.
+ Iterator i = getKeyEventDispatchers().iterator();
+
+ while (i.hasNext ())
+ {
+ KeyEventDispatcher dispatcher = (KeyEventDispatcher) i.next ();
+ if (dispatcher.dispatchKeyEvent ((KeyEvent) e))
+ return true;
+ }
+
+ // processKeyEvent checks if this event represents a focus
+ // traversal key stroke.
+ Component focusOwner = getGlobalPermanentFocusOwner ();
+
+ if (focusOwner != null)
+ processKeyEvent (focusOwner, (KeyEvent) e);
+
+ if (e.isConsumed ())
+ return true;
+
+ if (enqueueKeyEvent ((KeyEvent) e))
+ // This event was enqueued for dispatch at a later time.
+ return true;
+ else
+ // This event wasn't handled by any of the registered
+ // KeyEventDispatchers, and wasn't enqueued for dispatch
+ // later, so send it to the default dispatcher.
+ return dispatchKeyEvent ((KeyEvent) e);
+ }
+
+ return false;
+ }
+
+ /**
+ * Handles FOCUS_GAINED events in {@link #dispatchEvent(AWTEvent)}.
+ *
+ * @param fe the focus event
+ */
+ private boolean handleFocusGained(FocusEvent fe)
+ {
+ Component target = fe.getComponent ();
+
+ // If old focus owner != new focus owner, notify old focus
+ // owner that it has lost focus.
+ Component oldFocusOwner = getGlobalFocusOwner();
+ if (oldFocusOwner != null && oldFocusOwner != target)
+ {
+ FocusEvent lost = new FocusEvent(oldFocusOwner,
+ FocusEvent.FOCUS_LOST,
+ fe.isTemporary(), target);
+ oldFocusOwner.dispatchEvent(lost);
+ }
+
+ setGlobalFocusOwner (target);
+ if (target != getGlobalFocusOwner())
+ {
+ // Focus transfer was rejected, like when the target is not
+ // focusable.
+ dequeueKeyEvents(-1, target);
+ // FIXME: Restore focus somehow.
+ }
+ else
+ {
+ if (! fe.isTemporary())
+ {
+ setGlobalPermanentFocusOwner (target);
+ if (target != getGlobalPermanentFocusOwner())
+ {
+ // Focus transfer was rejected, like when the target is not
+ // focusable.
+ dequeueKeyEvents(-1, target);
+ // FIXME: Restore focus somehow.
+ }
+ else
+ {
+ redispatchEvent(target, fe);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Handles FOCUS_LOST events for {@link #dispatchEvent(AWTEvent)}.
+ *
+ * @param fe the focus event
+ *
+ * @return if the event has been handled
+ */
+ private boolean handleFocusLost(FocusEvent fe)
+ {
+ Component currentFocus = getGlobalFocusOwner();
+ if (currentFocus != fe.getOppositeComponent())
+ {
+ setGlobalFocusOwner(null);
+ if (getGlobalFocusOwner() != null)
+ {
+ // TODO: Is this possible? If so, then we should try to restore
+ // the focus.
+ }
+ else
+ {
+ if (! fe.isTemporary())
+ {
+ setGlobalPermanentFocusOwner(null);
+ if (getGlobalPermanentFocusOwner() != null)
+ {
+ // TODO: Is this possible? If so, then we should try to
+ // restore the focus.
+ }
+ else
+ {
+ fe.setSource(currentFocus);
+ redispatchEvent(currentFocus, fe);
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ private boolean enqueueKeyEvent (KeyEvent e)
+ {
+ Iterator i = delayRequests.iterator ();
+ boolean oneEnqueued = false;
+ while (i.hasNext ())
+ {
+ EventDelayRequest request = (EventDelayRequest) i.next ();
+ if (e.getWhen () > request.timestamp)
+ {
+ request.enqueueEvent (e);
+ oneEnqueued = true;
+ }
+ }
+ return oneEnqueued;
+ }
+
+ public boolean dispatchKeyEvent (KeyEvent e)
+ {
+ Component focusOwner = getFocusOwner();
+ if (focusOwner == null)
+ focusOwner = getFocusedWindow();
+
+ if (focusOwner != null)
+ redispatchEvent(focusOwner, e);
+
+ // Loop through all registered KeyEventPostProcessors, giving
+ // each a chance to process this event.
+ Iterator i = getKeyEventPostProcessors().iterator();
+
+ while (i.hasNext ())
+ {
+ KeyEventPostProcessor processor = (KeyEventPostProcessor) i.next ();
+ if (processor.postProcessKeyEvent (e))
+ return true;
+ }
+
+ // The event hasn't been consumed yet. Check if it is an
+ // MenuShortcut.
+ if (postProcessKeyEvent (e))
+ return true;
+
+ // Always return true.
+ return true;
+ }
+
+ public boolean postProcessKeyEvent (KeyEvent e)
+ {
+ // Check if this event represents a menu shortcut.
+
+ // MenuShortcuts are activated by Ctrl- KeyEvents, only on KEY_PRESSED.
+ int modifiers = e.getModifiersEx ();
+ if (e.getID() == KeyEvent.KEY_PRESSED
+ && (modifiers & KeyEvent.CTRL_DOWN_MASK) != 0)
+ {
+ Window focusedWindow = getGlobalFocusedWindow ();
+ if (focusedWindow instanceof Frame)
+ {
+ MenuBar menubar = ((Frame) focusedWindow).getMenuBar ();
+
+ if (menubar != null)
+ {
+ // If there's a menubar, loop through all menu items,
+ // checking whether each one has a shortcut, and if
+ // so, whether this key event should activate it.
+ int numMenus = menubar.getMenuCount ();
+
+ for (int i = 0; i < numMenus; i++)
+ {
+ Menu menu = menubar.getMenu (i);
+ int numItems = menu.getItemCount ();
+
+ for (int j = 0; j < numItems; j++)
+ {
+ MenuItem item = menu.getItem (j);
+ MenuShortcut shortcut = item.getShortcut ();
+
+ if (item.isEnabled() && shortcut != null)
+ {
+ // Dispatch a new ActionEvent if:
+ //
+ // a) this is a Shift- KeyEvent, and the
+ // shortcut requires the Shift modifier
+ //
+ // or, b) this is not a Shift- KeyEvent, and the
+ // shortcut does not require the Shift
+ // modifier.
+ if (shortcut.getKey () == e.getKeyCode ()
+ && ((shortcut.usesShiftModifier ()
+ && (modifiers & KeyEvent.SHIFT_DOWN_MASK) != 0)
+ || (! shortcut.usesShiftModifier ()
+ && (modifiers & KeyEvent.SHIFT_DOWN_MASK) == 0)))
+ {
+ item.dispatchEvent (new ActionEvent (item,
+ ActionEvent.ACTION_PERFORMED,
+ item.getActionCommand (),
+ modifiers));
+ // The event was dispatched.
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ public void processKeyEvent (Component comp, KeyEvent e)
+ {
+ AWTKeyStroke eventKeystroke = AWTKeyStroke.getAWTKeyStrokeForEvent (e);
+ // For every focus traversal keystroke, we need to also consume
+ // the other two key event types for the same key (e.g. if
+ // KEY_PRESSED TAB is a focus traversal keystroke, we also need to
+ // consume KEY_RELEASED and KEY_TYPED TAB key events).
+ // consuming KEY_RELEASED is easy, because their keyCodes matches
+ // the KEY_PRESSED event. Consuming the intermediate KEY_TYPED is
+ // very difficult because their is no clean way that we can know
+ // which KEY_TYPED belongs to a focusTraversalKey and which not.
+ // To address this problem we swallow every KEY_TYPE between the
+ // KEY_PRESSED event that matches a focusTraversalKey and the
+ // corresponding KEY_RELEASED.
+ AWTKeyStroke oppositeKeystroke = AWTKeyStroke.getAWTKeyStroke (e.getKeyCode (),
+ e.getModifiersEx (),
+ !(e.id == KeyEvent.KEY_RELEASED));
+
+ // Here we check if we are currently waiting for a KEY_RELEASED and
+ // swallow all KeyEvents that are to be delivered in between. This
+ // should only be the KEY_TYPED events that correspond to the
+ // focusTraversalKey's KEY_PRESSED event
+ if (waitForKeyStroke != null)
+ {
+ if (eventKeystroke.equals(waitForKeyStroke))
+ // release this lock
+ waitForKeyStroke = null;
+
+ // as long as we are waiting for the KEY_RELEASED, we swallow every
+ // KeyEvent, including the KEY_RELEASED
+ e.consume();
+ return;
+ }
+
+ Set forwardKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
+ Set backwardKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
+ Set upKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
+ Set downKeystrokes = null;
+ if (comp instanceof Container)
+ downKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
+
+ if (forwardKeystrokes.contains (eventKeystroke))
+ {
+ waitForKeyStroke = oppositeKeystroke;
+ focusNextComponent (comp);
+ e.consume ();
+ }
+ else if (backwardKeystrokes.contains (eventKeystroke))
+ {
+ waitForKeyStroke = oppositeKeystroke;
+ focusPreviousComponent (comp);
+ e.consume ();
+ }
+ else if (upKeystrokes.contains (eventKeystroke))
+ {
+ waitForKeyStroke = oppositeKeystroke;
+ upFocusCycle (comp);
+ e.consume ();
+ }
+ else if (comp instanceof Container
+ && downKeystrokes.contains (eventKeystroke))
+ {
+ waitForKeyStroke = oppositeKeystroke;
+ downFocusCycle ((Container) comp);
+ e.consume ();
+ }
+ }
+
+ protected void enqueueKeyEvents (long after, Component untilFocused)
+ {
+ delayRequests.add (new EventDelayRequest (after, untilFocused));
+ }
+
+ protected void dequeueKeyEvents (long after, Component untilFocused)
+ {
+ // FIXME: need synchronization on delayRequests and enqueuedKeyEvents.
+
+ // Remove the KeyEvent with the oldest timestamp, which should be
+ // the first element in the SortedSet.
+ if (after < 0)
+ {
+ int size = delayRequests.size ();
+ if (size > 0)
+ delayRequests.remove (delayRequests.first ());
+ }
+ else
+ {
+ EventDelayRequest template = new EventDelayRequest (after, untilFocused);
+ if (delayRequests.contains (template))
+ {
+ EventDelayRequest actual = (EventDelayRequest) delayRequests.tailSet (template).first ();
+ delayRequests.remove (actual);
+ actual.dispatchEvents ();
+ }
+ }
+ }
+
+ protected void discardKeyEvents (Component comp)
+ {
+ // FIXME: need synchronization on delayRequests and enqueuedKeyEvents.
+
+ Iterator i = delayRequests.iterator ();
+
+ while (i.hasNext ())
+ {
+ EventDelayRequest request = (EventDelayRequest) i.next ();
+
+ if (request.focusedComp == comp
+ || (comp instanceof Container
+ && ((Container) comp).isAncestorOf (request.focusedComp)))
+ request.discardEvents ();
+ }
+ }
+
+ public void focusPreviousComponent (Component comp)
+ {
+ if (comp != null)
+ comp.transferFocusBackward();
+ }
+
+ public void focusNextComponent (Component comp)
+ {
+ if (comp != null)
+ comp.transferFocus();
+ }
+
+ public void upFocusCycle (Component comp)
+ {
+ if (comp != null)
+ comp.transferFocusUpCycle();
+ }
+
+ public void downFocusCycle (Container cont)
+ {
+ if (cont != null)
+ cont.transferFocusDownCycle();
+ }
+} // class DefaultKeyboardFocusManager
diff --git a/libjava/classpath/java/awt/Desktop.java b/libjava/classpath/java/awt/Desktop.java
new file mode 100644
index 000000000..1b4078823
--- /dev/null
+++ b/libjava/classpath/java/awt/Desktop.java
@@ -0,0 +1,268 @@
+/* Desktop.java -- enable desktop integration between java programs and system
+ programs.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath 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 for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.peer.DesktopPeer;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+
+/**
+ * This class enables Java application to access system commands to perform
+ * desktop oriented operations, like writing and sending emails, or surfing
+ * webpages with the system browser or editing/printing files with a default
+ * editor. Methods are provided to handle these common operations, plus an
+ * <code>open</code> command selects a default registered application for the
+ * specified file type. For example, opening an odf file results in launching
+ * OpenOffice. If an operation is not supported, or the application fails to
+ * launch, an exception is generated.
+ *
+ * <strong>Implementation note: </strong>As this class is used to manage Desktop
+ * integration, we provide some extension to configure the behaviour of this
+ * class depending on the type of dektop that is detected.<br />
+ *
+ * First of all, we support 5 system properties that can be used to define
+ * the application to launch in any given case. These properties are:<br />
+ * <br />
+ * <code>gnu.java.awt.peer.Desktop.html.command</code><br />
+ * <code>gnu.java.awt.peer.Desktop.mail.command</code><br />
+ * <code>gnu.java.awt.peer.Desktop.edit.command</code><br />
+ * <code>gnu.java.awt.peer.Desktop.print.command</code><br />
+ * <code>gnu.java.awt.peer.Desktop.open.command</code><br />
+ * <br />
+ * <br />
+ * These can be specified from the command line and have priority on every
+ * other setting.<br />
+ * <br />
+ * The second method supported is defining a Java preference.<br />
+ * The main preference node is a <strong>user node</strong> relative to the
+ * class <code>gnu.java.awt.peer.ClasspathDesktopPeer</code>. This node
+ * contains a child for each supported operation. The key for each type is
+ * always <code>command</code>:
+ * <br /><br />
+ * <code>gnu.java.awt.peer.Desktop.html.command</code><br />
+ * <code>gnu.java.awt.peer.Desktop.mail.command</code><br />
+ * <code>gnu.java.awt.peer.Desktop.edit.command</code><br />
+ * <code>gnu.java.awt.peer.Desktop.print.command</code><br />
+ * <code>gnu.java.awt.peer.Desktop.open.command</code><br />
+ * <br />
+ * <br />
+ * The access to these keys is done with the Preference API or, if outside
+ * of the java scope, is done in a backend dependent way. For example,
+ * with the GConf backend, you can access these properties
+ * with (may not be accurate on your system):
+ * <br /><br />
+ * <code>
+ * gconftool-2 -g /apps/classpath/gnu/java/awt/peer/Desktop/html/command
+ * </code>
+ *
+ * @author Mario Torre <neugens@limasoftware.net>
+ * @since 1.6
+ */
+public class Desktop
+{
+ /**
+ * Represents an action type supported by a platform.
+ *
+ * To determine if a given action is supported by the platform,
+ * use the <code>Desktop.isSupported(java.awt.Desktop.Action)</code>
+ * method.
+ *
+ * @author Mario Torre <neugens@limasoftware.net>
+ */
+ public enum Action
+ {
+ BROWSE, EDIT, MAIL, OPEN, PRINT
+ }
+
+ private DesktopPeer peer;
+
+ private Desktop()
+ {
+ /* nothing to be done */
+ }
+
+ /**
+ * Returns an instance of the Desktop Class.
+ *
+ * If this implementation does not support Desktop, an
+ * UnsupportedOperationException will be thrown.
+ * Also, an HeadlessException will be generated if
+ * GraphicsEnvironment.isHeadless() returns true.
+ *
+ * @throws UnsupportedOperationException
+ * @throws HeadlessException
+ */
+ public static Desktop getDesktop() throws UnsupportedOperationException,
+ HeadlessException
+ {
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException();
+
+ if (!Desktop.isDesktopSupported())
+ throw new UnsupportedOperationException();
+
+ Desktop desktop = new Desktop();
+ desktop.peer = Toolkit.getDefaultToolkit().createDesktopPeer(desktop);
+
+ return desktop;
+ }
+
+ /**
+ * Check if this implementation supports Desktop.
+ * If true, use getDesktop to get an instance of this class.
+ *
+ * This implementation will return false when GraphicsEnvironment.isHeadless
+ * returns true.
+ *
+ * @return true if this class is supported on the current platform;
+ * false otherwise
+ */
+ public static boolean isDesktopSupported()
+ {
+ if (GraphicsEnvironment.isHeadless())
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Check if the given Action is supported by this implementation.
+ *
+ * @param action
+ * @return
+ */
+ public boolean isSupported(Desktop.Action action)
+ {
+ return peer.isSupported(action);
+ }
+
+ /**
+ * Launches the Desktop default browser to open the given <code>uri</code>.
+ *
+ * If a security manager exists and denies
+ * AWTPermission("showWindowWithoutWarningBanner"),a SecurityException will
+ * be generated.
+ *
+ * @param uri
+ * @throws IOException
+ */
+ public void browse(URI uri)
+ throws IOException
+ {
+ peer.browse(uri);
+ }
+
+ /**
+ * Launch the edit command to edit this file.
+ * File should already exist before the editing starts.
+ *
+ * If a security manager exists and
+ * SecurityManager.checkRead(java.lang.String) method denies read access to
+ * the file, or SecurityManager.checkPrintJobAccess() method denies the
+ * permission to print the file, a SecurityException will be generated.
+ *
+ * @param file
+ * @throws IOException
+ */
+ public void edit(File file)
+ throws IOException
+ {
+ peer.edit(file);
+ }
+
+ /**
+ * Launches the Desktop default mailer.
+ *
+ * If a security manager exists and denies
+ * AWTPermission("showWindowWithoutWarningBanner"), a SecurityException will
+ * be generated.
+ *
+ * @throws IOException
+ */
+ public void mail()
+ throws IOException
+ {
+ peer.mail();
+ }
+
+ /**
+ * Launches the Desktop default mailer, with the given mailtoURI
+ * as agrument. The <code>mailtoURI</code> must conform to the
+ * {@link http://www.ietf.org/rfc/rfc2368.txt The mailto URL scheme (RFC 2368)}
+ *
+ * If a security manager exists and denies
+ * AWTPermission("showWindowWithoutWarningBanner"), a SecurityException will
+ * be generated.
+ *
+ * @param mailtoURI
+ * @throws IOException
+ */
+ public void mail(URI mailtoURI)
+ throws IOException
+ {
+ peer.mail(mailtoURI);
+ }
+
+ /**
+ * Launches the Desktop default application to open the given File.
+ * If <code>file</code> is a directory, a file manager is launched.
+ *
+ * @param file
+ * @throws IOException
+ */
+ public void open(File file)
+ throws IOException
+ {
+ peer.open(file);
+ }
+
+ /**
+ * Launch the print program to print this file.
+ *
+ * @param file
+ * @throws IOException
+ */
+ public void print(File file)
+ throws IOException
+ {
+ peer.print(file);
+ }
+}
diff --git a/libjava/classpath/java/awt/Dialog.java b/libjava/classpath/java/awt/Dialog.java
new file mode 100644
index 000000000..d12e1eb12
--- /dev/null
+++ b/libjava/classpath/java/awt/Dialog.java
@@ -0,0 +1,570 @@
+/* Dialog.java -- An AWT dialog box
+ Copyright (C) 1999, 2000, 2001, 2002, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath 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 for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.peer.DialogPeer;
+
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleState;
+import javax.accessibility.AccessibleStateSet;
+
+/**
+ * <code>Dialog</code> provides a top-level window normally used to receive
+ * user input in applications.
+ * <p>
+ * A dialog always has another top-level window as owner and is only visible
+ * if this owner is visible to the user. The default layout of dialogs is the
+ * <code>BorderLayout</code>. Dialogs can be modal (blocks user input to other
+ * components) or non-modal (user input in other components are allowed).
+ * </p>
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@redhat.com)
+ */
+public class Dialog extends Window
+{
+ public enum ModalExclusionType
+ {
+ APPLICATION_EXCLUDE,
+ NO_EXCLUDE,
+ TOOLKIT_EXCLUDE
+ }
+
+ public enum ModalityType
+ {
+ APPLICATION_MODAL,
+ DOCUMENT_MODAL,
+ MODELESS,
+ TOOLKIT_MODAL
+ }
+
+ // Serialization constant
+ private static final long serialVersionUID = 5920926903803293709L;
+
+ /**
+ * @serial Indicates whether or not this dialog box is modal.
+ */
+ private boolean modal;
+
+ /**
+ * @serial Indicates whether or not this dialog box is resizable.
+ */
+ private boolean resizable = true;
+
+ /**
+ * @serial The title string for this dialog box, which can be
+ * <code>null</code>.
+ */
+ private String title;
+
+ /**
+ * This field indicates whether the dialog is undecorated or not.
+ */
+ private boolean undecorated = false;
+
+ /**
+ * Indicates that we are blocked for modality in show
+ */
+ private boolean blocked = false;
+
+ /**
+ * Secondary EventQueue to handle AWT events while we are blocked for
+ * modality in show.
+ */
+ private EventQueue eq2 = null;
+
+ /**
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_dialog_number;
+
+ /**
+ * Initializes a new instance of <code>Dialog</code> with the specified
+ * parent, that is resizable and not modal, and which has no title.
+ *
+ * @param parent The parent frame of this dialog box.
+ * @exception IllegalArgumentException If the owner's GraphicsConfiguration
+ * is not from a screen device, or if owner is null. This exception is
+ * always thrown when GraphicsEnvironment.isHeadless() returns true.
+ */
+ public Dialog(Frame parent)
+ {
+ this(parent, "", false);
+ }
+
+ /**
+ * Initializes a new instance of <code>Dialog</code> with the specified
+ * parent and modality, that is resizable and which has no title.
+ *
+ * @param parent The parent frame of this dialog box.
+ * @param modal <code>true</code> if this dialog box is modal,
+ * <code>false</code> otherwise.
+ *
+ * @exception IllegalArgumentException If the owner's GraphicsConfiguration
+ * is not from a screen device, or if owner is null. This exception is
+ * always thrown when GraphicsEnvironment.isHeadless() returns true.
+ */
+ public Dialog(Frame parent, boolean modal)
+ {
+ this(parent, "", modal);
+ }
+
+ /**
+ * Initializes a new instance of <code>Dialog</code> with the specified
+ * parent, that is resizable and not modal, and which has the specified
+ * title.
+ *
+ * @param parent The parent frame of this dialog box.
+ * @param title The title string for this dialog box.
+ *
+ * @exception IllegalArgumentException If the owner's GraphicsConfiguration
+ * is not from a screen device, or if owner is null. This exceptionnis
+ * always thrown when GraphicsEnvironment.isHeadless() returns true.
+ */
+ public Dialog(Frame parent, String title)
+ {
+ this(parent, title, false);
+ }
+
+ /**
+ * Initializes a new instance of <code>Dialog</code> with the specified,
+ * parent, title, and modality, that is resizable.
+ *
+ * @param parent The parent frame of this dialog box.
+ * @param title The title string for this dialog box.
+ * @param modal <code>true</code> if this dialog box is modal,
+ * <code>false</code> otherwise.
+ *
+ * @exception IllegalArgumentException If owner is null or
+ * GraphicsEnvironment.isHeadless() returns true.
+ */
+ public Dialog(Frame parent, String title, boolean modal)
+ {
+ this(parent, title, modal, parent.getGraphicsConfiguration());
+ }
+
+ /**
+ * Initializes a new instance of <code>Dialog</code> with the specified,
+ * parent, title, modality and <code>GraphicsConfiguration</code>, that is
+ * resizable.
+ *
+ * @param parent The parent frame of this dialog box.
+ * @param title The title string for this dialog box.
+ * @param modal <code>true</code> if this dialog box is modal,
+ * <code>false</code> otherwise.
+ * @param gc The <code>GraphicsConfiguration</code> object to use. If
+ * <code>null</code> the <code>GraphicsConfiguration</code> of the target
+ * frame is used.
+ *
+ * @exception IllegalArgumentException If owner is null, the
+ * GraphicsConfiguration is not a screen device or
+ * GraphicsEnvironment.isHeadless() returns true.
+ * @since 1.4
+ */
+ public Dialog(Frame parent, String title, boolean modal,
+ GraphicsConfiguration gc)
+ {
+ super(parent, (gc == null) ? parent.getGraphicsConfiguration() : gc);
+
+ // A null title is equivalent to an empty title
+ this.title = (title != null) ? title : "";
+ this.modal = modal;
+ visible = false;
+
+ setLayout(new BorderLayout());
+ setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
+ }
+
+ /**
+ * Initializes a new instance of <code>Dialog</code> with the specified,
+ * parent, that is resizable.
+ *
+ * @param owner The parent frame of this dialog box.
+ *
+ * @exception IllegalArgumentException If parent is null. This exception is
+ * always thrown when GraphicsEnvironment.isHeadless() returns true.
+ *
+ * @since 1.2
+ */
+ public Dialog(Dialog owner)
+ {
+ this(owner, "", false, owner.getGraphicsConfiguration());
+ }
+
+ /**
+ * Initializes a new instance of <code>Dialog</code> with the specified,
+ * parent and title, that is resizable.
+ *
+ * @param owner The parent frame of this dialog box.
+ * @param title The title string for this dialog box.
+ *
+ * @exception IllegalArgumentException If parent is null. This exception is
+ * always thrown when GraphicsEnvironment.isHeadless() returns
+ * true.
+ * @since 1.2
+ */
+ public Dialog(Dialog owner, String title)
+ {
+ this(owner, title, false, owner.getGraphicsConfiguration());
+ }
+
+ /**
+ * Initializes a new instance of <code>Dialog</code> with the specified,
+ * parent, title and modality, that is resizable.
+ *
+ * @param owner The parent frame of this dialog box.
+ * @param title The title string for this dialog box.
+ * @param modal <code>true</code> if this dialog box is modal,
+ * <code>false</code> otherwise.
+ *
+ * @exception IllegalArgumentException If parent is null. This exception is
+ * always thrown when GraphicsEnvironment.isHeadless() returns true.
+ * @since 1.2
+ */
+ public Dialog(Dialog owner, String title, boolean modal)
+ {
+ this(owner, title, modal, owner.getGraphicsConfiguration());
+ }
+
+ /**
+ * Initializes a new instance of <code>Dialog</code> with the specified,
+ * parent, title, modality and <code>GraphicsConfiguration</code>, that is
+ * resizable.
+ *
+ * @param parent The parent frame of this dialog box.
+ * @param title The title string for this dialog box.
+ * @param modal <code>true</code> if this dialog box is modal,
+ * <code>false</code> otherwise.
+ * @param gc The <code>GraphicsConfiguration</code> object to use. If
+ * <code>null</code> the <code>GraphicsConfiguration</code> of the target
+ * frame is used.
+ *
+ * @exception IllegalArgumentException If parent is null, the
+ * GraphicsConfiguration is not a screen device or
+ * GraphicsEnvironment.isHeadless() returns true.
+ *
+ * @since 1.4
+ */
+ public Dialog(Dialog parent, String title, boolean modal,
+ GraphicsConfiguration gc)
+ {
+ super(parent, (gc == null) ? parent.getGraphicsConfiguration() : gc);
+
+ // A null title is equivalent to an empty title
+ this.title = (title != null) ? title : "";
+ this.modal = modal;
+ visible = false;
+
+ setLayout(new BorderLayout());
+ setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
+ }
+
+ /**
+ * Returns the title of this dialog box.
+ *
+ * @return The title of this dialog box.
+ */
+ public String getTitle()
+ {
+ return title;
+ }
+
+ /**
+ * Sets the title of this dialog box to the specified string.
+ *
+ * @param title the new title. If <code>null</code> an empty
+ * title will be set.
+ */
+ public synchronized void setTitle(String title)
+ {
+ // A null title is equivalent to an empty title
+ this.title = (title != null) ? title : "";
+
+ if (peer != null)
+ {
+ DialogPeer d = (DialogPeer) peer;
+ d.setTitle(title);
+ }
+ }
+
+ /**
+ * Tests whether or not this dialog box is modal.
+ *
+ * @return <code>true</code> if this dialog box is modal, <code>false</code>
+ * otherwise.
+ */
+ public boolean isModal()
+ {
+ return modal;
+ }
+
+ /**
+ * Changes the modality of this dialog box. This can only be done before the
+ * peer is created.
+ *
+ * @param modal <code>true</code> to make this dialog box modal,
+ * <code>false</code> to make it non-modal.
+ */
+ public void setModal(boolean modal)
+ {
+ this.modal = modal;
+ }
+
+ /**
+ * Tests whether or not this dialog box is resizable.
+ *
+ * @return <code>true</code> if this dialog is resizable,
+ * <code>false</code> otherwise.
+ */
+ public boolean isResizable()
+ {
+ return resizable;
+ }
+
+ /**
+ * Changes the resizability of this dialog box.
+ *
+ * @param resizable <code>true</code> to make this dialog resizable,
+ * <code>false</code> to make it non-resizable.
+ */
+ public synchronized void setResizable(boolean resizable)
+ {
+ this.resizable = resizable;
+ if (peer != null)
+ {
+ DialogPeer d = (DialogPeer) peer;
+ d.setResizable(resizable);
+ }
+ }
+
+ /**
+ * Creates this object's native peer.
+ */
+ public synchronized void addNotify()
+ {
+ if (peer == null)
+ peer = getToolkit().createDialog(this);
+ super.addNotify();
+ }
+
+ /**
+ * Makes this dialog visible and brings it to the front. If the dialog is
+ * modal and is not already visible, this call will not return until the
+ * dialog is hidden by someone calling hide or dispose. If this is the event
+ * dispatching thread we must ensure that another event thread runs while the
+ * one which invoked this method is blocked.
+ *
+ * @deprecated Use {@link Component#setVisible(boolean)} instead.
+ */
+ public synchronized void show()
+ {
+ super.show();
+
+ if (isModal())
+ {
+ // If already shown (and blocked) just return
+ if (blocked)
+ return;
+
+ /*
+ * If show is called in the dispatch thread for a modal dialog it will
+ * block so we must run another thread so the events keep being
+ * dispatched.
+ */
+ if (EventQueue.isDispatchThread())
+ {
+ EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
+ eq2 = new EventQueue();
+ eq.push(eq2);
+ }
+
+ try
+ {
+ blocked = true;
+ wait();
+ blocked = false;
+ }
+ catch (InterruptedException e)
+ {
+ blocked = false;
+ }
+
+ if (eq2 != null)
+ {
+ eq2.pop();
+ eq2 = null;
+ }
+ }
+ }
+
+ /**
+ * Hides the Dialog and then causes show() to return if it is currently
+ * blocked.
+ *
+ * @deprecated Use {@link Component#setVisible(boolean)} instead.
+ */
+ public synchronized void hide()
+ {
+ if (blocked)
+ {
+ notifyAll();
+ }
+
+ super.hide();
+ }
+
+ /**
+ * Disposes the Dialog and then causes show() to return if it is currently
+ * blocked.
+ */
+ public synchronized void dispose()
+ {
+ if (blocked)
+ {
+ notifyAll();
+ }
+
+ super.dispose();
+ }
+
+ /**
+ * Returns a debugging string for this component.
+ *
+ * @return A debugging string for this component.
+ */
+ protected String paramString()
+ {
+ return "title+" + title + ",modal=" + modal + ",resizable=" + resizable
+ + "," + super.paramString();
+ }
+
+ /**
+ * Returns whether this frame is undecorated or not.
+ *
+ * @return <code>true</code> if this dialog is undecorated,
+ * <code>false</code> otherwise.
+ *
+ * @since 1.4
+ */
+ public boolean isUndecorated()
+ {
+ return undecorated;
+ }
+
+ /**
+ * Disables or enables decorations for this frame. This method can only be
+ * called while the frame is not displayable.
+ *
+ * @param undecorated <code>true</code> to disable dialog decorations,
+ * <code>false</code> otherwise.
+ *
+ * @exception IllegalComponentStateException If this frame is displayable.
+ * @since 1.4
+ */
+ public void setUndecorated(boolean undecorated)
+ {
+ if (isDisplayable())
+ throw new IllegalComponentStateException();
+
+ this.undecorated = undecorated;
+ }
+
+ /**
+ * Accessibility support for <code>Dialog</code>.
+ */
+ protected class AccessibleAWTDialog
+ extends AccessibleAWTWindow
+ {
+ private static final long serialVersionUID = 4837230331833941201L;
+
+ /**
+ * Gets the role of this object.
+ * @return AccessibleRole.DIALOG
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.DIALOG;
+ }
+
+ /**
+ * Gets the state set of this object.
+ * @return The current state of this dialog.
+ */
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ AccessibleStateSet states = super.getAccessibleStateSet();
+ if (isResizable())
+ states.add(AccessibleState.RESIZABLE);
+ if (isModal())
+ states.add(AccessibleState.MODAL);
+ return states;
+ }
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>Dialog</code>. The
+ * context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTDialog();
+ return accessibleContext;
+ }
+
+ /**
+ * Generate a unique name for this <code>Dialog</code>.
+ *
+ * @return A unique name for this <code>Dialog</code>.
+ */
+ String generateName()
+ {
+ return "dialog" + getUniqueLong();
+ }
+
+ private static synchronized long getUniqueLong()
+ {
+ return next_dialog_number++;
+ }
+}
diff --git a/libjava/classpath/java/awt/Dimension.java b/libjava/classpath/java/awt/Dimension.java
new file mode 100644
index 000000000..4c1a07bf9
--- /dev/null
+++ b/libjava/classpath/java/awt/Dimension.java
@@ -0,0 +1,234 @@
+/* Dimension.java -- represents a 2-dimensional span
+ Copyright (C) 1999, 2000, 2002 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.geom.Dimension2D;
+import java.io.Serializable;
+
+/**
+ * This class holds a width and height value pair. This is used in plenty
+ * of windowing classes, but also has geometric meaning.
+ *
+ * <p>It is valid for a dimension to have negative width or height; but it
+ * is considered to have no area. Therefore, the behavior in various methods
+ * is undefined in such a case.
+ *
+ * <p>There are some public fields; if you mess with them in an inconsistent
+ * manner, it is your own fault when you get invalid results. Also, this
+ * class is not threadsafe.
+ *
+ * @author Per Bothner (bothner@cygnus.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Component
+ * @see LayoutManager
+ * @since 1.0
+ * @status updated to 1.14
+ */
+public class Dimension extends Dimension2D implements Serializable
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 4723952579491349524L;
+
+ /**
+ * The width of this object.
+ *
+ * @see #getSize()
+ * @see #setSize(double, double)
+ * @serial the width
+ */
+ public int width;
+
+ /**
+ * The height of this object.
+ *
+ * @see #getSize()
+ * @see #setSize(double, double)
+ * @serial the height
+ */
+ public int height;
+
+ /**
+ * Create a new Dimension with a width and height of zero.
+ */
+ public Dimension()
+ {
+ }
+
+ /**
+ * Create a new Dimension with width and height identical to that of the
+ * specified dimension.
+ *
+ * @param d the Dimension to copy
+ * @throws NullPointerException if d is null
+ */
+ public Dimension(Dimension d)
+ {
+ width = d.width;
+ height = d.height;
+ }
+
+ /**
+ * Create a new Dimension with the specified width and height.
+ *
+ * @param w the width of this object
+ * @param h the height of this object
+ */
+ public Dimension(int w, int h)
+ {
+ width = w;
+ height = h;
+ }
+
+ /**
+ * Gets the width of this dimension.
+ *
+ * @return the width, as a double
+ */
+ public double getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Gets the height of this dimension.
+ *
+ * @return the height, as a double
+ */
+ public double getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * Sets the size of this dimension. The values are rounded to int.
+ *
+ * @param w the new width
+ * @param h the new height
+ * @since 1.2
+ */
+ public void setSize(double w, double h)
+ {
+ width = (int) w;
+ height = (int) h;
+ }
+
+ /**
+ * Returns the size of this dimension. A pretty useless method, as this is
+ * already a dimension.
+ *
+ * @return a copy of this dimension
+ * @see #setSize(Dimension)
+ * @since 1.1
+ */
+ public Dimension getSize()
+ {
+ return new Dimension(width, height);
+ }
+
+ /**
+ * Sets the width and height of this object to match that of the
+ * specified object.
+ *
+ * @param d the Dimension to get the new width and height from
+ * @throws NullPointerException if d is null
+ * @see #getSize()
+ * @since 1.1
+ */
+ public void setSize(Dimension d)
+ {
+ width = d.width;
+ height = d.height;
+ }
+
+ /**
+ * Sets the width and height of this object to the specified values.
+ *
+ * @param w the new width value
+ * @param h the new height value
+ */
+ public void setSize(int w, int h)
+ {
+ width = w;
+ height = h;
+ }
+
+ /**
+ * Tests this object for equality against the specified object. This will
+ * be true if and only if the specified object is an instance of
+ * Dimension2D, and has the same width and height.
+ *
+ * @param obj the object to test against
+ * @return true if the object is equal to this
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof Dimension))
+ return false;
+ Dimension dim = (Dimension) obj;
+ return height == dim.height && width == dim.width;
+ }
+
+ /**
+ * Return the hashcode for this object. It is not documented, but appears
+ * to be <code>((width + height) * (width + height + 1) / 2) + width</code>.
+ *
+ * @return the hashcode
+ */
+ public int hashCode()
+ {
+ // Reverse engineering this was fun!
+ return (width + height) * (width + height + 1) / 2 + width;
+ }
+
+ /**
+ * Returns a string representation of this object. The format is:
+ * <code>getClass().getName() + "[width=" + width + ",height=" + height
+ * + ']'</code>.
+ *
+ * @return a string representation of this object
+ */
+ public String toString()
+ {
+ return getClass().getName()
+ + "[width=" + width + ",height=" + height + ']';
+ }
+} // class Dimension
diff --git a/libjava/classpath/java/awt/DisplayMode.java b/libjava/classpath/java/awt/DisplayMode.java
new file mode 100644
index 000000000..be2a1d118
--- /dev/null
+++ b/libjava/classpath/java/awt/DisplayMode.java
@@ -0,0 +1,164 @@
+/* DisplayMode.java -- a description of display mode configurations
+ Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This encapsulates information about the display mode for a graphics
+ * device configuration. They are device dependent, and may not always be
+ * available.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see GraphicsDevice
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public final class DisplayMode
+{
+ /**
+ * Value of the bit depth if multiple depths are supported.
+ *
+ * @see #getBitDepth()
+ */
+ public static final int BIT_DEPTH_MULTI = -1;
+
+ /**
+ * Value of an unknown refresh rate.
+ *
+ * @see #getRefreshRate()
+ */
+ public static final int REFRESH_RATE_UNKNOWN = 0;
+
+ /** The width. */
+ private final int width;
+
+ /** The height. */
+ private final int height;
+
+ /** The bit depth. */
+ private final int bitDepth;
+
+ /** The refresh rate. */
+ private final int refreshRate;
+
+ /**
+ * Create a mode with the given parameters.
+ *
+ * @param width the width
+ * @param height the height
+ * @param bitDepth the bitDepth
+ * @param refreshRate the refreshRate
+ * @see #BIT_DEPTH_MULTI
+ * @see #REFRESH_RATE_UNKNOWN
+ */
+ public DisplayMode(int width, int height, int bitDepth, int refreshRate)
+ {
+ this.width = width;
+ this.height = height;
+ this.bitDepth = bitDepth;
+ this.refreshRate = refreshRate;
+ }
+
+ /**
+ * Returns the height, in pixels.
+ *
+ * @return the height
+ */
+ public int getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * Returns the width, in pixels.
+ *
+ * @return the width
+ */
+ public int getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Returns the bit depth, in bits per pixel. This may be BIT_DEPTH_MULTI.
+ *
+ * @return the bit depth
+ * @see #BIT_DEPTH_MULTI
+ */
+ public int getBitDepth()
+ {
+ return bitDepth;
+ }
+
+ /**
+ * Returns the refresh rate, in hertz. This may be REFRESH_RATE_UNKNOWN.
+ *
+ * @return the refresh rate
+ * @see #REFRESH_RATE_UNKNOWN
+ */
+ public int getRefreshRate()
+ {
+ return refreshRate;
+ }
+
+ /**
+ * Test for equality. This returns true for two modes with identical
+ * parameters.
+ *
+ * @param dm The display mode to compare to
+ *
+ * @return true if it is equal
+ */
+ public boolean equals (DisplayMode dm)
+ {
+ return (width == dm.width
+ && height == dm.height
+ && bitDepth == dm.bitDepth
+ && refreshRate == dm.refreshRate);
+ }
+
+ /**
+ * Returns a hash code for the display mode.
+ *
+ * @return the hash code
+ */
+ public int hashCode()
+ {
+ return width + height + bitDepth + refreshRate;
+ }
+} // class DisplayMode
diff --git a/libjava/classpath/java/awt/Event.java b/libjava/classpath/java/awt/Event.java
new file mode 100644
index 000000000..f2c98b9b0
--- /dev/null
+++ b/libjava/classpath/java/awt/Event.java
@@ -0,0 +1,185 @@
+/* Copyright (C) 1999, 2000, 2002 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * Written using on-line Java Platform 1.2 API Specification, as well
+ * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
+ * Status: Believed complete and correct.
+ */
+
+public class Event implements java.io.Serializable
+{
+ static final long serialVersionUID = 5488922509400504703L;
+
+ public static final int SHIFT_MASK = 1;
+ public static final int CTRL_MASK = 2;
+ public static final int META_MASK = 4;
+ public static final int ALT_MASK = 8;
+
+ public static final int ACTION_EVENT = 1001;
+ public static final int BACK_SPACE = 8;
+ public static final int CAPS_LOCK = 1022;
+ public static final int DELETE = 127;
+ public static final int DOWN = 1005;
+ public static final int END = 1001;
+ public static final int ENTER = 10;
+ public static final int ESCAPE = 27;
+ public static final int F1 = 1008;
+ public static final int F10 = 1017;
+ public static final int F11 = 1018;
+ public static final int F12 = 1019;
+ public static final int F2 = 1009;
+ public static final int F3 = 1010;
+ public static final int F4 = 1011;
+ public static final int F5 = 1012;
+ public static final int F6 = 1013;
+ public static final int F7 = 1014;
+ public static final int F8 = 1015;
+ public static final int F9 = 1016;
+ public static final int GOT_FOCUS = 1004;
+ public static final int HOME = 1000;
+ public static final int INSERT = 1025;
+ public static final int KEY_ACTION = 403;
+ public static final int KEY_ACTION_RELEASE = 404;
+ public static final int KEY_PRESS = 401;
+ public static final int KEY_RELEASE = 402;
+ public static final int LEFT = 1006;
+ public static final int LIST_DESELECT = 702;
+ public static final int LIST_SELECT = 701;
+ public static final int LOAD_FILE = 1002;
+ public static final int LOST_FOCUS = 1005;
+ public static final int MOUSE_DOWN = 501;
+ public static final int MOUSE_DRAG = 506;
+ public static final int MOUSE_ENTER = 504;
+ public static final int MOUSE_EXIT = 505;
+ public static final int MOUSE_MOVE = 503;
+ public static final int MOUSE_UP = 502;
+ public static final int NUM_LOCK = 1023;
+ public static final int PAUSE = 1024;
+ public static final int PGDN = 1003;
+ public static final int PGUP = 1002;
+ public static final int PRINT_SCREEN = 1020;
+ public static final int RIGHT = 1007;
+ public static final int SAVE_FILE = 1003;
+ public static final int SCROLL_ABSOLUTE = 605;
+ public static final int SCROLL_BEGIN = 606;
+ public static final int SCROLL_END = 607;
+ public static final int SCROLL_LINE_DOWN = 602;
+ public static final int SCROLL_LINE_UP = 601;
+ public static final int SCROLL_LOCK = 1021;
+ public static final int SCROLL_PAGE_DOWN = 604;
+ public static final int SCROLL_PAGE_UP = 603;
+ public static final int TAB = 9;
+ public static final int UP = 1004;
+ public static final int WINDOW_DEICONIFY = 204;
+ public static final int WINDOW_DESTROY = 201;
+ public static final int WINDOW_EXPOSE = 202;
+ public static final int WINDOW_ICONIFY = 203;
+ public static final int WINDOW_MOVED = 205;
+
+ public Object arg;
+ public int clickCount;
+ boolean consumed; // Required by serialization spec.
+ public Event evt;
+ public int id;
+ public int key;
+ public int modifiers;
+ public Object target;
+ public long when;
+ public int x;
+ public int y;
+
+ public Event (Object target, int id, Object arg)
+ {
+ this.id = id;
+ this.target = target;
+ this.arg = arg;
+ }
+
+ public Event (Object target, long when, int id, int x, int y, int key,
+ int modifiers)
+ {
+ this.target = target;
+ this.when = when;
+ this.id = id;
+ this.x = x;
+ this.y = y;
+ this.key = key;
+ this.modifiers = modifiers;
+ }
+
+ public Event (Object target, long when, int id, int x, int y, int key,
+ int modifiers, Object arg)
+ {
+ this (target, when, id, x, y, key, modifiers);
+ this.arg = arg;
+ }
+
+ public boolean controlDown ()
+ {
+ return ((modifiers & CTRL_MASK) == 0 ? false : true);
+ }
+
+ public boolean metaDown ()
+ {
+ return ((modifiers & META_MASK) == 0 ? false : true);
+ }
+
+ protected String paramString ()
+ {
+ return "id=" + id + ",x=" + x + ",y=" + y
+ + ",target=" + target + ",arg=" + arg;
+ }
+
+ public boolean shiftDown()
+ {
+ return ((modifiers & SHIFT_MASK) == 0 ? false : true);
+ }
+
+ public String toString()
+ {
+ return getClass().getName() + "[" + paramString() + "]";
+ }
+
+ public void translate (int x, int y)
+ {
+ this.x += x;
+ this.y += y;
+ }
+}
diff --git a/libjava/classpath/java/awt/EventDispatchThread.java b/libjava/classpath/java/awt/EventDispatchThread.java
new file mode 100644
index 000000000..c2147f4c0
--- /dev/null
+++ b/libjava/classpath/java/awt/EventDispatchThread.java
@@ -0,0 +1,107 @@
+/* EventDispatchThread.java -
+ Copyright (C) 2000, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt;
+
+/**
+ * @author Bryce McKinlay
+ * @status believed complete, but untested.
+ */
+class EventDispatchThread extends Thread
+{
+ /**
+ * The default priority when no property has been set.
+ */
+ private static final int DEFAULT_PRIORITY = NORM_PRIORITY + 1;
+
+ private static int dispatchThreadNum;
+
+ private EventQueue queue;
+
+ EventDispatchThread(EventQueue queue)
+ {
+ super();
+ setName("AWT-EventQueue-" + ++dispatchThreadNum);
+ this.queue = queue;
+
+ int priority = DEFAULT_PRIORITY;
+ try
+ {
+ String priorityString =
+ System.getProperty("gnu.awt.dispatchthread.priority");
+ if (priorityString != null)
+ {
+ priority = Integer.parseInt(priorityString);
+ }
+ }
+ catch (NumberFormatException ex)
+ {
+ // Ignore and use default.
+ }
+ setPriority(priority);
+
+ // Make sure that an event dispatch thread is never a daemon thread.
+ setDaemon(false);
+ }
+
+ public void run()
+ {
+ while (true)
+ {
+ try
+ {
+ AWTEvent evt = queue.getNextEvent();
+ queue.dispatchEvent(evt);
+ }
+ catch (ThreadDeath death)
+ {
+ // If someone wants to kill us, let them.
+ return;
+ }
+ catch (InterruptedException ie)
+ {
+ // We are interrupted when we should finish executing
+ return;
+ }
+ catch (Throwable x)
+ {
+ System.err.println("Exception during event dispatch:");
+ x.printStackTrace(System.err);
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/java/awt/EventQueue.java b/libjava/classpath/java/awt/EventQueue.java
new file mode 100644
index 000000000..cb52ae013
--- /dev/null
+++ b/libjava/classpath/java/awt/EventQueue.java
@@ -0,0 +1,658 @@
+/* EventQueue.java --
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import gnu.java.awt.LowPriorityEvent;
+import gnu.java.awt.peer.NativeEventLoopRunningEvent;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.InputEvent;
+import java.awt.event.InputMethodEvent;
+import java.awt.event.InvocationEvent;
+import java.awt.event.PaintEvent;
+import java.awt.peer.ComponentPeer;
+import java.awt.peer.LightweightPeer;
+import java.lang.reflect.InvocationTargetException;
+import java.util.EmptyStackException;
+
+/* Written using on-line Java 2 Platform Standard Edition v1.3 API
+ * Specification, as well as "The Java Class Libraries", 2nd edition
+ * (Addison-Wesley, 1998).
+ * Status: Believed complete, but untested.
+ */
+
+/**
+ * This class manages a queue of <code>AWTEvent</code> objects that
+ * are posted to it. The AWT system uses only one event queue for all
+ * events.
+ *
+ * @author Bryce McKinlay
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class EventQueue
+{
+ /**
+ * Indicates events that are processed with normal priority. This is normally
+ * all events except PaintEvents.
+ */
+ private static final int NORM_PRIORITY = 0;
+
+ /**
+ * Indicates events that are processed with lowes priority. This is normally
+ * all PaintEvents and LowPriorityEvents.
+ */
+ private static final int LOW_PRIORITY = 1;
+
+ /**
+ * Implements the actual queue. EventQueue has 2 internal queues for
+ * different priorities:
+ * 1 PaintEvents are always dispatched with low priority.
+ * 2. All other events are dispatched with normal priority.
+ *
+ * This makes sure that the actual painting (output) is performed _after_ all
+ * available input has been processed and that the paint regions are
+ * coalesced as much as possible.
+ */
+ private class Queue
+ {
+ /**
+ * The first item in the queue. This is where events are popped from.
+ */
+ AWTEvent queueHead;
+
+ /**
+ * The last item. This is where events are posted to.
+ */
+ AWTEvent queueTail;
+ }
+
+ /**
+ * The three internal event queues.
+ *
+ * @see Queue
+ */
+ private Queue[] queues;
+
+ private EventQueue next;
+ private EventQueue prev;
+ private AWTEvent currentEvent;
+ private long lastWhen = System.currentTimeMillis();
+
+ private EventDispatchThread dispatchThread = new EventDispatchThread(this);
+ private boolean nativeLoopRunning = false;
+
+ private boolean isShutdown ()
+ {
+ // This is the exact self-shutdown condition specified in J2SE:
+ // http://java.sun.com/j2se/1.4.2/docs/api/java/awt/doc-files/AWTThreadIssues.html
+
+ if (nativeLoopRunning)
+ return false;
+
+ if (peekEvent() != null)
+ return false;
+
+ if (Frame.hasDisplayableFrames())
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Initializes a new instance of <code>EventQueue</code>.
+ */
+ public EventQueue()
+ {
+ queues = new Queue[2];
+ queues[NORM_PRIORITY] = new Queue();
+ queues[LOW_PRIORITY] = new Queue();
+ }
+
+ /**
+ * Returns the next event in the queue. This method will block until
+ * an event is available or until the thread is interrupted.
+ *
+ * @return The next event in the queue.
+ *
+ * @exception InterruptedException If this thread is interrupted while
+ * waiting for an event to be posted to the queue.
+ */
+ public synchronized AWTEvent getNextEvent()
+ throws InterruptedException
+ {
+ if (next != null)
+ return next.getNextEvent();
+
+ AWTEvent res = getNextEventImpl(true);
+
+ while (res == null)
+ {
+ if (isShutdown())
+ {
+ // Explicitly set dispathThread to null. If we don't do
+ // this, there is a race condition where dispatchThread
+ // can be != null even after the event dispatch thread has
+ // stopped running. If that happens, then the
+ // dispatchThread == null check in postEventImpl will
+ // fail, and a new event dispatch thread will not be
+ // created, leaving invokeAndWaits waiting indefinitely.
+ dispatchThread = null;
+
+ // Interrupt the event dispatch thread.
+ throw new InterruptedException();
+ }
+
+ wait();
+ res = getNextEventImpl(true);
+ }
+
+ return res;
+ }
+
+ /**
+ * Fetches and possibly removes the next event from the internal queues.
+ * This method returns immediately. When all queues are empty, this returns
+ * <code>null</code>:
+ *
+ * @param remove <true> when the event should be removed from the queue,
+ * <code>false</code> otherwise
+ *
+ * @return the next event or <code>null</code> when all internal queues
+ * are empty
+ */
+ private AWTEvent getNextEventImpl(boolean remove)
+ {
+ AWTEvent next = null;
+ for (int i = 0; i < queues.length && next == null; i++)
+ {
+ Queue q = queues[i];
+ if (q.queueHead != null)
+ {
+ // Got an event, remove it.
+ next = q.queueHead;
+ if (remove)
+ {
+ // Unlink event from the queue.
+ q.queueHead = next.queueNext;
+ if (q.queueHead == null)
+ q.queueTail = null;
+ next.queueNext = null;
+ }
+ }
+ }
+ return next;
+ }
+
+ /**
+ * Returns the next event in the queue without removing it from the queue.
+ * This method will block until an event is available or until the thread
+ * is interrupted.
+ *
+ * @return The next event in the queue.
+ * @specnote Does not block. Returns null if there are no events on the
+ * queue.
+ */
+ public synchronized AWTEvent peekEvent()
+ {
+ if (next != null)
+ return next.peekEvent();
+
+ return getNextEventImpl(false);
+ }
+
+ /**
+ * Returns the next event in the queue that has the specified id
+ * without removing it from the queue.
+ * This method will block until an event is available or until the thread
+ * is interrupted.
+ *
+ * @param id The event id to return.
+ *
+ * @return The next event in the queue.
+ *
+ * @specnote Does not block. Returns null if there are no matching events
+ * on the queue.
+ */
+ public synchronized AWTEvent peekEvent(int id)
+ {
+ if (next != null)
+ return next.peekEvent(id);
+
+ AWTEvent evt = null;
+ for (int i = 0; i < queues.length && evt == null; i++)
+ {
+ Queue q = queues[i];
+ evt = q.queueHead;
+ while (evt != null && evt.id != id)
+ evt = evt.queueNext;
+ // At this point we either have found an event (evt != null -> exit
+ // for loop), or we have found no event (evt == null -> search next
+ // internal queue).
+ }
+ return evt;
+ }
+
+ /**
+ * Posts a new event to the queue.
+ *
+ * @param evt The event to post to the queue.
+ *
+ * @exception NullPointerException If event is null.
+ */
+ public void postEvent(AWTEvent evt)
+ {
+ postEventImpl(evt);
+ }
+
+ /**
+ * Sorts events to their priority and calls
+ * {@link #postEventImpl(AWTEvent, int)}.
+ *
+ * @param evt the event to post
+ */
+ private synchronized final void postEventImpl(AWTEvent evt)
+ {
+ int priority = NORM_PRIORITY;
+ if (evt instanceof PaintEvent || evt instanceof LowPriorityEvent)
+ priority = LOW_PRIORITY;
+ // TODO: Maybe let Swing RepaintManager events also be processed with
+ // low priority.
+ if (evt instanceof NativeEventLoopRunningEvent)
+ {
+ nativeLoopRunning = ((NativeEventLoopRunningEvent) evt).isRunning();
+ notify();
+ return;
+ }
+ postEventImpl(evt, priority);
+ }
+
+ /**
+ * Actually performs the event posting. This is needed because the
+ * RI doesn't use the public postEvent() method when transferring events
+ * between event queues in push() and pop().
+ *
+ * @param evt the event to post
+ * @param priority the priority of the event
+ */
+ private final void postEventImpl(AWTEvent evt, int priority)
+ {
+ if (evt == null)
+ throw new NullPointerException();
+
+ if (next != null)
+ {
+ next.postEvent(evt);
+ return;
+ }
+
+ Object source = evt.getSource();
+
+ Queue q = queues[priority];
+ if (source instanceof Component)
+ {
+ // For PaintEvents, ask the ComponentPeer to coalesce the event
+ // when the component is heavyweight.
+ Component comp = (Component) source;
+ ComponentPeer peer = comp.peer;
+ if (peer != null && evt instanceof PaintEvent
+ && ! (peer instanceof LightweightPeer))
+ peer.coalescePaintEvent((PaintEvent) evt);
+
+ // Check for any events already on the queue with the same source
+ // and ID.
+ AWTEvent previous = null;
+ for (AWTEvent qevt = q.queueHead; qevt != null; qevt = qevt.queueNext)
+ {
+ Object src = qevt.getSource();
+ if (qevt.id == evt.id && src == comp)
+ {
+ // If there are, call coalesceEvents on the source component
+ // to see if they can be combined.
+ Component srccmp = (Component) src;
+ AWTEvent coalescedEvt = srccmp.coalesceEvents(qevt, evt);
+ if (coalescedEvt != null)
+ {
+ // Yes. Replace the existing event with the combined event.
+ if (qevt != coalescedEvt)
+ {
+ if (previous != null)
+ {
+ assert previous.queueNext == qevt;
+ previous.queueNext = coalescedEvt;
+ }
+ else
+ {
+ assert q.queueHead == qevt;
+ q.queueHead = coalescedEvt;
+ }
+ coalescedEvt.queueNext = qevt.queueNext;
+ if (q.queueTail == qevt)
+ q.queueTail = coalescedEvt;
+ qevt.queueNext = null;
+ }
+ return;
+ }
+ }
+ previous = qevt;
+ }
+ }
+
+ if (q.queueHead == null)
+ {
+ // We have an empty queue. Set this event both as head and as tail.
+ q.queueHead = evt;
+ q.queueTail = evt;
+ }
+ else
+ {
+ // Note: queueTail should not be null here.
+ q.queueTail.queueNext = evt;
+ q.queueTail = evt;
+ }
+
+ if (dispatchThread == null || !dispatchThread.isAlive())
+ {
+ dispatchThread = new EventDispatchThread(this);
+ dispatchThread.start();
+ }
+
+ notify();
+ }
+
+ /**
+ * Causes runnable to have its run method called in the dispatch thread of the
+ * EventQueue. This will happen after all pending events are processed. The
+ * call blocks until this has happened. This method will throw an Error if
+ * called from the event dispatcher thread.
+ *
+ * @exception InterruptedException If another thread has interrupted
+ * this thread.
+ * @exception InvocationTargetException If an exception is thrown when running
+ * runnable.
+ *
+ * @since 1.2
+ */
+ public static void invokeAndWait(Runnable runnable)
+ throws InterruptedException, InvocationTargetException
+ {
+ if (isDispatchThread ())
+ throw new Error("Can't call invokeAndWait from event dispatch thread");
+
+ EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
+ Object notifyObject = new Object();
+
+ InvocationEvent ie =
+ new InvocationEvent(eq, runnable, notifyObject, true);
+
+ synchronized (notifyObject)
+ {
+ eq.postEvent(ie);
+ notifyObject.wait();
+ }
+
+ Exception exception;
+
+ if ((exception = ie.getException()) != null)
+ throw new InvocationTargetException(exception);
+ }
+
+ /**
+ * This arranges for runnable to have its run method called in the
+ * dispatch thread of the EventQueue. This will happen after all
+ * pending events are processed.
+ *
+ * @since 1.2
+ */
+ public static void invokeLater(Runnable runnable)
+ {
+ EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
+
+ InvocationEvent ie =
+ new InvocationEvent(eq, runnable, null, false);
+
+ eq.postEvent(ie);
+ }
+
+ /**
+ * Return true if the current thread is the current AWT event dispatch
+ * thread.
+ */
+ public static boolean isDispatchThread()
+ {
+ EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
+
+ /* Find last EventQueue in chain */
+ while (eq.next != null)
+ eq = eq.next;
+
+ return (Thread.currentThread() == eq.dispatchThread);
+ }
+
+ /**
+ * Return the event currently being dispatched by the event
+ * dispatch thread. If the current thread is not the event
+ * dispatch thread, this method returns null.
+ *
+ * @since 1.4
+ */
+ public static AWTEvent getCurrentEvent()
+ {
+ EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
+ Thread ct = Thread.currentThread();
+
+ /* Find out if this thread is the dispatch thread for any of the
+ EventQueues in the chain */
+ while (ct != eq.dispatchThread)
+ {
+ // Try next EventQueue, if any
+ if (eq.next == null)
+ return null; // Not an event dispatch thread
+ eq = eq.next;
+ }
+
+ return eq.currentEvent;
+ }
+
+ /**
+ * Allows a custom EventQueue implementation to replace this one.
+ * All pending events are transferred to the new queue. Calls to postEvent,
+ * getNextEvent, and peekEvent and others are forwarded to the pushed queue
+ * until it is removed with a pop().
+ *
+ * @exception NullPointerException if newEventQueue is null.
+ */
+ public synchronized void push(EventQueue newEventQueue)
+ {
+ if (newEventQueue == null)
+ throw new NullPointerException ();
+
+ /* Make sure we are at the top of the stack because callers can
+ only get a reference to the one at the bottom using
+ Toolkit.getDefaultToolkit().getSystemEventQueue() */
+ if (next != null)
+ {
+ next.push (newEventQueue);
+ return;
+ }
+
+ /* Make sure we have a live dispatch thread to drive the queue */
+ if (dispatchThread == null)
+ dispatchThread = new EventDispatchThread(this);
+
+ synchronized (newEventQueue)
+ {
+ // The RI transfers the events without calling the new eventqueue's
+ // push(), but using getNextEvent().
+ while (peekEvent() != null)
+ {
+ try
+ {
+ newEventQueue.postEventImpl(getNextEvent());
+ }
+ catch (InterruptedException ex)
+ {
+ // What should we do with this?
+ ex.printStackTrace();
+ }
+ }
+ newEventQueue.prev = this;
+ }
+
+ next = newEventQueue;
+ }
+
+ /** Transfer any pending events from this queue back to the parent queue that
+ * was previously push()ed. Event dispatch from this queue is suspended.
+ *
+ * @exception EmptyStackException If no previous push was made on this
+ * EventQueue.
+ */
+ protected void pop() throws EmptyStackException
+ {
+ /* The order is important here, we must get the prev lock first,
+ or deadlock could occur as callers usually get here following
+ prev's next pointer, and thus obtain prev's lock before trying
+ to get this lock. */
+ EventQueue previous = prev;
+ if (previous == null)
+ throw new EmptyStackException();
+ synchronized (previous)
+ {
+ synchronized (this)
+ {
+ EventQueue nextQueue = next;
+ if (nextQueue != null)
+ {
+ nextQueue.pop();
+ }
+ else
+ {
+ previous.next = null;
+
+ // The RI transfers the events without calling the new eventqueue's
+ // push(), so this should be OK and most effective.
+ while (peekEvent() != null)
+ {
+ try
+ {
+ previous.postEventImpl(getNextEvent());
+ }
+ catch (InterruptedException ex)
+ {
+ // What should we do with this?
+ ex.printStackTrace();
+ }
+ }
+ prev = null;
+ // Tell our EventDispatchThread that it can end
+ // execution.
+ if (dispatchThread != null)
+ {
+ dispatchThread.interrupt();
+ dispatchThread = null;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Dispatches an event. The manner in which the event is dispatched depends
+ * upon the type of the event and the type of the event's source object.
+ *
+ * @exception NullPointerException If event is null.
+ */
+ protected void dispatchEvent(AWTEvent evt)
+ {
+ currentEvent = evt;
+
+ if (evt instanceof InputEvent)
+ lastWhen = ((InputEvent) evt).getWhen();
+ else if (evt instanceof ActionEvent)
+ lastWhen = ((ActionEvent) evt).getWhen();
+ else if (evt instanceof InvocationEvent)
+ lastWhen = ((InvocationEvent) evt).getWhen();
+
+ if (evt instanceof ActiveEvent)
+ {
+ ActiveEvent active_evt = (ActiveEvent) evt;
+ active_evt.dispatch();
+ }
+ else
+ {
+ Object source = evt.getSource();
+
+ if (source instanceof Component)
+ {
+ Component srccmp = (Component) source;
+ srccmp.dispatchEvent(evt);
+ }
+ else if (source instanceof MenuComponent)
+ {
+ MenuComponent srccmp = (MenuComponent) source;
+ srccmp.dispatchEvent(evt);
+ }
+ }
+ }
+
+ /**
+ * Returns the timestamp of the most recent event that had a timestamp, or
+ * the initialization time of the event queue if no events have been fired.
+ * At present, only <code>InputEvent</code>s, <code>ActionEvent</code>s,
+ * <code>InputMethodEvent</code>s, and <code>InvocationEvent</code>s have
+ * timestamps, but this may be added to other events in future versions.
+ * If this is called by the event dispatching thread, it can be any
+ * (sequential) value, but to other threads, the safest bet is to return
+ * System.currentTimeMillis().
+ *
+ * @return the most recent timestamp
+ * @see InputEvent#getWhen()
+ * @see ActionEvent#getWhen()
+ * @see InvocationEvent#getWhen()
+ * @see InputMethodEvent#getWhen()
+ * @since 1.4
+ */
+ public static long getMostRecentEventTime()
+ {
+ EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
+ if (Thread.currentThread() != eq.dispatchThread)
+ return System.currentTimeMillis();
+ return eq.lastWhen;
+ }
+}
diff --git a/libjava/classpath/java/awt/FileDialog.java b/libjava/classpath/java/awt/FileDialog.java
new file mode 100644
index 000000000..c1bd08264
--- /dev/null
+++ b/libjava/classpath/java/awt/FileDialog.java
@@ -0,0 +1,395 @@
+/* FileDialog.java -- A filename selection dialog box
+ Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.peer.FileDialogPeer;
+import java.io.FilenameFilter;
+import java.io.Serializable;
+
+/**
+ * This class implements a file selection dialog box widget.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@redhat.com)
+ */
+public class FileDialog extends Dialog implements Serializable
+{
+
+/*
+ * Static Variables
+ */
+
+/**
+ * Indicates that the purpose of the dialog is for opening a file.
+ */
+public static final int LOAD = 0;
+
+/**
+ * Indicates that the purpose of the dialog is for saving a file.
+ */
+public static final int SAVE = 1;
+
+// Serialization constant
+private static final long serialVersionUID = 5035145889651310422L;
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * @serial The directory for this file dialog.
+ */
+private String dir;
+
+/**
+ * @serial The filename for this file dialog
+ */
+private String file;
+
+/**
+ * @serial The filter for selecting filenames to display
+ */
+private FilenameFilter filter;
+
+/**
+ * @serial The mode of this dialog, either <code>LOAD</code> or
+ * <code>SAVE</code>.
+ */
+private int mode;
+
+/**
+ * The number used to generate the name returned by getName.
+ */
+private static transient long next_file_dialog_number;
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+ /**
+ * Initializes a new instance of <code>FileDialog</code> with the specified
+ * parent. This dialog will have no title and will be for loading a file.
+ *
+ * @param parent The parent dialog for this.
+ *
+ * @since 1.5
+ */
+ public FileDialog(Dialog parent)
+ {
+ this(parent, "", LOAD);
+ }
+
+ /**
+ * Initialized a new instance of <code>FileDialog</code> with the
+ * specified parent and title. This dialog will be for opening a file.
+ *
+ * @param parent The parent dialog for this.
+ * @param title The title for this dialog.
+ *
+ * @since 1.5
+ */
+ public FileDialog(Dialog parent, String title)
+ {
+ this(parent, title, LOAD);
+ }
+
+ /**
+ * Initialized a new instance of <code>FileDialog</code> with the specified
+ * parent, title, and mode.
+ *
+ * @param parent The parent dialog for this.
+ * @param title The title for this dialog.
+ * @param mode The mode of the dialog, either <code>LOAD</code> or
+ * <code>SAVE</code>.
+ * @throws IllegalArgumentException - if illegal mode, if
+ * GraphicsEnvironment.isHeadless or if parent is null.
+ *
+ * @since 1.5
+ */
+ public FileDialog(Dialog parent, String title, int mode)
+ {
+ super(parent, title, true);
+
+ // Other IllegalArgumentException cases are taken care of in Window.java
+ if (mode != LOAD && mode != SAVE)
+ throw new IllegalArgumentException (
+ "Mode argument must be either LOAD or SAVE");
+
+ setMode(mode);
+ }
+
+/**
+ * Initializes a new instance of <code>FileDialog</code> with the
+ * specified parent. This dialog will have no title and will be for
+ * loading a file.
+ *
+ * @param parent The parent frame for this dialog.
+ */
+public
+FileDialog(Frame parent)
+{
+ this(parent, "", LOAD);
+}
+
+/*************************************************************************/
+
+/**
+ * Initialized a new instance of <code>FileDialog</code> with the
+ * specified parent and title. This dialog will be for opening a file.
+ *
+ * @param parent The parent frame for this dialog.
+ * @param title The title for this dialog.
+ */
+public
+FileDialog(Frame parent, String title)
+{
+ this(parent, title, LOAD);
+}
+
+/*************************************************************************/
+
+/**
+ * Initialized a new instance of <code>FileDialog</code> with the
+ * specified parent, title, and mode.
+ *
+ * @param parent The parent frame for this dialog.
+ * @param title The title for this dialog.
+ * @param mode The mode of the dialog, either <code>LOAD</code> or
+ * <code>SAVE</code>.
+ *
+ * @exception IllegalArgumentException If an illegal file dialog mode
+ * is supplied.
+ */
+public
+FileDialog(Frame parent, String title, int mode)
+{
+ super(parent, title, true);
+
+ if ((mode != LOAD) && (mode != SAVE))
+ throw new IllegalArgumentException (
+ "Mode argument must be either LOAD or SAVE");
+
+ setMode (mode);
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Methods
+ */
+
+/**
+ * Returns the mode of this dialog, either <code>LOAD</code> or
+ * <code>SAVE</code>.
+ *
+ * @return The mode of this dialog.
+ */
+public int
+getMode()
+{
+ return(mode);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the mode of this dialog to either <code>LOAD</code> or
+ * <code>SAVE</code>. This method is only effective before the native
+ * peer is created.
+ *
+ * @param mode The new mode of this file dialog.
+ *
+ * @exception IllegalArgumentException If an illegal file dialog mode
+ * is supplied.
+ */
+public void
+setMode(int mode)
+{
+ if ((mode != LOAD) && (mode != SAVE))
+ throw new IllegalArgumentException("Bad mode: " + mode);
+
+ this.mode = mode;
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the directory for this file dialog.
+ *
+ * @return The directory for this file dialog.
+ */
+public String
+getDirectory()
+{
+ return(dir);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the directory for this file dialog.
+ *
+ * @param dir The new directory for this file dialog.
+ */
+public synchronized void
+setDirectory(String dir)
+{
+ this.dir = dir;
+ if (peer != null)
+ {
+ FileDialogPeer f = (FileDialogPeer) peer;
+ f.setDirectory (dir);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the file that is selected in this dialog.
+ *
+ * @return The file that is selected in this dialog.
+ */
+public String
+getFile()
+{
+ return(file);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the selected file for this dialog.
+ *
+ * @param file The selected file for this dialog.
+ */
+public synchronized void
+setFile(String file)
+{
+ if ("".equals(file))
+ this.file = null;
+ else
+ this.file = file;
+
+ if (peer != null)
+ {
+ FileDialogPeer f = (FileDialogPeer) peer;
+ f.setFile (file);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the filename filter being used by this dialog.
+ *
+ * @return The filename filter being used by this dialog.
+ */
+public FilenameFilter
+getFilenameFilter()
+{
+ return(filter);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the filename filter used by this dialog.
+ *
+ * @param filter The new filename filter for this file dialog box.
+ */
+public synchronized void
+setFilenameFilter(FilenameFilter filter)
+{
+ this.filter = filter;
+ if (peer != null)
+ {
+ FileDialogPeer f = (FileDialogPeer) peer;
+ f.setFilenameFilter (filter);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Creates the native peer for this file dialog box.
+ */
+public void
+addNotify()
+{
+ if (peer == null)
+ peer = getToolkit ().createFileDialog (this);
+ super.addNotify ();
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a debugging string for this object.
+ *
+ * @return A debugging string for this object.
+ */
+protected String
+paramString()
+{
+ return ("dir=" + dir + ",file=" + file +
+ ",mode=" + mode + "," + super.paramString());
+}
+
+/**
+ * Generate a unique name for this <code>FileDialog</code>.
+ *
+ * @return A unique name for this <code>FileDialog</code>.
+ */
+String
+generateName()
+{
+ return "filedlg" + getUniqueLong();
+}
+
+private static synchronized long
+getUniqueLong()
+{
+ return next_file_dialog_number++;
+}
+
+} // class FileDialog
diff --git a/libjava/classpath/java/awt/FlowLayout.java b/libjava/classpath/java/awt/FlowLayout.java
new file mode 100644
index 000000000..231d041b1
--- /dev/null
+++ b/libjava/classpath/java/awt/FlowLayout.java
@@ -0,0 +1,365 @@
+/* FlowLayout.java -- Grid-based layout engine
+ Copyright (C) 1999, 2000, 2001, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.io.Serializable;
+
+/** This class implements a flow-based layout. Components are laid
+ * out in order from left to right. When a component cannot be placed
+ * without horizontal clipping, a new row is started. This class
+ * supports horizontal and vertical gaps. These are used for spacing
+ * between components.
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class FlowLayout implements LayoutManager, Serializable
+{
+ /** Constant that specifies left alignment. */
+ public static final int LEFT = 0;
+ /** Constant that specifies center alignment. */
+ public static final int CENTER = 1;
+ /** Constant that specifies right alignment. */
+ public static final int RIGHT = 2;
+
+ /** Constant that specifies alignment to leading edge of container's
+ * orientation. */
+ public static final int LEADING = 3;
+ /** Constant that specifies alignment to trailing edge of container's
+ * orientation. */
+ public static final int TRAILING = 4;
+
+ // Serialization constant
+ private static final long serialVersionUID = -7262534875583282631L;
+
+ /**
+ * Add a new component to the layout. This particular implementation
+ * does nothing.
+ *
+ * @param name the name
+ * @param comp the component
+ */
+ public void addLayoutComponent (String name, Component comp)
+ {
+ // Nothing.
+ }
+
+ /**
+ * Returns the current justification value for this object.
+ *
+ * @return The current justification value for this object.
+ */
+ public int getAlignment ()
+ {
+ return align;
+ }
+
+ /**
+ * Returns the horizontal gap between components.
+ *
+ * @return The horizontal gap between components.
+ */
+ public int getHgap ()
+ {
+ return hgap;
+ }
+
+ /**
+ * Returns the vertical gap between lines of components.
+ *
+ * @return The vertical gap between lines of components.
+ */
+ public int getVgap ()
+ {
+ return vgap;
+ }
+
+ /**
+ * Initializes a new instance of <code>FlowLayout</code> with a center
+ * justification and a default horizontal and vertical gap of 5.
+ */
+ public FlowLayout ()
+ {
+ this (CENTER, 5, 5);
+ }
+
+ /**
+ * Initializes a new instance of <code>FlowLayout</code> with the specified
+ * justification and a default horizontal and vertical gap of 5.
+ *
+ * @param align The justification setting, which should be one of the
+ * contants in this class.
+ */
+ public FlowLayout (int align)
+ {
+ this (align, 5, 5);
+ }
+
+ /**
+ * Initializes a new instance of <code>FlowLayout</code> with the specified
+ * justification and gap values
+ * @param align Alignment
+ * @param hgap The horizontal gap
+ * @param vgap The vertical gap
+ * @exception IllegalArgumentException If either gap is negative
+ */
+ public FlowLayout (int align, int hgap, int vgap)
+ {
+ // Use methods to set fields so that we can have all the checking
+ // in one place.
+ setVgap (vgap);
+ setHgap (hgap);
+ setAlignment (align);
+ }
+
+ /** Lay out the container's components based on current settings.
+ * @param parent The parent container
+ */
+ public void layoutContainer (Container parent)
+ {
+ synchronized (parent.getTreeLock ())
+ {
+ int num = parent.getComponentCount ();
+ // This is more efficient than calling getComponents().
+ Component[] comps = parent.component;
+
+ Dimension d = parent.getSize ();
+ Insets ins = parent.getInsets ();
+
+ ComponentOrientation orient = parent.getComponentOrientation ();
+ boolean left_to_right = orient.isLeftToRight ();
+
+ int y = ins.top + vgap;
+ int i = 0;
+ while (i < num)
+ {
+ // Find the components which go in the current row.
+ int new_w = ins.left + hgap + ins.right;
+ int new_h = 0;
+ int j;
+ boolean found_one = false;
+ for (j = i; j < num; ++j)
+ {
+ // Skip invisible items.
+ if (! comps[j].visible)
+ continue;
+
+ Dimension c = comps[j].getPreferredSize ();
+
+ int next_w = new_w + hgap + c.width;
+ if (next_w <= d.width || ! found_one)
+ {
+ new_w = next_w;
+ new_h = Math.max (new_h, c.height);
+ found_one = true;
+ }
+ else
+ {
+ // Must start a new row, and we already found an item
+ break;
+ }
+ }
+
+ // Set the location of each component for this row.
+ int x;
+
+ int myalign = align;
+ if (align == LEADING)
+ myalign = left_to_right ? LEFT : RIGHT;
+ else if (align == TRAILING)
+ myalign = left_to_right ? RIGHT : LEFT;
+
+ if (myalign == RIGHT)
+ x = ins.left + (d.width - new_w) + hgap;
+ else if (myalign == CENTER)
+ x = ins.left + (d.width - new_w) / 2 + hgap;
+ else // LEFT and all other values of align.
+ x = ins.left + hgap;
+
+ for (int k = i; k < j; ++k)
+ {
+ if (comps[k].visible)
+ {
+ Dimension c = comps[k].getPreferredSize ();
+ comps[k].setBounds (x, y + (new_h - c.height) / 2,
+ c.width, c.height);
+ x += c.width + hgap;
+ }
+ }
+
+ // Advance to next row.
+ i = j;
+ y += new_h + vgap;
+ }
+ }
+ }
+
+ /**
+ * Returns the minimum layout size for the specified container using
+ * this layout.
+ * @param cont The parent container
+ * @return The minimum layout size.
+ */
+ public Dimension minimumLayoutSize (Container cont)
+ {
+ return getSize (cont, true);
+ }
+
+ /**
+ * Returns the preferred layout size for the specified container using
+ * this layout.
+ * @param cont The parent container
+ * @return The preferred layout size.
+ */
+ public Dimension preferredLayoutSize (Container cont)
+ {
+ return getSize (cont, false);
+ }
+
+ /** Remove the indicated component from this layout manager.
+ * This particular implementation does nothing.
+ * @param comp The component to remove
+ */
+ public void removeLayoutComponent (Component comp)
+ {
+ // Nothing.
+ }
+
+ /**
+ * Sets the justification value for this object to the specified value.
+ *
+ * @param align The new justification value for this object, which must
+ * be one of the constants in this class.
+ */
+ public void setAlignment (int align)
+ {
+ // The JDK accepts invalid values and treats them as
+ // LEFT during layout, so do we. The invalid value is even stored,
+ // getAlignment() returns the same invalid value.
+ this.align = align;
+ }
+
+ /**
+ * Sets the horizontal gap between lines of components to the specified value.
+ * No Exception is thrown if hgap < 0.
+ *
+ * @param hgap The new horizontal gap between components.
+ */
+ public void setHgap (int hgap)
+ {
+ this.hgap = hgap;
+ }
+
+ /**
+ * Sets the vertical gap between lines of components to the specified value.
+ * No Exception is thrown if vgap < 0.
+ *
+ * @param vgap The new vertical gap.
+ */
+ public void setVgap (int vgap)
+ {
+ this.vgap = vgap;
+ }
+
+ /** Return String description of this object.
+ * @return A string representation of this object.
+ */
+ public String toString ()
+ {
+ return ("[" + getClass ().getName () + ",hgap=" + hgap + ",vgap=" + vgap
+ + ",align=" + align + "]");
+ }
+
+ // This method is used to compute the various sizes.
+ private Dimension getSize (Container parent, boolean is_min)
+ {
+ synchronized (parent.getTreeLock ())
+ {
+ int w, h, num = parent.getComponentCount ();
+ // This is more efficient than calling getComponents().
+ Component[] comps = parent.component;
+
+ w = 0;
+ h = 0;
+ for (int i = 0; i < num; ++i)
+ {
+ if (! comps[i].visible)
+ continue;
+
+ // FIXME: can we just directly read the fields in Component?
+ // Or will that not work with subclassing?
+ Dimension d;
+
+ if (is_min)
+ d = comps[i].getMinimumSize ();
+ else
+ d = comps[i].getPreferredSize ();
+
+ w += d.width;
+ h = Math.max (d.height, h);
+ }
+
+ Insets ins = parent.getInsets ();
+
+ if (num == 0)
+ w += 2 * hgap + ins.left + ins.right;
+ else
+ w += (num + 1) * hgap + ins.left + ins.right;
+ h += 2 * vgap + ins.top + ins.bottom;
+
+ return new Dimension (w, h);
+ }
+ }
+
+ /**
+ * @serial The justification alignment of the lines of components, which
+ * will be one of the constants defined in this class.
+ */
+ private int align;
+
+ /**
+ * @serial The horizontal gap between components.
+ */
+ private int hgap;
+
+ /**
+ * @serial The vertical gap between lines of components.
+ */
+ private int vgap;
+}
diff --git a/libjava/classpath/java/awt/FocusTraversalPolicy.java b/libjava/classpath/java/awt/FocusTraversalPolicy.java
new file mode 100644
index 000000000..d9374eae8
--- /dev/null
+++ b/libjava/classpath/java/awt/FocusTraversalPolicy.java
@@ -0,0 +1,103 @@
+/* FocusTraversalPolicy.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * @since 1.4
+ */
+public abstract class FocusTraversalPolicy
+{
+ /**
+ * Creates a <code>FocusTraversalPolicy</code> object.
+ */
+ public FocusTraversalPolicy()
+ {
+ // Do nothing in here.
+ }
+
+ /**
+ * Returns the Component that should receive the focus after a Component.
+ *
+ * @exception IllegalArgumentException If root or current is null,
+ * or if root is not a focus cycle root of current.
+ */
+ public abstract Component getComponentAfter(Container root,
+ Component current);
+
+ /**
+ * Returns the Component that should receive the focus before a Component.
+ *
+ * @exception IllegalArgumentException If root or current is null,
+ * or if root is not a focus cycle root of current.
+ */
+ public abstract Component getComponentBefore(Container root,
+ Component current);
+
+ /**
+ * Returns the first Component in the traversal cycle.
+ *
+ * @exception IllegalArgumentException If root is null.
+ */
+ public abstract Component getFirstComponent(Container root);
+
+ /**
+ * Returns the last Component in the traversal cycle.
+ *
+ * @exception IllegalArgumentException If root is null.
+ */
+ public abstract Component getLastComponent(Container root);
+
+ /**
+ * Returns the default Component to focus.
+ *
+ * @exception IllegalArgumentException If root is null.
+ */
+ public abstract Component getDefaultComponent(Container root);
+
+ /**
+ * Returns the Component that should receive the focus when a Window is made
+ * visible for the first time.
+ *
+ * @exception IllegalArgumentException If window is null.
+ */
+ public Component getInitialComponent(Window window)
+ {
+ return getDefaultComponent(window);
+ }
+} // class FocusTraversalPolicy
diff --git a/libjava/classpath/java/awt/Font.java b/libjava/classpath/java/awt/Font.java
new file mode 100644
index 000000000..89ff1f52a
--- /dev/null
+++ b/libjava/classpath/java/awt/Font.java
@@ -0,0 +1,1451 @@
+/* Font.java -- Font object
+ Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import gnu.java.awt.ClasspathToolkit;
+import gnu.java.awt.peer.ClasspathFontPeer;
+
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.font.LineMetrics;
+import java.awt.font.TextAttribute;
+import java.awt.font.TextLayout;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.peer.FontPeer;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.text.AttributedCharacterIterator;
+import java.text.CharacterIterator;
+import java.text.StringCharacterIterator;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+/**
+ * This class represents a windowing system font.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Graydon Hoare (graydon@redhat.com)
+ */
+public class Font implements Serializable
+{
+
+ /**
+ * Constant indicating a "plain" font.
+ */
+ public static final int PLAIN = 0;
+
+ /**
+ * Constant indicating a "bold" font.
+ */
+ public static final int BOLD = 1;
+
+ /**
+ * Constant indicating an "italic" font.
+ */
+ public static final int ITALIC = 2;
+
+ /**
+ * Constant indicating the baseline mode characteristic of Roman.
+ */
+ public static final int ROMAN_BASELINE = 0;
+
+ /**
+ * Constant indicating the baseline mode characteristic of Chinese.
+ */
+ public static final int CENTER_BASELINE = 1;
+
+ /**
+ * Constant indicating the baseline mode characteristic of Devanigri.
+ */
+ public static final int HANGING_BASELINE = 2;
+
+
+ /**
+ * Indicates to <code>createFont</code> that the supplied font data
+ * is in TrueType format.
+ *
+ * <p><em>Specification Note:</em> The Sun JavaDoc for J2SE 1.4 does
+ * not indicate whether this value also subsumes OpenType. OpenType
+ * is essentially the same format as TrueType, but allows to define
+ * glyph shapes in the same way as PostScript, using cubic bezier
+ * curves.
+ *
+ * @since 1.3
+ */
+ public static final int TRUETYPE_FONT = 0;
+
+ /**
+ * Indicates to <code>createFont</code> that the supplied font data
+ * is in Type1 format.
+ *
+ * @since 1.5
+ */
+ public static final int TYPE1_FONT = 1;
+
+ /**
+ * A flag for <code>layoutGlyphVector</code>, indicating that the
+ * orientation of a text run is from left to right.
+ *
+ * @since 1.4
+ */
+ public static final int LAYOUT_LEFT_TO_RIGHT = 0;
+
+
+ /**
+ * A flag for <code>layoutGlyphVector</code>, indicating that the
+ * orientation of a text run is from right to left.
+ *
+ * @since 1.4
+ */
+ public static final int LAYOUT_RIGHT_TO_LEFT = 1;
+
+
+ /**
+ * A flag for <code>layoutGlyphVector</code>, indicating that the
+ * text does not contain valid characters before the
+ * <code>start</code> position. If this flag is set,
+ * <code>layoutGlyphVector</code> does not examine the text before
+ * <code>start</code>, even if this would be necessary to select the
+ * correct glyphs (e.g., for Arabic text).
+ *
+ * @since 1.4
+ */
+ public static final int LAYOUT_NO_START_CONTEXT = 2;
+
+
+ /**
+ * A flag for <code>layoutGlyphVector</code>, indicating that the
+ * text does not contain valid characters after the
+ * <code>limit</code> position. If this flag is set,
+ * <code>layoutGlyphVector</code> does not examine the text after
+ * <code>limit</code>, even if this would be necessary to select the
+ * correct glyphs (e.g., for Arabic text).
+ *
+ * @since 1.4
+ */
+ public static final int LAYOUT_NO_LIMIT_CONTEXT = 4;
+
+ /**
+ * @since 1.6
+ */
+ public static final String DIALOG = "Dialog";
+
+ /**
+ * @since 1.6
+ */
+ public static final String DIALOG_INPUT = "DialogInput";
+
+ /**
+ * @since 1.6
+ */
+ public static final String MONOSPACED = "Monospaced";
+
+ /**
+ * @since 1.6
+ */
+ public static final String SANS_SERIF = "SansSerif";
+
+ /**
+ * @since 1.6
+ */
+ public static final String SERIF = "Serif";
+
+ /**
+ * The logical name of this font.
+ *
+ * @since 1.0
+ */
+ protected String name;
+
+ /**
+ * The size of this font in points, rounded.
+ *
+ * @since 1.0
+ */
+ protected int size;
+
+ /**
+ * The size of this font in points.
+ *
+ * @since 1.0
+ */
+ protected float pointSize;
+
+ /**
+ * The style of this font -- PLAIN, BOLD, ITALIC or BOLD+ITALIC.
+ *
+ * @since 1.0
+ */
+ protected int style;
+
+//Serialization constant
+ private static final long serialVersionUID = -4206021311591459213L;
+
+
+ // The ClasspathToolkit-provided peer which implements this font
+ private transient ClasspathFontPeer peer;
+
+ /**
+ * The cached hashcode. A value of 0 (default initialized) means that the
+ * hashcode is not computed yet.
+ */
+ private transient int hashCode;
+
+ /**
+ * Creates a <code>Font</code> object from the specified string, which
+ * is in one of the following formats:
+ * <p>
+ * <ul>
+ * <li>fontname-style-pointsize
+ * <li>fontname-style
+ * <li>fontname-pointsize
+ * <li>fontname
+ * </ul>
+ * <p>
+ * The style should be one of BOLD, ITALIC, or BOLDITALIC. The default
+ * style if none is specified is PLAIN. The default size if none
+ * is specified is 12.
+ *
+ * @param fontspec a string specifying the required font (<code>null</code>
+ * permitted, interpreted as 'Dialog-PLAIN-12').
+ *
+ * @return A font.
+ */
+ public static Font decode(String fontspec)
+ {
+ if (fontspec == null)
+ fontspec = "Dialog-PLAIN-12";
+ String name = null;
+ int style = PLAIN;
+ int size = 12;
+
+ StringTokenizer st = new StringTokenizer(fontspec, "- ");
+ while (st.hasMoreTokens())
+ {
+ String token = st.nextToken();
+ if (name == null)
+ {
+ name = token;
+ continue;
+ }
+
+ if (token.toUpperCase().equals("BOLD"))
+ {
+ style = BOLD;
+ continue;
+ }
+ if (token.toUpperCase().equals("ITALIC"))
+ {
+ style = ITALIC;
+ continue;
+ }
+ if (token.toUpperCase().equals("BOLDITALIC"))
+ {
+ style = BOLD | ITALIC;
+ continue;
+ }
+
+ int tokenval = 0;
+ try
+ {
+ tokenval = Integer.parseInt(token);
+ }
+ catch (NumberFormatException e)
+ {
+ // Ignored.
+ }
+
+ if (tokenval != 0)
+ size = tokenval;
+ }
+
+ HashMap attrs = new HashMap();
+ ClasspathFontPeer.copyStyleToAttrs(style, attrs);
+ ClasspathFontPeer.copySizeToAttrs(size, attrs);
+
+ return getFontFromToolkit(name, attrs);
+ }
+
+ /* These methods delegate to the toolkit. */
+
+ static ClasspathToolkit tk()
+ {
+ return (ClasspathToolkit) Toolkit.getDefaultToolkit();
+ }
+
+ /* Every factory method in Font should eventually call this. */
+ static Font getFontFromToolkit(String name, Map attribs)
+ {
+ return tk().getFont(name, attribs);
+ }
+
+ /* Every Font constructor should eventually call this. */
+ static ClasspathFontPeer getPeerFromToolkit(String name, Map attrs)
+ {
+ return tk().getClasspathFontPeer(name, attrs);
+ }
+
+
+ /**
+ * Returns a <code>Font</code> object from the passed property name.
+ *
+ * @param propname The name of the system property.
+ * @param defval Value to use if the property is not found.
+ *
+ * @return The requested font, or <code>default</code> if the property
+ * not exist or is malformed.
+ */
+ public static Font getFont(String propname, Font defval)
+ {
+ String propval = System.getProperty(propname);
+ if (propval != null)
+ return decode(propval);
+ return defval;
+ }
+
+ /**
+ * Returns a <code>Font</code> object from the passed property name.
+ *
+ * @param propname The name of the system property.
+ *
+ * @return The requested font, or <code>null</code> if the property
+ * not exist or is malformed.
+ */
+ public static Font getFont(String propname)
+ {
+ return getFont(propname, (Font) null);
+ }
+
+ protected Font(Font font)
+ {
+ this(font.getName(), font.getAttributes());
+ }
+
+ /**
+ * Initializes a new instance of <code>Font</code> with the specified
+ * attributes.
+ *
+ * @param name The name of the font.
+ * @param style The font style.
+ * @param size The font point size.
+ */
+ public Font(String name, int style, int size)
+ {
+ HashMap attrs = new HashMap();
+ ClasspathFontPeer.copyStyleToAttrs(style, attrs);
+ ClasspathFontPeer.copySizeToAttrs(size, attrs);
+ this.peer = getPeerFromToolkit(name, attrs);
+ this.size = size;
+ this.pointSize = (float) size;
+ if (name != null)
+ this.name = name;
+ else
+ this.name = peer.getName(this);
+ }
+
+ public Font(Map<? extends AttributedCharacterIterator.Attribute, ?> attrs)
+ {
+ this(null, attrs);
+ }
+
+ /* This extra constructor is here to permit ClasspathToolkit and to
+ build a font with a "logical name" as well as attrs.
+ ClasspathToolkit.getFont(String,Map) uses reflection to call this
+ package-private constructor. */
+ Font(String name, Map attrs)
+ {
+ // If attrs is null, setting it to an empty HashMap will give this
+ // Font default attributes.
+ if (attrs == null)
+ attrs = new HashMap();
+ peer = getPeerFromToolkit(name, attrs);
+ size = (int) peer.getSize(this);
+ pointSize = peer.getSize(this);
+ if (name != null)
+ this.name = name;
+ else
+ this.name = peer.getName(this);
+ }
+
+ /**
+ * Returns the logical name of the font. A logical name is the name the
+ * font was constructed with. It may be the name of a logical font (one
+ * of 6 required names in all java environments) or it may be a face
+ * name.
+ *
+ * @return The logical name of the font.
+ *
+ * @see #getFamily()
+ * @see #getFontName()
+ */
+ public String getName ()
+ {
+ return peer.getName(this);
+ }
+
+ /**
+ * Returns the size of the font, in typographics points (1/72 of an inch),
+ * rounded to an integer.
+ *
+ * @return The font size
+ */
+ public int getSize()
+ {
+ return size;
+ }
+
+ /**
+ * Returns the size of the font, in typographics points (1/72 of an inch).
+ *
+ * @return The font size
+ */
+ public float getSize2D()
+ {
+ return pointSize;
+ }
+
+ /**
+ * Tests whether or not this is a plain font. This will be true if
+ * and only if neither the bold nor the italics style is set.
+ *
+ * @return <code>true</code> if this is a plain font, <code>false</code>
+ * otherwise.
+ */
+ public boolean isPlain()
+ {
+ return peer.isPlain(this);
+ }
+
+ /**
+ * Tests whether or not this font is bold.
+ *
+ * @return <code>true</code> if this font is bold, <code>false</code>
+ * otherwise.
+ */
+ public boolean isBold()
+ {
+ return peer.isBold(this);
+ }
+
+ /**
+ * Tests whether or not this font is italic.
+ *
+ * @return <code>true</code> if this font is italic, <code>false</code>
+ * otherwise.
+ */
+ public boolean isItalic()
+ {
+ return peer.isItalic(this);
+ }
+
+ /**
+ * Returns the family name of this font. A family name describes a design
+ * or "brand name" (such as Helvetica or Palatino). It is less specific
+ * than a font face name (such as Helvetica Bold).
+ *
+ * @return A string containing the font family name.
+ *
+ * @since 1.2
+ *
+ * @see #getName()
+ * @see #getFontName()
+ * @see GraphicsEnvironment#getAvailableFontFamilyNames()
+ */
+ public String getFamily()
+ {
+ return peer.getFamily(this);
+ }
+
+ /**
+ * Returns integer code representing the sum of style flags of this font, a
+ * combination of either {@link #PLAIN}, {@link #BOLD}, or {@link #ITALIC}.
+ *
+ * @return code representing the style of this font.
+ *
+ * @see #isPlain()
+ * @see #isBold()
+ * @see #isItalic()
+ */
+ public int getStyle()
+ {
+ return peer.getStyle(this);
+ }
+
+ /**
+ * Checks if specified character maps to a glyph in this font.
+ *
+ * @param c The character to check.
+ *
+ * @return Whether the character has a corresponding glyph in this font.
+ *
+ * @since 1.2
+ */
+ public boolean canDisplay(char c)
+ {
+ return canDisplay((int) c);
+ }
+
+ public boolean canDisplay(int codePoint)
+ {
+ return peer.canDisplay(this, codePoint);
+ }
+
+ /**
+ * Checks how much of a given string can be mapped to glyphs in
+ * this font.
+ *
+ * @param s The string to check.
+ *
+ * @return The index of the first character in <code>s</code> which cannot
+ * be converted to a glyph by this font, or <code>-1</code> if all
+ * characters can be mapped to glyphs.
+ *
+ * @since 1.2
+ */
+ public int canDisplayUpTo(String s)
+ {
+ return peer.canDisplayUpTo(this, new StringCharacterIterator(s),
+ 0, s.length() - 1);
+ }
+
+ /**
+ * Checks how much of a given sequence of text can be mapped to glyphs in
+ * this font.
+ *
+ * @param text Array containing the text to check.
+ * @param start Position of first character to check in <code>text</code>.
+ * @param limit Position of last character to check in <code>text</code>.
+ *
+ * @return The index of the first character in the indicated range which
+ * cannot be converted to a glyph by this font, or <code>-1</code> if all
+ * characters can be mapped to glyphs.
+ *
+ * @since 1.2
+ *
+ * @throws IndexOutOfBoundsException if the range [start, limit] is
+ * invalid in <code>text</code>.
+ */
+ public int canDisplayUpTo (char[] text, int start, int limit)
+ {
+ return peer.canDisplayUpTo(this,
+ new StringCharacterIterator(new String (text)),
+ start, limit);
+ }
+
+ /**
+ * Checks how much of a given sequence of text can be mapped to glyphs in
+ * this font.
+ *
+ * @param i Iterator over the text to check.
+ * @param start Position of first character to check in <code>i</code>.
+ * @param limit Position of last character to check in <code>i</code>.
+ *
+ * @return The index of the first character in the indicated range which
+ * cannot be converted to a glyph by this font, or <code>-1</code> if all
+ * characters can be mapped to glyphs.
+ *
+ * @since 1.2
+ *
+ * @throws IndexOutOfBoundsException if the range [start, limit] is
+ * invalid in <code>i</code>.
+ */
+ public int canDisplayUpTo(CharacterIterator i, int start, int limit)
+ {
+ return peer.canDisplayUpTo(this, i, start, limit);
+ }
+
+ /**
+ * Creates a new font with point size 1 and {@link #PLAIN} style,
+ * reading font data from the provided input stream. The resulting font
+ * can have further fonts derived from it using its
+ * <code>deriveFont</code> method.
+ *
+ * @param fontFormat Integer code indicating the format the font data is
+ * in.Currently this can only be {@link #TRUETYPE_FONT}.
+ * @param is {@link InputStream} from which font data will be read. This
+ * stream is not closed after font data is extracted.
+ *
+ * @return A new {@link Font} of the format indicated.
+ *
+ * @throws IllegalArgumentException if <code>fontType</code> is not
+ * recognized.
+ * @throws FontFormatException if data in InputStream is not of format
+ * indicated.
+ * @throws IOException if insufficient data is present on InputStream.
+ *
+ * @since 1.3
+ */
+ public static Font createFont (int fontFormat, InputStream is)
+ throws FontFormatException, IOException
+ {
+ return tk().createFont(fontFormat, is);
+ }
+
+ /**
+ * Creates a new font from a File object.
+ *
+ * @see #layoutGlyphVector(FontRenderContext, char[], int, int, int)
+ *
+ * @param fontFormat - Integer code indicating the format the font data is
+ * in.Currently this can only be {@link #TRUETYPE_FONT}.
+ * @param file - a {@link File} from which font data will be read.
+ *
+ * @return A new {@link Font} of the format indicated.
+ *
+ * @throws IllegalArgumentException if <code>fontType</code> is not
+ * recognized.
+ * @throws NullPointerException if <code>file</code> is <code>null</code>.
+ * @throws FontFormatException if data in the file is invalid or cannot be read..
+ * @throws SecurityException if the caller has no read permission for the file.
+ * @throws IOException if the file cannot be read
+ *
+ * @since 1.5
+ */
+ public static Font createFont (int fontFormat, File file)
+ throws FontFormatException, IOException
+ {
+ if( file == null )
+ throw new NullPointerException("Null file argument");
+ return tk().createFont(fontFormat, new FileInputStream( file ));
+ }
+
+ /**
+ * Maps characters to glyphs in a one-to-one relationship, returning a new
+ * {@link GlyphVector} with a mapped glyph for each input character. This
+ * sort of mapping is often sufficient for some scripts such as Roman, but
+ * is inappropriate for scripts with special shaping or contextual layout
+ * requirements such as Arabic, Indic, Hebrew or Thai.
+ *
+ * @param ctx The rendering context used for precise glyph placement.
+ * @param str The string to convert to Glyphs.
+ *
+ * @return A new {@link GlyphVector} containing glyphs mapped from str,
+ * through the font's cmap table.
+ *
+ * @see #layoutGlyphVector(FontRenderContext, char[], int, int, int)
+ */
+ public GlyphVector createGlyphVector(FontRenderContext ctx, String str)
+ {
+ return peer.createGlyphVector(this, ctx, new StringCharacterIterator(str));
+ }
+
+ /**
+ * Maps characters to glyphs in a one-to-one relationship, returning a new
+ * {@link GlyphVector} with a mapped glyph for each input character. This
+ * sort of mapping is often sufficient for some scripts such as Roman, but
+ * is inappropriate for scripts with special shaping or contextual layout
+ * requirements such as Arabic, Indic, Hebrew or Thai.
+ *
+ * @param ctx The rendering context used for precise glyph placement.
+ * @param i Iterator over the text to convert to glyphs.
+ *
+ * @return A new {@link GlyphVector} containing glyphs mapped from str,
+ * through the font's cmap table.
+ *
+ * @see #layoutGlyphVector(FontRenderContext, char[], int, int, int)
+ */
+ public GlyphVector createGlyphVector(FontRenderContext ctx,
+ CharacterIterator i)
+ {
+ return peer.createGlyphVector(this, ctx, i);
+ }
+
+ /**
+ * Maps characters to glyphs in a one-to-one relationship, returning a new
+ * {@link GlyphVector} with a mapped glyph for each input character. This
+ * sort of mapping is often sufficient for some scripts such as Roman, but
+ * is inappropriate for scripts with special shaping or contextual layout
+ * requirements such as Arabic, Indic, Hebrew or Thai.
+ *
+ * @param ctx The rendering context used for precise glyph placement.
+ * @param chars Array of characters to convert to glyphs.
+ *
+ * @return A new {@link GlyphVector} containing glyphs mapped from str,
+ * through the font's cmap table.
+ *
+ * @see #layoutGlyphVector(FontRenderContext, char[], int, int, int)
+ */
+ public GlyphVector createGlyphVector(FontRenderContext ctx, char[] chars)
+ {
+ return peer.createGlyphVector(this, ctx,
+ new StringCharacterIterator(new String(chars)));
+ }
+
+ /**
+ * Extracts a sequence of glyphs from a font, returning a new {@link
+ * GlyphVector} with a mapped glyph for each input glyph code.
+ *
+ * @param ctx The rendering context used for precise glyph placement.
+ * @param glyphCodes Array of characters to convert to glyphs.
+ *
+ * @return A new {@link GlyphVector} containing glyphs mapped from str,
+ * through the font's cmap table.
+ *
+ * @see #layoutGlyphVector(FontRenderContext, char[], int, int, int)
+ *
+ * @specnote This method is documented to perform character-to-glyph
+ * conversions, in the Sun documentation, but its second parameter name is
+ * "glyphCodes" and it is not clear to me why it would exist if its
+ * purpose was to transport character codes inside integers. I assume it
+ * is mis-documented in the Sun documentation.
+ */
+ public GlyphVector createGlyphVector(FontRenderContext ctx, int[] glyphCodes)
+ {
+ return peer.createGlyphVector(this, ctx, glyphCodes);
+ }
+
+ /**
+ * Produces a new {@link Font} based on the current font, adjusted to a
+ * new size and style.
+ *
+ * @param style The style of the newly created font.
+ * @param size The size of the newly created font.
+ *
+ * @return A clone of the current font, with the specified size and style.
+ *
+ * @since 1.2
+ */
+ public Font deriveFont(int style, float size)
+ {
+ return peer.deriveFont(this, style, size);
+ }
+
+ /**
+ * Produces a new {@link Font} based on the current font, adjusted to a
+ * new size.
+ *
+ * @param size The size of the newly created font.
+ *
+ * @return A clone of the current font, with the specified size.
+ *
+ * @since 1.2
+ */
+ public Font deriveFont(float size)
+ {
+ return peer.deriveFont(this, size);
+ }
+
+ /**
+ * Produces a new {@link Font} based on the current font, adjusted to a
+ * new style.
+ *
+ * @param style The style of the newly created font.
+ *
+ * @return A clone of the current font, with the specified style.
+ *
+ * @since 1.2
+ */
+ public Font deriveFont(int style)
+ {
+ return peer.deriveFont(this, style);
+ }
+
+ /**
+ * Produces a new {@link Font} based on the current font, adjusted to a
+ * new style and subjected to a new affine transformation.
+ *
+ * @param style The style of the newly created font.
+ * @param a The transformation to apply.
+ *
+ * @return A clone of the current font, with the specified style and
+ * transform.
+ *
+ * @throws IllegalArgumentException If transformation is
+ * <code>null</code>.
+ *
+ * @since 1.2
+ */
+ public Font deriveFont(int style, AffineTransform a)
+ {
+ if (a == null)
+ throw new IllegalArgumentException("Affine transformation is null");
+
+ return peer.deriveFont(this, style, a);
+ }
+
+ /**
+ * Produces a new {@link Font} based on the current font, subjected
+ * to a new affine transformation.
+ *
+ * @param a The transformation to apply.
+ *
+ * @return A clone of the current font, with the specified transform.
+ *
+ * @throws IllegalArgumentException If transformation is
+ * <code>null</code>.
+ *
+ * @since 1.2
+ */
+ public Font deriveFont(AffineTransform a)
+ {
+ if (a == null)
+ throw new IllegalArgumentException("Affine transformation is null");
+
+ return peer.deriveFont(this, a);
+ }
+
+ /**
+ * Produces a new {@link Font} based on the current font, adjusted to a
+ * new set of attributes.
+ *
+ * @param attributes Attributes of the newly created font.
+ *
+ * @return A clone of the current font, with the specified attributes.
+ *
+ * @since 1.2
+ */
+ public Font deriveFont(Map<? extends AttributedCharacterIterator.Attribute, ?> attributes)
+ {
+ return peer.deriveFont(this, attributes);
+ }
+
+ /**
+ * Returns a map of chracter attributes which this font currently has set.
+ *
+ * @return A map of chracter attributes which this font currently has set.
+ *
+ * @see #getAvailableAttributes()
+ * @see java.text.AttributedCharacterIterator.Attribute
+ * @see java.awt.font.TextAttribute
+ */
+ public Map<TextAttribute, ?> getAttributes()
+ {
+ return peer.getAttributes(this);
+ }
+
+ /**
+ * Returns an array of chracter attribute keys which this font understands.
+ *
+ * @return An array of chracter attribute keys which this font understands.
+ *
+ * @see #getAttributes()
+ * @see java.text.AttributedCharacterIterator.Attribute
+ * @see java.awt.font.TextAttribute
+ */
+ public AttributedCharacterIterator.Attribute[] getAvailableAttributes()
+ {
+ return peer.getAvailableAttributes(this);
+ }
+
+ /**
+ * Returns a baseline code (one of {@link #ROMAN_BASELINE}, {@link
+ * #CENTER_BASELINE} or {@link #HANGING_BASELINE}) indicating which baseline
+ * this font will measure baseline offsets for, when presenting glyph
+ * metrics for a given character.
+ *
+ * Baseline offsets describe the position of a glyph relative to an
+ * invisible line drawn under, through the center of, or over a line of
+ * rendered text, respectively. Different scripts use different baseline
+ * modes, so clients should not assume all baseline offsets in a glyph
+ * vector are from a common baseline.
+ *
+ * @param c The character code to select a baseline mode for.
+ *
+ * @return The baseline mode which would be used in a glyph associated
+ * with the provided character.
+ *
+ * @since 1.2
+ *
+ * @see LineMetrics#getBaselineOffsets()
+ */
+ public byte getBaselineFor(char c)
+ {
+ return peer.getBaselineFor(this, c);
+ }
+
+ /**
+ * Returns the family name of this font. A family name describes a
+ * typographic style (such as Helvetica or Palatino). It is more specific
+ * than a logical font name (such as Sans Serif) but less specific than a
+ * font face name (such as Helvetica Bold).
+ *
+ * @param lc The locale in which to describe the name of the font family.
+ *
+ * @return A string containing the font family name, localized for the
+ * provided locale.
+ *
+ * @since 1.2
+ *
+ * @see #getName()
+ * @see #getFontName()
+ * @see GraphicsEnvironment#getAvailableFontFamilyNames()
+ * @see Locale
+ */
+ public String getFamily(Locale lc)
+ {
+ return peer.getFamily(this, lc);
+ }
+
+ /**
+ * Returns a font appropriate for the given attribute set.
+ *
+ * @param attributes The attributes required for the new font.
+ *
+ * @return A new Font with the given attributes.
+ *
+ * @since 1.2
+ *
+ * @see java.awt.font.TextAttribute
+ */
+ public static Font getFont(Map<? extends AttributedCharacterIterator.Attribute, ?> attributes)
+ {
+ return getFontFromToolkit(null, attributes);
+ }
+
+ /**
+ * Returns the font face name of the font. A font face name describes a
+ * specific variant of a font family (such as Helvetica Bold). It is more
+ * specific than both a font family name (such as Helvetica) and a logical
+ * font name (such as Sans Serif).
+ *
+ * @return The font face name of the font.
+ *
+ * @since 1.2
+ *
+ * @see #getName()
+ * @see #getFamily()
+ */
+ public String getFontName()
+ {
+ return peer.getFontName(this);
+ }
+
+ /**
+ * Returns the font face name of the font. A font face name describes a
+ * specific variant of a font family (such as Helvetica Bold). It is more
+ * specific than both a font family name (such as Helvetica).
+ *
+ * @param lc The locale in which to describe the name of the font face.
+ *
+ * @return A string containing the font face name, localized for the
+ * provided locale.
+ *
+ * @since 1.2
+ *
+ * @see #getName()
+ * @see #getFamily()
+ */
+ public String getFontName(Locale lc)
+ {
+ return peer.getFontName(this, lc);
+ }
+
+ /**
+ * Returns the italic angle of this font, a measurement of its slant when
+ * style is {@link #ITALIC}. The precise meaning is the inverse slope of a
+ * caret line which "best measures" the font's italic posture.
+ *
+ * @return The italic angle.
+ *
+ * @see java.awt.font.TextAttribute#POSTURE
+ */
+ public float getItalicAngle()
+ {
+ return peer.getItalicAngle(this);
+ }
+
+ /**
+ * Returns a {@link LineMetrics} object constructed with the specified
+ * text and {@link FontRenderContext}.
+ *
+ * @param text The string to calculate metrics from.
+ * @param begin Index of first character in <code>text</code> to measure.
+ * @param limit Index of last character in <code>text</code> to measure.
+ * @param rc Context for calculating precise glyph placement and hints.
+ *
+ * @return A new {@link LineMetrics} object.
+ *
+ * @throws IndexOutOfBoundsException if the range [begin, limit] is
+ * invalid in <code>text</code>.
+ */
+ public LineMetrics getLineMetrics(String text, int begin,
+ int limit, FontRenderContext rc)
+ {
+ return peer.getLineMetrics(this, new StringCharacterIterator(text),
+ begin, limit, rc);
+ }
+
+ /**
+ * Returns a {@link LineMetrics} object constructed with the specified
+ * text and {@link FontRenderContext}.
+ *
+ * @param chars The string to calculate metrics from.
+ * @param begin Index of first character in <code>text</code> to measure.
+ * @param limit Index of last character in <code>text</code> to measure.
+ * @param rc Context for calculating precise glyph placement and hints.
+ *
+ * @return A new {@link LineMetrics} object.
+ *
+ * @throws IndexOutOfBoundsException if the range [begin, limit] is
+ * invalid in <code>chars</code>.
+ */
+ public LineMetrics getLineMetrics(char[] chars, int begin,
+ int limit, FontRenderContext rc)
+ {
+ return peer.getLineMetrics(this,
+ new StringCharacterIterator(new String(chars)),
+ begin, limit, rc);
+ }
+
+ /**
+ * Returns a {@link LineMetrics} object constructed with the specified
+ * text and {@link FontRenderContext}.
+ *
+ * @param ci The string to calculate metrics from.
+ * @param begin Index of first character in <code>text</code> to measure.
+ * @param limit Index of last character in <code>text</code> to measure.
+ * @param rc Context for calculating precise glyph placement and hints.
+ *
+ * @return A new {@link LineMetrics} object.
+ *
+ * @throws IndexOutOfBoundsException if the range [begin, limit] is
+ * invalid in <code>ci</code>.
+ */
+ public LineMetrics getLineMetrics(CharacterIterator ci, int begin,
+ int limit, FontRenderContext rc)
+ {
+ return peer.getLineMetrics(this, ci, begin, limit, rc);
+ }
+
+ /**
+ * Returns the maximal bounding box of all the bounding boxes in this
+ * font, when the font's bounding boxes are evaluated in a given {@link
+ * FontRenderContext}
+ *
+ * @param rc Context in which to evaluate bounding boxes.
+ *
+ * @return The maximal bounding box.
+ */
+ public Rectangle2D getMaxCharBounds(FontRenderContext rc)
+ {
+ return peer.getMaxCharBounds(this, rc);
+ }
+
+ /**
+ * Returns the glyph code this font uses to represent missing glyphs. This
+ * code will be present in glyph vectors when the font was unable to
+ * locate a glyph to represent a particular character code.
+ *
+ * @return The missing glyph code.
+ *
+ * @since 1.2
+ */
+ public int getMissingGlyphCode()
+ {
+ return peer.getMissingGlyphCode(this);
+ }
+
+ /**
+ * Returns the overall number of glyphs in this font. This number is one
+ * more than the greatest glyph code used in any glyph vectors this font
+ * produces. In other words, glyph codes are taken from the range
+ * <code>[ 0, getNumGlyphs() - 1 ]</code>.
+ *
+ * @return The number of glyphs in this font.
+ *
+ * @since 1.2
+ */
+ public int getNumGlyphs()
+ {
+ return peer.getNumGlyphs(this);
+ }
+
+ /**
+ * Returns the PostScript Name of this font.
+ *
+ * @return The PostScript Name of this font.
+ *
+ * @since 1.2
+ *
+ * @see #getName()
+ * @see #getFamily()
+ * @see #getFontName()
+ */
+ public String getPSName()
+ {
+ return peer.getPostScriptName(this);
+ }
+
+ /**
+ * Returns the logical bounds of the specified string when rendered with this
+ * font in the specified {@link FontRenderContext}. This box will include the
+ * glyph origin, ascent, advance, height, and leading, but may not include all
+ * diacritics or accents. To get the complete visual bounding box of all the
+ * glyphs in a run of text, use the {@link TextLayout#getBounds} method of
+ * {@link TextLayout}.
+ *
+ * @param str The string to measure.
+ * @param frc The context in which to make the precise glyph measurements.
+ *
+ * @return A bounding box covering the logical bounds of the specified text.
+ *
+ * @see #createGlyphVector(FontRenderContext, String)
+ */
+ public Rectangle2D getStringBounds(String str, FontRenderContext frc)
+ {
+ char[] chars = str.toCharArray();
+ return getStringBounds(chars, 0, chars.length, frc);
+ }
+
+ /**
+ * Returns the logical bounds of the specified string when rendered with this
+ * font in the specified {@link FontRenderContext}. This box will include the
+ * glyph origin, ascent, advance, height, and leading, but may not include all
+ * diacritics or accents. To get the complete visual bounding box of all the
+ * glyphs in a run of text, use the {@link TextLayout#getBounds} method of
+ * {@link TextLayout}.
+ *
+ * @param str The string to measure.
+ * @param begin Index of the first character in <code>str</code> to measure.
+ * @param limit Index of the last character in <code>str</code> to measure.
+ * @param frc The context in which to make the precise glyph measurements.
+ *
+ * @return A bounding box covering the logical bounds of the specified text.
+ *
+ * @throws IndexOutOfBoundsException if the range [begin, limit] is
+ * invalid in <code>str</code>.
+ *
+ * @since 1.2
+ *
+ * @see #createGlyphVector(FontRenderContext, String)
+ */
+ public Rectangle2D getStringBounds(String str, int begin,
+ int limit, FontRenderContext frc)
+ {
+ String sub = str.substring(begin, limit);
+ return getStringBounds(sub, frc);
+ }
+
+ /**
+ * Returns the logical bounds of the specified string when rendered with this
+ * font in the specified {@link FontRenderContext}. This box will include the
+ * glyph origin, ascent, advance, height, and leading, but may not include all
+ * diacritics or accents. To get the complete visual bounding box of all the
+ * glyphs in a run of text, use the {@link TextLayout#getBounds} method of
+ * {@link TextLayout}.
+ *
+ * @param ci The text to measure.
+ * @param begin Index of the first character in <code>ci</code> to measure.
+ * @param limit Index of the last character in <code>ci</code> to measure.
+ * @param frc The context in which to make the precise glyph measurements.
+ *
+ * @return A bounding box covering the logical bounds of the specified text.
+ *
+ * @throws IndexOutOfBoundsException if the range [begin, limit] is
+ * invalid in <code>ci</code>.
+ *
+ * @since 1.2
+ *
+ * @see #createGlyphVector(FontRenderContext, CharacterIterator)
+ */
+ public Rectangle2D getStringBounds(CharacterIterator ci, int begin,
+ int limit, FontRenderContext frc)
+ {
+ int start = ci.getBeginIndex();
+ int end = ci.getEndIndex();
+ char[] chars = new char[limit - start];
+ ci.setIndex(start);
+ for (int index = 0; index < chars.length; index++)
+ {
+ chars[index] = ci.current();
+ ci.next();
+ }
+ return getStringBounds(chars, 0, chars.length, frc);
+ }
+
+ /**
+ * Returns the logical bounds of the specified string when rendered with this
+ * font in the specified {@link FontRenderContext}. This box will include the
+ * glyph origin, ascent, advance, height, and leading, but may not include all
+ * diacritics or accents. To get the complete visual bounding box of all the
+ * glyphs in a run of text, use the {@link TextLayout#getBounds} method of
+ * {@link TextLayout}.
+ *
+ * @param chars The text to measure.
+ * @param begin Index of the first character in <code>ci</code> to measure.
+ * @param limit Index of the last character in <code>ci</code> to measure.
+ * @param frc The context in which to make the precise glyph measurements.
+ *
+ * @return A bounding box covering the logical bounds of the specified text.
+ *
+ * @throws IndexOutOfBoundsException if the range [begin, limit] is
+ * invalid in <code>chars</code>.
+ *
+ * @since 1.2
+ *
+ * @see #createGlyphVector(FontRenderContext, char[])
+ */
+ public Rectangle2D getStringBounds(char[] chars, int begin,
+ int limit, FontRenderContext frc)
+ {
+ String str = new String(chars, begin, limit - begin);
+ TextLayout layout = new TextLayout(str, this, frc);
+ return new Rectangle2D.Float(0, -layout.getAscent(), layout.getAdvance(),
+ layout.getDescent() + layout.getLeading());
+ }
+
+ /**
+ * Returns a copy of the affine transformation this font is currently
+ * subject to, if any.
+ *
+ * @return The current transformation.
+ */
+ public AffineTransform getTransform()
+ {
+ return peer.getTransform(this);
+ }
+
+ /**
+ * Indicates whether this font's line metrics are uniform. A font may be
+ * composed of several "subfonts", each covering a different code range,
+ * and each with their own line metrics. A font with no subfonts, or
+ * subfonts with identical line metrics, is said to have "uniform" line
+ * metrics.
+ *
+ * @return Whether this font has uniform line metrics.
+ *
+ * @see LineMetrics
+ * @see #getLineMetrics(String, FontRenderContext)
+ */
+ public boolean hasUniformLineMetrics()
+ {
+ return peer.hasUniformLineMetrics(this);
+ }
+
+ /**
+ * Indicates whether this font is subject to a non-identity affine
+ * transformation.
+ *
+ * @return <code>true</code> iff the font has a non-identity affine
+ * transformation applied to it.
+ */
+ public boolean isTransformed()
+ {
+ return peer.isTransformed(this);
+ }
+
+ /**
+ * Produces a glyph vector representing a full layout fo the specified
+ * text in this font. Full layouts may include complex shaping and
+ * reordering operations, for scripts such as Arabic or Hindi.
+ *
+ * Bidirectional (bidi) layout is not performed in this method; text
+ * should have its bidi direction specified with one of the flags {@link
+ * #LAYOUT_LEFT_TO_RIGHT} or {@link #LAYOUT_RIGHT_TO_LEFT}.
+ *
+ * Some types of layout (notably Arabic glyph shaping) may examine context
+ * characters beyond the bounds of the indicated range, in order to select
+ * an appropriate shape. The flags {@link #LAYOUT_NO_START_CONTEXT} and
+ * {@link #LAYOUT_NO_LIMIT_CONTEXT} can be provided to prevent these extra
+ * context areas from being examined, for instance if they contain invalid
+ * characters.
+ *
+ * @param frc Context in which to perform the layout.
+ * @param chars Text to perform layout on.
+ * @param start Index of first character to perform layout on.
+ * @param limit Index of last character to perform layout on.
+ * @param flags Combination of flags controlling layout.
+ *
+ * @return A new {@link GlyphVector} representing the specified text.
+ *
+ * @throws IndexOutOfBoundsException if the range [begin, limit] is
+ * invalid in <code>chars</code>.
+ */
+ public GlyphVector layoutGlyphVector(FontRenderContext frc,
+ char[] chars, int start,
+ int limit, int flags)
+ {
+ return peer.layoutGlyphVector(this, frc, chars, start, limit, flags);
+ }
+
+
+ /**
+ * Returns a native peer object for this font.
+ *
+ * @return A native peer object for this font.
+ *
+ * @deprecated
+ */
+ public FontPeer getPeer()
+ {
+ return peer;
+ }
+
+
+ /**
+ * Returns a hash value for this font.
+ *
+ * @return A hash for this font.
+ */
+ public int hashCode()
+ {
+ // We cache the hashcode. This makes sense, because the font wouldn't
+ // change the relevant properties.
+ if (hashCode == 0)
+ {
+ hashCode = getName().hashCode() ^ getTransform().hashCode() ^ getSize()
+ ^ getStyle();
+ // In the rare case when the above yields 0, we set this to some other
+ // value to avoid recomputing over and over again. This is still
+ // conform to the specification of hashCode().
+ if (hashCode == 0)
+ {
+ hashCode = -1;
+ }
+ }
+ return hashCode;
+ }
+
+
+ /**
+ * Tests whether or not the specified object is equal to this font. This
+ * will be true if and only if:
+ * <P>
+ * <ul>
+ * <li>The object is not <code>null</code>.
+ * <li>The object is an instance of <code>Font</code>.
+ * <li>The object has the same names, style, size, and transform as this object.
+ * </ul>
+ *
+ * @return <code>true</code> if the specified object is equal to this
+ * object, <code>false</code> otherwise.
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ return false;
+
+ if (! (obj instanceof Font))
+ return false;
+
+ Font f = (Font) obj;
+
+ return (f.getName().equals(this.getName())
+ && f.getFamily().equals(this.getFamily())
+ && f.getFontName().equals(this.getFontName())
+ && f.getTransform().equals(this.getTransform ())
+ && f.getSize() == this.getSize()
+ && f.getStyle() == this.getStyle());
+ }
+
+ /**
+ * Returns a string representation of this font.
+ *
+ * @return A string representation of this font.
+ */
+ public String toString()
+ {
+ String styleString = "";
+
+ switch (getStyle())
+ {
+ case 0:
+ styleString = "plain";
+ break;
+ case 1:
+ styleString = "bold";
+ break;
+ case 2:
+ styleString = "italic";
+ break;
+ default:
+ styleString = "unknown";
+ }
+
+ return getClass().getName()
+ + "[family=" + getFamily ()
+ + ",name=" + getFontName ()
+ + ",style=" + styleString
+ + ",size=" + getSize () + "]";
+ }
+
+
+ /**
+ * Determines the line metrics for a run of text.
+ *
+ * @param str the text run to be measured.
+ *
+ * @param frc the font rendering parameters that are used for the
+ * measurement. The exact placement and size of text slightly
+ * depends on device-specific characteristics, for instance
+ * the device resolution or anti-aliasing. For this reason,
+ * the returned measurement will only be accurate if the
+ * passed <code>FontRenderContext</code> correctly reflects
+ * the relevant parameters. Hence, <code>frc</code> should be
+ * obtained from the same <code>Graphics2D</code> that will
+ * be used for drawing, and any rendering hints should be set
+ * to the desired values before obtaining <code>frc</code>.
+ *
+ * @see java.awt.Graphics2D#getFontRenderContext()
+ */
+ public LineMetrics getLineMetrics(String str, FontRenderContext frc)
+ {
+ return getLineMetrics(str, 0, str.length() - 1, frc);
+ }
+
+ public boolean hasLayoutAttributes()
+ {
+ // TODO: Implement properly.
+ return false;
+ }
+
+ /**
+ * Reads the normal fields from the stream and then constructs the
+ * peer from the style and size through getPeerFromToolkit().
+ */
+ private void readObject(ObjectInputStream ois)
+ throws IOException, ClassNotFoundException
+ {
+ ois.defaultReadObject();
+
+ HashMap attrs = new HashMap();
+ ClasspathFontPeer.copyStyleToAttrs(style, attrs);
+ ClasspathFontPeer.copySizeToAttrs(size, attrs);
+ peer = getPeerFromToolkit(name, attrs);
+
+ }
+}
diff --git a/libjava/classpath/java/awt/FontFormatException.java b/libjava/classpath/java/awt/FontFormatException.java
new file mode 100644
index 000000000..6ec8757fb
--- /dev/null
+++ b/libjava/classpath/java/awt/FontFormatException.java
@@ -0,0 +1,65 @@
+/* FontFormatException.java -- the specified font is bad
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * Thrown when a specified font is bad.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Font
+ * @since 1.3
+ * @status updated to 1.4
+ */
+public class FontFormatException extends Exception
+{
+ /**
+ * Compatible with JDK 1.4+.
+ */
+ private static final long serialVersionUID = -4481290147811361272L;
+
+ /**
+ * Create a new instance with the specified detailed error message.
+ *
+ * @param message the detailed error message
+ */
+ public FontFormatException(String message)
+ {
+ super(message);
+ }
+} // class FontFormatException
diff --git a/libjava/classpath/java/awt/FontMetrics.java b/libjava/classpath/java/awt/FontMetrics.java
new file mode 100644
index 000000000..e483d28fc
--- /dev/null
+++ b/libjava/classpath/java/awt/FontMetrics.java
@@ -0,0 +1,448 @@
+/* FontMetrics.java -- Information about about a fonts display characteristics
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.font.FontRenderContext;
+import java.awt.font.LineMetrics;
+import java.awt.geom.Rectangle2D;
+import java.text.CharacterIterator;
+
+// FIXME: I leave many methods basically unimplemented. This
+// should be reviewed.
+
+/**
+ * This class returns information about the display characteristics of
+ * a font. It is abstract, and concrete subclasses should implement at
+ * least the following methods:
+ *
+ * <ul>
+ * <li>getAscent()</li>
+ * <li>getDescent()</li>
+ * <li>getLeading()</li>
+ * <li>getMaxAdvance()</li>
+ * <li>charWidth(char)</li>
+ * <li>charsWidth(char[], int, int)</li>
+ * </ul>
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public abstract class FontMetrics implements java.io.Serializable
+{
+ // Serialization constant.
+ private static final long serialVersionUID = 1681126225205050147L;
+
+ /**
+ * This is the font for which metrics will be returned.
+ */
+ protected Font font;
+
+ /**
+ * Initializes a new instance of <code>FontMetrics</code> for the
+ * specified font.
+ *
+ * @param font The font to return metric information for.
+ */
+ protected FontMetrics(Font font)
+ {
+ this.font = font;
+ }
+
+ /**
+ * Returns the font that this object is creating metric information fo.
+ *
+ * @return The font for this object.
+ */
+ public Font getFont()
+ {
+ return font;
+ }
+
+ /**
+ * Returns the leading, or spacing between lines, for this font.
+ *
+ * @return The font leading.
+ */
+ public int getLeading()
+ {
+ return 0;
+ }
+
+ /**
+ * Returns the ascent of the font, which is the distance from the base
+ * to the top of the majority of characters in the set. Some characters
+ * can exceed this value however.
+ *
+ * @return The font ascent.
+ */
+ public int getAscent()
+ {
+ return 1;
+ }
+
+ /**
+ * Returns the descent of the font, which is the distance from the base
+ * to the bottom of the majority of characters in the set. Some characters
+ * can exceed this value however.
+ *
+ * @return The font descent.
+ */
+ public int getDescent()
+ {
+ return 1;
+ }
+
+ /**
+ * Returns the height of a line in this font. This will be the sum
+ * of the leading, the ascent, and the descent.
+ *
+ * @return The height of the font.
+ */
+ public int getHeight()
+ {
+ return getAscent() + getDescent() + getLeading();
+ }
+
+ /**
+ * Returns the maximum ascent value. This is the maximum distance any
+ * character in the font rised above the baseline.
+ *
+ * @return The maximum ascent for this font.
+ */
+ public int getMaxAscent()
+ {
+ return getAscent();
+ }
+
+ /**
+ * Returns the maximum descent value. This is the maximum distance any
+ * character in the font extends below the baseline.
+ *
+ * @return The maximum descent for this font.
+ */
+ public int getMaxDescent()
+ {
+ return getMaxDecent();
+ }
+
+ /**
+ * Returns the maximum descent value. This is the maximum distance any
+ * character in the font extends below the baseline.
+ *
+ * @return The maximum descent for this font.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getMaxDescent()</code>.
+ */
+ public int getMaxDecent()
+ {
+ return getDescent();
+ }
+
+ /**
+ * Returns the width of the widest character in the font.
+ *
+ * @return The width of the widest character in the font.
+ */
+ public int getMaxAdvance()
+ {
+ return -1;
+ }
+
+ /**
+ * Returns the width of the specified character.
+ *
+ * @param ch The character to return the width of.
+ *
+ * @return The width of the specified character.
+ */
+ public int charWidth(int ch)
+ {
+ char[] chars = Character.toChars(ch);
+ return charsWidth(chars, 0, chars.length);
+ }
+
+ /**
+ * Returns the width of the specified character.
+ *
+ * @param ch The character to return the width of.
+ *
+ * @return The width of the specified character.
+ */
+ public int charWidth(char ch)
+ {
+ return 1;
+ }
+
+ /**
+ * Returns the total width of the specified string
+ *
+ * @param str The string to return the width of.
+ *
+ * @return The width of the string.
+ */
+ public int stringWidth(String str)
+ {
+ char[] buf = new char[str.length()];
+ str.getChars(0, str.length(), buf, 0);
+
+ return charsWidth(buf, 0, buf.length);
+ }
+
+ /**
+ * Returns the total width of the specified character array.
+ *
+ * @param buf The character array containing the data.
+ * @param offset The offset into the array to start calculating from.
+ * @param len The total number of bytes to process.
+ *
+ * @return The width of the requested characters.
+ */
+ public int charsWidth(char[] buf, int offset, int len)
+ {
+ int total_width = 0;
+ int endOffset = offset + len;
+ for (int i = offset; i < endOffset; i++)
+ total_width += charWidth(buf[i]);
+ return total_width;
+ }
+
+ /**
+ * Returns the total width of the specified byte array.
+ *
+ * @param buf The byte array containing the data.
+ * @param offset The offset into the array to start calculating from.
+ * @param len The total number of bytes to process.
+ *
+ * @return The width of the requested characters.
+ */
+ public int bytesWidth(byte[] buf, int offset, int len)
+ {
+ int total_width = 0;
+ for (int i = offset; i < len; i++)
+ total_width = charWidth((char) buf[i]);
+
+ return total_width;
+ }
+
+ /**
+ * Returns the widths of the first 256 characters in the font.
+ *
+ * @return The widths of the first 256 characters in the font.
+ */
+ public int[] getWidths()
+ {
+ int[] result = new int[256];
+ for (char i = 0; i < 256; i++)
+ result[i] = charWidth(i);
+ return result;
+ }
+
+ /**
+ * Returns a string representation of this object.
+ *
+ * @return A string representation of this object.
+ */
+ public String toString()
+ {
+ return (this.getClass() + "[font=" + font + ",ascent=" + getAscent()
+ + ",descent=" + getDescent() + ",height=" + getHeight() + "]");
+ }
+
+ // Generic FontRenderContext used when getLineMetrics is called with a
+ // plain Graphics object.
+ private static final FontRenderContext gRC = new FontRenderContext(null,
+ false,
+ false);
+
+ /**
+ * Returns a {@link LineMetrics} object constructed with the
+ * specified text and the {@link FontRenderContext} of the Graphics
+ * object when it is an instance of Graphics2D or a generic
+ * FontRenderContext with a null transform, not anti-aliased and not
+ * using fractional metrics.
+ *
+ * @param text The string to calculate metrics from.
+ * @param g The Graphics object that will be used.
+ *
+ * @return A new {@link LineMetrics} object.
+ */
+ public LineMetrics getLineMetrics(String text, Graphics g)
+ {
+ return getLineMetrics(text, 0, text.length(), g);
+ }
+
+ /**
+ * Returns a {@link LineMetrics} object constructed with the
+ * specified text and the {@link FontRenderContext} of the Graphics
+ * object when it is an instance of Graphics2D or a generic
+ * FontRenderContext with a null transform, not anti-aliased and not
+ * using fractional metrics.
+ *
+ * @param text The string to calculate metrics from.
+ * @param begin Index of first character in <code>text</code> to measure.
+ * @param limit Index of last character in <code>text</code> to measure.
+ * @param g The Graphics object that will be used.
+ *
+ * @return A new {@link LineMetrics} object.
+ *
+ * @throws IndexOutOfBoundsException if the range [begin, limit] is
+ * invalid in <code>text</code>.
+ */
+ public LineMetrics getLineMetrics(String text, int begin, int limit,
+ Graphics g)
+ {
+ FontRenderContext rc;
+ if (g instanceof Graphics2D)
+ rc = ((Graphics2D) g).getFontRenderContext();
+ else
+ rc = gRC;
+ return font.getLineMetrics(text, begin, limit, rc);
+ }
+
+ /**
+ * Returns a {@link LineMetrics} object constructed with the
+ * specified text and the {@link FontRenderContext} of the Graphics
+ * object when it is an instance of Graphics2D or a generic
+ * FontRenderContext with a null transform, not anti-aliased and not
+ * using fractional metrics.
+ *
+ * @param chars The string to calculate metrics from.
+ * @param begin Index of first character in <code>text</code> to measure.
+ * @param limit Index of last character in <code>text</code> to measure.
+ * @param g The Graphics object that will be used.
+ *
+ * @return A new {@link LineMetrics} object.
+ *
+ * @throws IndexOutOfBoundsException if the range [begin, limit] is
+ * invalid in <code>text</code>.
+ */
+ public LineMetrics getLineMetrics(char[] chars, int begin, int limit,
+ Graphics g)
+ {
+ FontRenderContext rc;
+ if (g instanceof Graphics2D)
+ rc = ((Graphics2D) g).getFontRenderContext();
+ else
+ rc = gRC;
+ return font.getLineMetrics(chars, begin, limit, rc);
+ }
+
+ /**
+ * Returns the bounds of the largest character in a Graphics context.
+ * @param context the Graphics context object.
+ * @return a <code>Rectangle2D</code> representing the bounds
+ */
+ public Rectangle2D getMaxCharBounds(Graphics context)
+ {
+ if( context instanceof Graphics2D )
+ return font.getMaxCharBounds(((Graphics2D)context).getFontRenderContext());
+ return font.getMaxCharBounds( gRC );
+ }
+
+ /**
+ * Returns a {@link LineMetrics} object constructed with the
+ * specified text and the {@link FontRenderContext} of the Graphics
+ * object when it is an instance of Graphics2D or a generic
+ * FontRenderContext with a null transform, not anti-aliased and not
+ * using fractional metrics.
+ *
+ * @param ci An iterator over the string to calculate metrics from.
+ * @param begin Index of first character in <code>text</code> to measure.
+ * @param limit Index of last character in <code>text</code> to measure.
+ * @param g The Graphics object that will be used.
+ *
+ * @return A new {@link LineMetrics} object.
+ *
+ * @throws IndexOutOfBoundsException if the range [begin, limit] is
+ * invalid in <code>text</code>.
+ */
+ public LineMetrics getLineMetrics(CharacterIterator ci, int begin,
+ int limit, Graphics g)
+ {
+ FontRenderContext rc;
+ if (g instanceof Graphics2D)
+ rc = ((Graphics2D) g).getFontRenderContext();
+ else
+ rc = gRC;
+ return font.getLineMetrics(ci, begin, limit, rc);
+ }
+
+ public Rectangle2D getStringBounds(String str, Graphics context)
+ {
+ return font.getStringBounds(str, getFontRenderContext(context));
+ }
+
+ public Rectangle2D getStringBounds(String str, int beginIndex, int limit,
+ Graphics context)
+ {
+ return font.getStringBounds(str, beginIndex, limit,
+ getFontRenderContext(context));
+ }
+
+ public Rectangle2D getStringBounds(char[] chars, int beginIndex, int limit,
+ Graphics context)
+ {
+ return font.getStringBounds(chars, beginIndex, limit,
+ getFontRenderContext(context));
+ }
+
+ public Rectangle2D getStringBounds(CharacterIterator ci, int beginIndex,
+ int limit, Graphics context)
+ {
+ return font.getStringBounds(ci, beginIndex, limit,
+ getFontRenderContext(context));
+ }
+
+ private FontRenderContext getFontRenderContext(Graphics context)
+ {
+ if (context instanceof Graphics2D)
+ return ((Graphics2D) context).getFontRenderContext();
+
+ return gRC;
+ }
+
+ /**
+ * Returns if the font has uniform line metrics.
+ * @see Font#hasUniformLineMetrics()
+ */
+ public boolean hasUniformLineMetrics()
+ {
+ return font.hasUniformLineMetrics();
+ }
+}
diff --git a/libjava/classpath/java/awt/Frame.java b/libjava/classpath/java/awt/Frame.java
new file mode 100644
index 000000000..83bdb0947
--- /dev/null
+++ b/libjava/classpath/java/awt/Frame.java
@@ -0,0 +1,704 @@
+/* Frame.java -- AWT toplevel window
+ Copyright (C) 1999, 2000, 2002, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.peer.FramePeer;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Vector;
+
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleState;
+import javax.accessibility.AccessibleStateSet;
+
+/**
+ * This class is a top-level window with a title bar and window
+ * decorations.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class Frame extends Window implements MenuContainer
+{
+
+ /**
+ * Constant for the default cursor.
+ *
+ * @deprecated Replaced by <code>Cursor.DEFAULT_CURSOR</code> instead.
+ */
+ public static final int DEFAULT_CURSOR = Cursor.DEFAULT_CURSOR;
+
+ /**
+ * Constant for a cross-hair cursor.
+ *
+ * @deprecated Use <code>Cursor.CROSSHAIR_CURSOR</code> instead.
+ */
+ public static final int CROSSHAIR_CURSOR = Cursor.CROSSHAIR_CURSOR;
+
+ /**
+ * Constant for a cursor over a text field.
+ *
+ * @deprecated Use <code>Cursor.TEXT_CURSOR</code> instead.
+ */
+ public static final int TEXT_CURSOR = Cursor.TEXT_CURSOR;
+
+ /**
+ * Constant for a cursor to display while waiting for an action to complete.
+ *
+ * @deprecated Use <code>Cursor.WAIT_CURSOR</code>.
+ */
+ public static final int WAIT_CURSOR = Cursor.WAIT_CURSOR;
+
+ /**
+ * Cursor used over SW corner of window decorations.
+ *
+ * @deprecated Use <code>Cursor.SW_RESIZE_CURSOR</code> instead.
+ */
+ public static final int SW_RESIZE_CURSOR = Cursor.SW_RESIZE_CURSOR;
+
+ /**
+ * Cursor used over SE corner of window decorations.
+ * @deprecated Use <code>Cursor.SE_RESIZE_CURSOR</code> instead.
+ */
+ public static final int SE_RESIZE_CURSOR = Cursor.SE_RESIZE_CURSOR;
+
+ /**
+ * Cursor used over NW corner of window decorations.
+ *
+ * @deprecated Use <code>Cursor.NW_RESIZE_CURSOR</code> instead.
+ */
+ public static final int NW_RESIZE_CURSOR = Cursor.NW_RESIZE_CURSOR;
+
+ /**
+ * Cursor used over NE corner of window decorations.
+ *
+ * @deprecated Use <code>Cursor.NE_RESIZE_CURSOR</code> instead.
+ */
+ public static final int NE_RESIZE_CURSOR = Cursor.NE_RESIZE_CURSOR;
+
+ /**
+ * Cursor used over N edge of window decorations.
+ *
+ * @deprecated Use <code>Cursor.N_RESIZE_CURSOR</code> instead.
+ */
+ public static final int N_RESIZE_CURSOR = Cursor.N_RESIZE_CURSOR;
+
+ /**
+ * Cursor used over S edge of window decorations.
+ *
+ * @deprecated Use <code>Cursor.S_RESIZE_CURSOR</code> instead.
+ */
+ public static final int S_RESIZE_CURSOR = Cursor.S_RESIZE_CURSOR;
+
+ /**
+ * Cursor used over E edge of window decorations.
+ *
+ * @deprecated Use <code>Cursor.E_RESIZE_CURSOR</code> instead.
+ */
+ public static final int E_RESIZE_CURSOR = Cursor.E_RESIZE_CURSOR;
+
+ /**
+ * Cursor used over W edge of window decorations.
+ *
+ * @deprecated Use <code>Cursor.W_RESIZE_CURSOR</code> instead.
+ */
+ public static final int W_RESIZE_CURSOR = Cursor.W_RESIZE_CURSOR;
+
+ /**
+ * Constant for a hand cursor.
+ *
+ * @deprecated Use <code>Cursor.HAND_CURSOR</code> instead.
+ */
+ public static final int HAND_CURSOR = Cursor.HAND_CURSOR;
+
+ /**
+ * Constant for a cursor used during window move operations.
+ *
+ * @deprecated Use <code>Cursor.MOVE_CURSOR</code> instead.
+ */
+ public static final int MOVE_CURSOR = Cursor.MOVE_CURSOR;
+
+ public static final int ICONIFIED = 1;
+ public static final int MAXIMIZED_BOTH = 6;
+ public static final int MAXIMIZED_HORIZ = 2;
+ public static final int MAXIMIZED_VERT = 4;
+ public static final int NORMAL = 0;
+
+//Serialization version constant
+ private static final long serialVersionUID = 2673458971256075116L;
+
+ /**
+ * @serial The version of the class data being serialized
+ * FIXME: what is this value?
+ */
+ private int frameSerializedDataVersion;
+
+ /**
+ * @serial Image used as the icon when this frame is minimized.
+ */
+ private Image icon;
+
+ /**
+ * @serial Constant used by the JDK Motif peer set. Not used in
+ * this implementation.
+ */
+ private boolean mbManagement;
+
+ /**
+ * @serial The menu bar for this frame.
+ */
+ private MenuBar menuBar;
+
+ /**
+ * @serial A list of other top-level windows owned by this window.
+ */
+ Vector ownedWindows = new Vector();
+
+ /**
+ * @serial Indicates whether or not this frame is resizable.
+ */
+ private boolean resizable = true;
+
+ /**
+ * @serial The state of this frame.
+ * // FIXME: What are the values here?
+ * This is package-private to avoid an accessor method.
+ */
+ int state;
+
+ /**
+ * @serial The title of the frame.
+ */
+ private String title = "";
+
+ /**
+ * Maximized bounds for this frame.
+ */
+ private Rectangle maximizedBounds;
+
+ /**
+ * This field indicates whether the frame is undecorated or not.
+ */
+ private boolean undecorated = false;
+
+ /*
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_frame_number;
+
+ /**
+ * Initializes a new instance of <code>Frame</code> that is not visible
+ * and has no title.
+ */
+ public Frame()
+ {
+ this("");
+ noteFrame(this);
+ }
+
+ /**
+ * Initializes a new instance of <code>Frame</code> that is not visible
+ * and has the specified title.
+ *
+ * @param title the title of this frame
+ */
+ public Frame(String title)
+ {
+ super();
+ this.title = title;
+ // Top-level frames are initially invisible.
+ visible = false;
+ noteFrame(this);
+ }
+
+ public Frame(GraphicsConfiguration gc)
+ {
+ super(gc);
+ visible = false;
+ noteFrame(this);
+ }
+
+ public Frame(String title, GraphicsConfiguration gc)
+ {
+ super(gc);
+ setTitle(title);
+ visible = false;
+ noteFrame(this);
+ }
+
+ /**
+ * Returns this frame's title string.
+ *
+ * @return this frame's title string
+ */
+ public String getTitle()
+ {
+ return title;
+ }
+
+ /**
+ * Sets this frame's title to the specified value.
+ *
+ * @param title the new frame title
+ */
+ public synchronized void setTitle(String title)
+ {
+ this.title = title;
+ if (peer != null)
+ ((FramePeer) peer).setTitle(title);
+ }
+
+ /**
+ * Returns this frame's icon.
+ *
+ * @return this frame's icon, or <code>null</code> if this frame does not
+ * have an icon
+ */
+ public Image getIconImage()
+ {
+ return icon;
+ }
+
+ /**
+ * Sets this frame's icon to the specified value.
+ *
+ * @icon the new icon for this frame
+ */
+ public synchronized void setIconImage(Image icon)
+ {
+ this.icon = icon;
+ if (peer != null)
+ ((FramePeer) peer).setIconImage(icon);
+ }
+
+ /**
+ * Returns this frame's menu bar.
+ *
+ * @return this frame's menu bar, or <code>null</code> if this frame
+ * does not have a menu bar
+ */
+ public MenuBar getMenuBar()
+ {
+ return menuBar;
+ }
+
+ /**
+ * Sets this frame's menu bar. Removes any existing menu bar. If the
+ * given menu bar is part of another frame it will be removed from
+ * that frame.
+ *
+ * @param menuBar the new menu bar for this frame
+ */
+ public synchronized void setMenuBar(MenuBar menuBar)
+ {
+ if (this.menuBar != null)
+ remove(this.menuBar);
+
+ this.menuBar = menuBar;
+ if (menuBar != null)
+ {
+ MenuContainer parent = menuBar.getParent();
+ if (parent != null)
+ parent.remove(menuBar);
+ menuBar.setParent(this);
+
+ // Create local copy for thread safety.
+ FramePeer p = (FramePeer) peer;
+ if (p != null)
+ {
+ if (menuBar != null)
+ menuBar.addNotify();
+ if (valid)
+ invalidate();
+ p.setMenuBar(menuBar);
+ }
+ }
+ }
+
+ /**
+ * Tests whether or not this frame is resizable. This will be
+ * <code>true</code> by default.
+ *
+ * @return <code>true</code> if this frame is resizable, <code>false</code>
+ * otherwise
+ */
+ public boolean isResizable()
+ {
+ return resizable;
+ }
+
+ /**
+ * Sets the resizability of this frame to the specified value.
+ *
+ * @param resizable <code>true</code> to make the frame resizable,
+ * <code>false</code> to make it non-resizable
+ */
+ public synchronized void setResizable(boolean resizable)
+ {
+ this.resizable = resizable;
+ if (peer != null)
+ ((FramePeer) peer).setResizable(resizable);
+ }
+
+ /**
+ * Returns the cursor type of the cursor for this window. This will
+ * be one of the constants in this class.
+ *
+ * @return the cursor type for this frame
+ *
+ * @deprecated Use <code>Component.getCursor()</code> instead.
+ */
+ public int getCursorType()
+ {
+ return getCursor().getType();
+ }
+
+ /**
+ * Sets the cursor for this window to the specified type. The specified
+ * type should be one of the constants in this class.
+ *
+ * @param type the cursor type
+ *
+ * @deprecated Use <code>Component.setCursor(Cursor)</code> instead.
+ */
+ public void setCursor(int type)
+ {
+ setCursor(new Cursor(type));
+ }
+
+ /**
+ * Removes the specified menu component from this frame. If it is
+ * the current MenuBar it is removed from the frame. If it is a
+ * Popup it is removed from this component. If it is any other menu
+ * component it is ignored.
+ *
+ * @param menu the menu component to remove
+ */
+ public void remove(MenuComponent menu)
+ {
+ if (menu == menuBar)
+ {
+ if (menuBar != null)
+ {
+ if (peer != null)
+ {
+ ((FramePeer) peer).setMenuBar(null);
+ menuBar.removeNotify();
+ }
+ menuBar.setParent(null);
+ }
+ menuBar = null;
+ }
+ else
+ super.remove(menu);
+ }
+
+ public void addNotify()
+ {
+ if (menuBar != null)
+ menuBar.addNotify();
+ if (peer == null)
+ peer = getToolkit ().createFrame (this);
+
+ super.addNotify();
+ }
+
+ public void removeNotify()
+ {
+ if (menuBar != null)
+ menuBar.removeNotify();
+ super.removeNotify();
+ }
+
+ /**
+ * Returns a debugging string describing this window.
+ *
+ * @return a debugging string describing this window
+ */
+ protected String paramString()
+ {
+ String title = getTitle();
+
+ String resizable = "";
+ if (isResizable ())
+ resizable = ",resizable";
+
+ String state = "";
+ switch (getState ())
+ {
+ case NORMAL:
+ state = ",normal";
+ break;
+ case ICONIFIED:
+ state = ",iconified";
+ break;
+ case MAXIMIZED_BOTH:
+ state = ",maximized-both";
+ break;
+ case MAXIMIZED_HORIZ:
+ state = ",maximized-horiz";
+ break;
+ case MAXIMIZED_VERT:
+ state = ",maximized-vert";
+ break;
+ }
+
+ return super.paramString () + ",title=" + title + resizable + state;
+ }
+
+ /**
+ * The list of active frames. GC'ed frames get removed in noteFrame().
+ */
+ private static ArrayList<WeakReference<Frame>> weakFrames =
+ new ArrayList<WeakReference<Frame>>();
+
+ /**
+ * The death queue for all frames.
+ */
+ private static ReferenceQueue weakFramesQueue =
+ new ReferenceQueue<Frame>();
+
+ private static void noteFrame(Frame f)
+ {
+ synchronized (weakFrames)
+ {
+ // Remove GCed frames from the list.
+ Reference ref = weakFramesQueue.poll();
+ while (ref != null)
+ {
+ weakFrames.remove(ref);
+ ref = weakFramesQueue.poll();
+ }
+ // Add new frame.
+ weakFrames.add(new WeakReference<Frame>(f));
+ }
+ }
+
+ /**
+ * Returns <code>true</code> when there are any displayable frames,
+ * <code>false</code> otherwise.
+ *
+ * @return <code>true</code> when there are any displayable frames,
+ * <code>false</code> otherwise
+ */
+ static boolean hasDisplayableFrames()
+ {
+ synchronized (weakFrames)
+ {
+ for (WeakReference<Frame> r : Frame.weakFrames)
+ {
+ Frame f = (Frame) r.get();
+ if (f != null && f.isDisplayable())
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static Frame[] getFrames()
+ {
+ synchronized (weakFrames)
+ {
+ ArrayList<Frame> existingFrames = new ArrayList<Frame>();
+ for (WeakReference<Frame> ref : weakFrames)
+ {
+ Frame f = ref.get();
+ if (f != null)
+ {
+ existingFrames.add(f);
+ }
+ }
+ Frame[] frames = new Frame[existingFrames.size()];
+ frames = existingFrames.toArray(frames);
+ return frames;
+ }
+ }
+
+ public void setState(int state)
+ {
+ int current_state = getExtendedState ();
+
+ if (state == NORMAL
+ && (current_state & ICONIFIED) != 0)
+ setExtendedState(current_state | ICONIFIED);
+
+ if (state == ICONIFIED
+ && (current_state & ~ICONIFIED) == 0)
+ setExtendedState(current_state & ~ICONIFIED);
+ }
+
+ public int getState()
+ {
+ return (getExtendedState() & ICONIFIED) != 0 ? ICONIFIED : NORMAL;
+ }
+
+ /**
+ * @since 1.4
+ */
+ public void setExtendedState(int state)
+ {
+ if (getToolkit().isFrameStateSupported(state))
+ {
+ this.state = state;
+ FramePeer p = (FramePeer) peer;
+ if (p != null)
+ p.setState(state);
+ }
+ }
+
+ /**
+ * @since 1.4
+ */
+ public int getExtendedState()
+ {
+ FramePeer p = (FramePeer) peer;
+ if (p != null)
+ state = p.getState();
+ return state;
+ }
+
+ /**
+ * @since 1.4
+ */
+ public void setMaximizedBounds(Rectangle maximizedBounds)
+ {
+ this.maximizedBounds = maximizedBounds;
+ }
+
+ /**
+ * Returns the maximized bounds of this frame.
+ *
+ * @return the maximized rectangle, may be null
+ *
+ * @since 1.4
+ */
+ public Rectangle getMaximizedBounds()
+ {
+ return maximizedBounds;
+ }
+
+ /**
+ * Returns whether this frame is undecorated or not.
+ *
+ * @since 1.4
+ */
+ public boolean isUndecorated()
+ {
+ return undecorated;
+ }
+
+ /**
+ * Disables or enables decorations for this frame. This method can only be
+ * called while the frame is not displayable.
+ *
+ * @throws IllegalComponentStateException if this frame is displayable
+ *
+ * @since 1.4
+ */
+ public void setUndecorated(boolean undecorated)
+ {
+ if (isDisplayable())
+ throw new IllegalComponentStateException();
+
+ this.undecorated = undecorated;
+ }
+
+ /**
+ * Generate a unique name for this frame.
+ *
+ * @return a unique name for this frame
+ */
+ String generateName()
+ {
+ return "frame" + getUniqueLong();
+ }
+
+ private static synchronized long getUniqueLong()
+ {
+ return next_frame_number++;
+ }
+
+ /**
+ * Accessibility support for <code>Frame</code>.
+ */
+ protected class AccessibleAWTFrame extends AccessibleAWTWindow
+ {
+ private static final long serialVersionUID = -6172960752956030250L;
+
+ /**
+ * Gets the role of this object.
+ * @return AccessibleRole.FRAME
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.FRAME;
+ }
+
+ /**
+ * Gets the state set of this object.
+ * @return The current state of this frame.
+ */
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ AccessibleStateSet states = super.getAccessibleStateSet();
+ if (isResizable())
+ states.add(AccessibleState.RESIZABLE);
+ if ((state & ICONIFIED) != 0)
+ states.add(AccessibleState.ICONIFIED);
+ return states;
+ }
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>Frame</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ // Create the context if this is the first request.
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTFrame();
+ return accessibleContext;
+ }
+}
diff --git a/libjava/classpath/java/awt/GradientPaint.java b/libjava/classpath/java/awt/GradientPaint.java
new file mode 100644
index 000000000..0bb840755
--- /dev/null
+++ b/libjava/classpath/java/awt/GradientPaint.java
@@ -0,0 +1,229 @@
+/* GradientPaint.java --
+ Copyright (C) 2002, 2005, Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.ColorModel;
+import gnu.java.awt.GradientPaintContext;
+
+/**
+ * A paint object that can be used to color a region by blending two colors.
+ * Instances of this class are immutable.
+ */
+public class GradientPaint implements Paint
+{
+ private final float x1;
+ private final float y1;
+ private final Color c1;
+ private final float x2;
+ private final float y2;
+ private final Color c2;
+ private final boolean cyclic;
+
+ /**
+ * Creates a new acyclic <code>GradientPaint</code>.
+ *
+ * @param x1 the x-coordinate of the anchor point for color 1.
+ * @param y1 the y-coordinate of the anchor point for color 1.
+ * @param c1 color 1 (<code>null</code> not permitted).
+ * @param x2 the x-coordinate of the anchor point for color 2.
+ * @param y2 the y-coordinate of the anchor point for color 2.
+ * @param c2 the second color (<code>null</code> not permitted).
+ */
+ public GradientPaint(float x1, float y1, Color c1,
+ float x2, float y2, Color c2)
+ {
+ this(x1, y1, c1, x2, y2, c2, false);
+ }
+
+ /**
+ * Creates a new acyclic <code>GradientPaint</code>.
+ *
+ * @param p1 anchor point 1 (<code>null</code> not permitted).
+ * @param c1 color 1 (<code>null</code> not permitted).
+ * @param p2 anchor point 2 (<code>null</code> not permitted).
+ * @param c2 color 2 (<code>null</code> not permitted).
+ */
+ public GradientPaint(Point2D p1, Color c1, Point2D p2, Color c2)
+ {
+ this((float) p1.getX(), (float) p1.getY(), c1,
+ (float) p2.getX(), (float) p2.getY(), c2, false);
+ }
+
+ /**
+ * Creates a new cyclic or acyclic <code>GradientPaint</code>.
+ *
+ * @param x1 the x-coordinate of the anchor point for color 1.
+ * @param y1 the y-coordinate of the anchor point for color 1.
+ * @param c1 color 1 (<code>null</code> not permitted).
+ * @param x2 the x-coordinate of the anchor point for color 2.
+ * @param y2 the y-coordinate of the anchor point for color 2.
+ * @param c2 the second color (<code>null</code> not permitted).
+ * @param cyclic a flag that controls whether the gradient is cyclic or
+ * acyclic.
+ */
+ public GradientPaint(float x1, float y1, Color c1,
+ float x2, float y2, Color c2, boolean cyclic)
+ {
+ if (c1 == null || c2 == null)
+ throw new NullPointerException();
+ this.x1 = x1;
+ this.y1 = y1;
+ this.c1 = c1;
+ this.x2 = x2;
+ this.y2 = y2;
+ this.c2 = c2;
+ this.cyclic = cyclic;
+ }
+
+ /**
+ * Creates a new cyclic or acyclic <code>GradientPaint</code>.
+ *
+ * @param p1 anchor point 1 (<code>null</code> not permitted).
+ * @param c1 color 1 (<code>null</code> not permitted).
+ * @param p2 anchor point 2 (<code>null</code> not permitted).
+ * @param c2 color 2 (<code>null</code> not permitted).
+ * @param cyclic a flag that controls whether the gradient is cyclic or
+ * acyclic.
+ */
+ public GradientPaint(Point2D p1, Color c1, Point2D p2, Color c2,
+ boolean cyclic)
+ {
+ this((float) p1.getX(), (float) p1.getY(), c1,
+ (float) p2.getX(), (float) p2.getY(), c2, cyclic);
+ }
+
+ /**
+ * Returns a point with the same coordinates as the anchor point for color 1.
+ * Note that if you modify this point, the <code>GradientPaint</code> remains
+ * unchanged.
+ *
+ * @return A point with the same coordinates as the anchor point for color 1.
+ */
+ public Point2D getPoint1()
+ {
+ return new Point2D.Float(x1, y1);
+ }
+
+ /**
+ * Returns the first color.
+ *
+ * @return The color (never <code>null</code>).
+ */
+ public Color getColor1()
+ {
+ return c1;
+ }
+
+ /**
+ * Returns a point with the same coordinates as the anchor point for color 2.
+ * Note that if you modify this point, the <code>GradientPaint</code> remains
+ * unchanged.
+ *
+ * @return A point with the same coordinates as the anchor point for color 2.
+ */
+ public Point2D getPoint2()
+ {
+ return new Point2D.Float(x2, y2);
+ }
+
+ /**
+ * Returns the second color.
+ *
+ * @return The color (never <code>null</code>).
+ */
+ public Color getColor2()
+ {
+ return c2;
+ }
+
+ /**
+ * Returns <code>true</code> if this <code>GradientPaint</code> instance is
+ * cyclic, and <code>false</code> otherwise.
+ *
+ * @return A boolean.
+ */
+ public boolean isCyclic()
+ {
+ return cyclic;
+ }
+
+ /**
+ * Returns the {@link PaintContext} used to generate the color pattern.
+ *
+ * @param cm the color model, used as a hint (ignored in this
+ * implementation).
+ * @param deviceBounds the device space bounding box of the painted area.
+ * @param userBounds the user space bounding box of the painted area.
+ * @param xform the transformation from user space to device space.
+ * @param hints any hints for choosing between rendering alternatives.
+ *
+ * @return The context for performing the paint
+ */
+ public PaintContext createContext(ColorModel cm, Rectangle deviceBounds,
+ Rectangle2D userBounds,
+ AffineTransform xform,
+ RenderingHints hints)
+ {
+ Point2D xp1 = xform.transform(getPoint1(), null);
+ Point2D xp2 = xform.transform(getPoint2(), null);
+ return new GradientPaintContext((float) xp1.getX(), (float) xp1.getY(), c1,
+ (float) xp2.getX(), (float) xp2.getY(), c2, cyclic);
+ }
+
+ /**
+ * Returns the transparency code for this <code>GradientPaint</code> instance.
+ * This is derived from the two {@link Color} objects used in creating this
+ * object: if both colors are opaque, this method returns
+ * {@link Transparency#OPAQUE}, otherwise it returns
+ * {@link Transparency#TRANSLUCENT}.
+ *
+ * @return {@link Transparency#OPAQUE} or {@link Transparency#TRANSLUCENT}.
+ */
+ public int getTransparency()
+ {
+ if (c1.getAlpha() == 255 && c2.getAlpha() == 255)
+ return Transparency.OPAQUE;
+ else
+ return Transparency.TRANSLUCENT;
+ }
+
+} // class GradientPaint
diff --git a/libjava/classpath/java/awt/Graphics.java b/libjava/classpath/java/awt/Graphics.java
new file mode 100644
index 000000000..dfc772207
--- /dev/null
+++ b/libjava/classpath/java/awt/Graphics.java
@@ -0,0 +1,639 @@
+/* Graphics.java -- Abstract Java drawing class
+ Copyright (C) 1999, 2000, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.image.ImageObserver;
+import java.text.AttributedCharacterIterator;
+
+/**
+ * This is the abstract superclass of classes for drawing to graphics
+ * devices such as the screen or printers.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ */
+public abstract class Graphics
+{
+
+ /**
+ * Default constructor for subclasses.
+ */
+ protected
+ Graphics()
+ {
+ }
+
+ /**
+ * Returns a copy of this <code>Graphics</code> object.
+ *
+ * @return A copy of this object.
+ */
+ public abstract Graphics create();
+
+ /**
+ * Returns a copy of this <code>Graphics</code> object. The origin point
+ * will be translated to the point (x, y) and the cliping rectangle set
+ * to the intersection of the clipping rectangle in this object and the
+ * rectangle specified by the parameters to this method.
+ *
+ * @param x The new X coordinate of the clipping region rect.
+ * @param y The new Y coordinate of the clipping region rect.
+ * @param width The width of the clipping region intersect rectangle.
+ * @param height The height of the clipping region intersect rectangle.
+ *
+ * @return A copy of this object, modified as specified.
+ */
+ public Graphics create(int x, int y, int width, int height)
+ {
+ Graphics g = create();
+
+ g.translate(x, y);
+ // FIXME: I'm not sure if this will work. Are the old clip rect bounds
+ // translated above?
+ g.clipRect(0, 0, width, height);
+
+ return(g);
+ }
+
+ /**
+ * Translates this context so that its new origin point is the point
+ * (x, y).
+ *
+ * @param x The new X coordinate of the origin.
+ * @param y The new Y coordinate of the origin.
+ */
+ public abstract void translate(int x, int y);
+
+ /**
+ * Returns the current color for this object.
+ *
+ * @return The color for this object.
+ */
+ public abstract Color getColor();
+
+ /**
+ * Sets the current color for this object.
+ *
+ * @param color The new color.
+ */
+ public abstract void setColor(Color color);
+
+ /**
+ * Sets this context into "paint" mode, where the target pixels are
+ * completely overwritten when drawn on.
+ */
+ public abstract void setPaintMode();
+
+ /**
+ * Sets this context info "XOR" mode, where the targe pixles are
+ * XOR-ed when drawn on.
+ *
+ * @param color The color to XOR against.
+ */
+ public abstract void setXORMode(Color color);
+
+ /**
+ * Returns the current font for this graphics context.
+ *
+ * @return The current font.
+ */
+ public abstract Font getFont();
+
+ /**
+ * Sets the font for this graphics context to the specified value.
+ *
+ * @param font The new font.
+ */
+ public abstract void setFont(Font font);
+
+ /**
+ * Returns the font metrics for the current font.
+ *
+ * @return The font metrics for the current font.
+ */
+ public FontMetrics getFontMetrics()
+ {
+ return getFontMetrics(getFont());
+ }
+
+ /**
+ * Returns the font metrics for the specified font.
+ *
+ * @param font The font to return metrics for.
+ *
+ * @return The requested font metrics.
+ */
+ public abstract FontMetrics getFontMetrics(Font font);
+
+ /**
+ * Returns the bounding rectangle of the clipping region for this
+ * graphics context.
+ *
+ * @return The bounding rectangle for the clipping region.
+ */
+ public abstract Rectangle getClipBounds();
+
+ /**
+ * Returns the bounding rectangle of the clipping region for this
+ * graphics context.
+ *
+ * @return The bounding rectangle for the clipping region.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getClipBounds()</code>.
+ */
+ public Rectangle getClipRect()
+ {
+ return getClipBounds();
+ }
+
+ /**
+ * Sets the clipping region to the intersection of the current clipping
+ * region and the rectangle determined by the specified parameters.
+ *
+ * @param x The X coordinate of the upper left corner of the intersect rect.
+ * @param y The Y coordinate of the upper left corner of the intersect rect.
+ * @param width The width of the intersect rect.
+ * @param height The height of the intersect rect.
+ */
+ public abstract void clipRect(int x, int y, int width, int height);
+
+ /**
+ * Sets the clipping region to the rectangle determined by the specified
+ * parameters.
+ *
+ * @param x The X coordinate of the upper left corner of the rect.
+ * @param y The Y coordinate of the upper left corner of the rect.
+ * @param width The width of the rect.
+ * @param height The height of the rect.
+ */
+ public abstract void setClip(int x, int y, int width, int height);
+
+ /**
+ * Returns the current clipping region as a <code>Shape</code> object.
+ *
+ * @return The clipping region as a <code>Shape</code>.
+ */
+ public abstract Shape getClip();
+
+ /**
+ * Sets the clipping region to the specified <code>Shape</code>.
+ *
+ * @param clip The new clipping region.
+ */
+ public abstract void setClip(Shape clip);
+
+ /**
+ * Copies the specified rectangle to the specified offset location.
+ *
+ * @param x The X coordinate of the upper left corner of the copy rect.
+ * @param y The Y coordinate of the upper left corner of the copy rect.
+ * @param width The width of the copy rect.
+ * @param height The height of the copy rect.
+ * @param dx The offset from the X value to start drawing.
+ * @param dy The offset from the Y value to start drawing.
+ */
+ public abstract void copyArea(int x, int y, int width, int height, int dx,
+ int dy);
+
+ /**
+ * Draws a line between the two specified points.
+ *
+ * @param x1 The X coordinate of the first point.
+ * @param y1 The Y coordinate of the first point.
+ * @param x2 The X coordinate of the second point.
+ * @param y2 The Y coordinate of the second point.
+ */
+ public abstract void drawLine(int x1, int y1, int x2, int y2);
+
+ /**
+ * Fills the area bounded by the specified rectangle.
+ *
+ * @param x The X coordinate of the upper left corner of the fill rect.
+ * @param y The Y coordinate of the upper left corner of the fill rect.
+ * @param width The width of the fill rect.
+ * @param height The height of the fill rect.
+ */
+ public abstract void fillRect(int x, int y, int width, int height);
+
+ /**
+ * Draws the outline of the specified rectangle.
+ *
+ * @param x The X coordinate of the upper left corner of the draw rect.
+ * @param y The Y coordinate of the upper left corner of the draw rect.
+ * @param width The width of the draw rect.
+ * @param height The height of the draw rect.
+ */
+ public void drawRect(int x, int y, int width, int height)
+ {
+ int x1 = x;
+ int y1 = y;
+ int x2 = x + width;
+ int y2 = y + height;
+ drawLine(x1, y1, x2, y1);
+ drawLine(x2, y1, x2, y2);
+ drawLine(x2, y2, x1, y2);
+ drawLine(x1, y2, x1, y1);
+ }
+
+ /**
+ * Clears the specified rectangle.
+ *
+ * @param x The X coordinate of the upper left corner of the clear rect.
+ * @param y The Y coordinate of the upper left corner of the clear rect.
+ * @param width The width of the clear rect.
+ * @param height The height of the clear rect.
+ */
+ public abstract void clearRect(int x, int y, int width, int height);
+
+ /**
+ * Draws the outline of the specified rectangle with rounded cornders.
+ *
+ * @param x The X coordinate of the upper left corner of the draw rect.
+ * @param y The Y coordinate of the upper left corner of the draw rect.
+ * @param width The width of the draw rect.
+ * @param height The height of the draw rect.
+ * @param arcWidth The width of the corner arcs.
+ * @param arcHeight The height of the corner arcs.
+ */
+ public abstract void drawRoundRect(int x, int y, int width, int height,
+ int arcWidth, int arcHeight);
+
+ /**
+ * Fills the specified rectangle with rounded cornders.
+ *
+ * @param x The X coordinate of the upper left corner of the fill rect.
+ * @param y The Y coordinate of the upper left corner of the fill rect.
+ * @param width The width of the fill rect.
+ * @param height The height of the fill rect.
+ * @param arcWidth The width of the corner arcs.
+ * @param arcHeight The height of the corner arcs.
+ */
+ public abstract void fillRoundRect(int x, int y, int width, int height,
+ int arcWidth, int arcHeight);
+
+ public void draw3DRect(int x, int y, int width, int height, boolean raised)
+ {
+ Color color = getColor();
+ Color tl = color.brighter();
+ Color br = color.darker();
+
+ if (!raised)
+ {
+ Color tmp = tl;
+ tl = br;
+ br = tmp;
+ }
+
+ int x1 = x;
+ int y1 = y;
+ int x2 = x + width;
+ int y2 = y + height;
+
+ setColor(tl);
+ drawLine(x1, y1, x2, y1);
+ drawLine(x1, y2, x1, y1);
+ setColor(br);
+ drawLine(x2, y1, x2, y2);
+ drawLine(x2, y2, x1, y2);
+ setColor(color);
+ }
+
+ /**
+ * Fills the specified rectangle with a 3D effect
+ *
+ * @param x The X coordinate of the upper left corner of the fill rect.
+ * @param y The Y coordinate of the upper left corner of the fill rect.
+ * @param width The width of the fill rect.
+ * @param height The height of the fill rect.
+ * @param raised <code>true</code> if the rectangle appears raised,
+ * <code>false</code> if it should appear etched.
+ */
+ public void fill3DRect(int x, int y, int width, int height, boolean raised)
+ {
+ fillRect(x, y, width, height);
+ draw3DRect(x, y, width-1, height-1, raised);
+ }
+
+ /**
+ * Draws an oval that just fits within the specified rectangle.
+ *
+ * @param x The X coordinate of the upper left corner of the rect.
+ * @param y The Y coordinate of the upper left corner of the rect.
+ * @param width The width of the rect.
+ * @param height The height of the rect.
+ */
+ public abstract void drawOval(int x, int y, int width, int height);
+
+ /**
+ * Fills an oval that just fits within the specified rectangle.
+ *
+ * @param x The X coordinate of the upper left corner of the rect.
+ * @param y The Y coordinate of the upper left corner of the rect.
+ * @param width The width of the rect.
+ * @param height The height of the rect.
+ */
+ public abstract void fillOval(int x, int y, int width, int height);
+
+ /**
+ * Draws an arc using the specified bounding rectangle and the specified
+ * angle parameter. The arc is centered at the center of the rectangle.
+ * The arc starts at the arcAngle position and extend for arcAngle
+ * degrees. The degree origin is at the 3 o'clock position.
+ *
+ * @param x The X coordinate of the upper left corner of the rect.
+ * @param y The Y coordinate of the upper left corner of the rect.
+ * @param width The width of the rect.
+ * @param height The height of the rect.
+ * @param arcStart The beginning angle of the arc.
+ * @param arcAngle The extent of the arc.
+ */
+ public abstract void drawArc(int x, int y, int width, int height,
+ int arcStart, int arcAngle);
+
+ /**
+ * Fills the arc define by the specified bounding rectangle and the specified
+ * angle parameter. The arc is centered at the center of the rectangle.
+ * The arc starts at the arcAngle position and extend for arcAngle
+ * degrees. The degree origin is at the 3 o'clock position.
+ *
+ * @param x The X coordinate of the upper left corner of the rect.
+ * @param y The Y coordinate of the upper left corner of the rect.
+ * @param width The width of the rect.
+ * @param height The height of the rect.
+ * @param arcStart The beginning angle of the arc.
+ * @param arcAngle The extent of the arc.
+ */
+ public abstract void fillArc(int x, int y, int width, int height,
+ int arcStart, int arcAngle);
+
+ /**
+ * Draws a series of interconnected lines determined by the arrays
+ * of corresponding x and y coordinates.
+ *
+ * @param xPoints The X coordinate array.
+ * @param yPoints The Y coordinate array.
+ * @param npoints The number of points to draw.
+ */
+ public abstract void drawPolyline(int xPoints[], int yPoints[], int npoints);
+
+ /**
+ * Draws a series of interconnected lines determined by the arrays
+ * of corresponding x and y coordinates. The figure is closed if necessary
+ * by connecting the first and last points.
+ *
+ * @param xPoints The X coordinate array.
+ * @param yPoints The Y coordinate array.
+ * @param npoints The number of points to draw.
+ */
+ public abstract void drawPolygon(int xPoints[], int yPoints[], int npoints);
+
+ /**
+ * Draws the specified polygon.
+ *
+ * @param polygon The polygon to draw.
+ */
+ public void drawPolygon(Polygon polygon)
+ {
+ drawPolygon(polygon.xpoints, polygon.ypoints, polygon.npoints);
+ }
+
+ /**
+ * Fills the polygon determined by the arrays
+ * of corresponding x and y coordinates.
+ *
+ * @param xPoints The X coordinate array.
+ * @param yPoints The Y coordinate array.
+ * @param npoints The number of points to draw.
+ */
+ public abstract void fillPolygon(int xPoints[], int yPoints[], int npoints);
+
+ /**
+ * Fills the specified polygon
+ *
+ * @param polygon The polygon to fill.
+ */
+ public void fillPolygon(Polygon polygon)
+ {
+ fillPolygon(polygon.xpoints, polygon.ypoints, polygon.npoints);
+ }
+
+ /**
+ * Draws the specified string starting at the specified point.
+ *
+ * @param string The string to draw.
+ * @param x The X coordinate of the point to draw at.
+ * @param y The Y coordinate of the point to draw at.
+ */
+ public abstract void drawString(String string, int x, int y);
+
+ public abstract void drawString (AttributedCharacterIterator ci, int x,
+ int y);
+
+ /**
+ * Draws the specified characters starting at the specified point.
+ *
+ * @param data The array of characters to draw.
+ * @param offset The offset into the array to start drawing characters from.
+ * @param length The number of characters to draw.
+ * @param x The X coordinate of the point to draw at.
+ * @param y The Y coordinate of the point to draw at.
+ */
+ public void drawChars(char data[], int offset, int length, int x, int y)
+ {
+ drawString(new String(data, offset, length), x, y);
+ }
+
+ public void drawBytes(byte[] data, int offset, int length, int x, int y)
+ {
+ String str = new String(data, offset, length);
+ drawString(str, x, y);
+ }
+
+ /**
+ * Draws all of the image that is available and returns. If the image
+ * is not completely loaded, <code>false</code> is returned and
+ * the specified iamge observer is notified as more data becomes
+ * available.
+ *
+ * @param image The image to draw.
+ * @param x The X coordinate of the point to draw at.
+ * @param y The Y coordinate of the point to draw at.
+ * @param observer The image observer to notify as data becomes available.
+ *
+ * @return <code>true</code> if all the image data is available,
+ * <code>false</code> otherwise.
+ */
+ public abstract boolean drawImage(Image image, int x, int y,
+ ImageObserver observer);
+
+ /**
+ * Draws all of the image that is available and returns. The image
+ * is scaled to fit in the specified rectangle. If the image
+ * is not completely loaded, <code>false</code> is returned and
+ * the specified iamge observer is notified as more data becomes
+ * available.
+ *
+ * @param image The image to draw.
+ * @param x The X coordinate of the point to draw at.
+ * @param y The Y coordinate of the point to draw at.
+ * @param width The width of the rectangle to draw in.
+ * @param height The height of the rectangle to draw in.
+ * @param observer The image observer to notify as data becomes available.
+ *
+ * @return <code>true</code> if all the image data is available,
+ * <code>false</code> otherwise.
+ */
+ public abstract boolean drawImage(Image image, int x, int y, int width,
+ int height, ImageObserver observer);
+
+ /**
+ * Draws all of the image that is available and returns. If the image
+ * is not completely loaded, <code>false</code> is returned and
+ * the specified iamge observer is notified as more data becomes
+ * available.
+ *
+ * @param image The image to draw.
+ * @param x The X coordinate of the point to draw at.
+ * @param y The Y coordinate of the point to draw at.
+ * @param bgcolor The background color to use for the image.
+ * @param observer The image observer to notify as data becomes available.
+ *
+ * @return <code>true</code> if all the image data is available,
+ * <code>false</code> otherwise.
+ */
+ public abstract boolean drawImage(Image image, int x, int y, Color bgcolor,
+ ImageObserver observer);
+
+ /**
+ * Draws all of the image that is available and returns. The image
+ * is scaled to fit in the specified rectangle. If the image
+ * is not completely loaded, <code>false</code> is returned and
+ * the specified iamge observer is notified as more data becomes
+ * available.
+ *
+ * @param image The image to draw.
+ * @param x The X coordinate of the point to draw at.
+ * @param y The Y coordinate of the point to draw at.
+ * @param width The width of the rectangle to draw in.
+ * @param height The height of the rectangle to draw in.
+ * @param bgcolor The background color to use for the image.
+ * @param observer The image observer to notify as data becomes available.
+ *
+ * @return <code>true</code> if all the image data is available,
+ * <code>false</code> otherwise.
+ */
+ public abstract boolean drawImage(Image image, int x, int y, int width,
+ int height, Color bgcolor,
+ ImageObserver observer);
+
+ /**
+ * FIXME: Write Javadocs for this when you understand it.
+ */
+ public abstract boolean drawImage(Image image, int dx1, int dy1, int dx2,
+ int dy2, int sx1, int sy1, int sx2,
+ int sy2, ImageObserver observer);
+
+ /**
+ * FIXME: Write Javadocs for this when you understand it.
+ */
+ public abstract boolean drawImage(Image image, int dx1, int dy1, int dx2,
+ int dy2, int sx1, int sy1, int sx2,
+ int sy2, Color bgcolor,
+ ImageObserver observer);
+
+ /**
+ * Free any resources held by this graphics context immediately instead
+ * of waiting for the object to be garbage collected and finalized.
+ */
+ public abstract void dispose();
+
+ /**
+ * Frees the resources held by this graphics context when it is
+ * garbage collected.
+ */
+ public void finalize()
+ {
+ dispose();
+ }
+
+ /**
+ * Returns a string representation of this object.
+ *
+ * @return A string representation of this object.
+ */
+ public String toString()
+ {
+ return getClass ().getName () + "[font=" + getFont () + ",color="
+ + getColor () + "]";
+ }
+
+ /**
+ * Returns <code>true</code> if the specified rectangle intersects with the
+ * current clip, <code>false</code> otherwise.
+ *
+ * @param x the X coordinate of the upper left corner of the test rectangle
+ * @param y the Y coordinate of the upper left corner of the test rectangle
+ * @param width the width of the upper left corner of the test rectangle
+ * @param height the height of the upper left corner of the test rectangle
+ * @return <code>true</code> if the specified rectangle intersects with the
+ * current clip, <code>false</code> otherwise
+ */
+ public boolean hitClip(int x, int y, int width, int height)
+ {
+ Shape clip = getClip();
+ if (clip == null)
+ return true;
+ return getClip().intersects(x, y, width, height);
+ }
+
+ public Rectangle getClipBounds(Rectangle r)
+ {
+ Rectangle clipBounds = getClipBounds();
+
+ if (r == null)
+ return clipBounds;
+
+ r.x = clipBounds.x;
+ r.y = clipBounds.y;
+ r.width = clipBounds.width;
+ r.height = clipBounds.height;
+ return r;
+ }
+}
diff --git a/libjava/classpath/java/awt/Graphics2D.java b/libjava/classpath/java/awt/Graphics2D.java
new file mode 100644
index 000000000..7c9622aef
--- /dev/null
+++ b/libjava/classpath/java/awt/Graphics2D.java
@@ -0,0 +1,358 @@
+/* Copyright (C) 2000, 2002, 2004, 2006, Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.geom.AffineTransform;
+import java.awt.image.BufferedImage;
+import java.awt.image.BufferedImageOp;
+import java.awt.image.ImageObserver;
+import java.awt.image.RenderedImage;
+import java.awt.image.renderable.RenderableImage;
+import java.awt.print.PageFormat;
+import java.awt.print.Printable;
+import java.text.AttributedCharacterIterator;
+import java.util.Map;
+
+/**
+ * An abstract class defining a device independent two-dimensional vector
+ * graphics API. Concrete subclasses implement this API for output of
+ * vector graphics to:
+ * <p>
+ * <ul>
+ * <li>a {@link javax.swing.JComponent} - in the
+ * {@link javax.swing.JComponent#paint(Graphics)} method, the incoming
+ * {@link Graphics} should always be an instance of
+ * <code>Graphics2D</code>;</li>
+ * <li>a {@link BufferedImage} - see
+ * {@link BufferedImage#createGraphics()};</li>
+ * <li>a {@link java.awt.print.PrinterJob} - in the
+ * {@link Printable#print(Graphics, PageFormat, int)} method, the incoming
+ * {@link Graphics} should always be an instance of
+ * <code>Graphics2D</code>.</li>
+ * </ul>
+ * <p>
+ * Third party libraries provide support for output to other formats via this
+ * API, including encapsulated postscript (EPS), portable document format (PDF),
+ * and scalable vector graphics (SVG).
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public abstract class Graphics2D extends Graphics
+{
+
+ protected Graphics2D()
+ {
+ }
+
+ public void draw3DRect(int x, int y, int width, int height,
+ boolean raised)
+ {
+ super.draw3DRect(x, y, width, height, raised);
+ }
+
+ public void fill3DRect(int x, int y, int width, int height,
+ boolean raised)
+ {
+ super.fill3DRect(x, y, width, height, raised);
+ }
+
+ /**
+ * Draws an outline around a shape using the current stroke and paint.
+ *
+ * @param shape the shape (<code>null</code> not permitted).
+ *
+ * @see #getStroke()
+ * @see #getPaint()
+ */
+ public abstract void draw(Shape shape);
+
+ public abstract boolean drawImage(Image image, AffineTransform xform,
+ ImageObserver obs);
+
+ public abstract void drawImage(BufferedImage image,
+ BufferedImageOp op,
+ int x,
+ int y);
+
+ public abstract void drawRenderedImage(RenderedImage image,
+ AffineTransform xform);
+
+ public abstract void drawRenderableImage(RenderableImage image,
+ AffineTransform xform);
+
+ /**
+ * Draws a string at the specified location, using the current font.
+ *
+ * @param text the string to draw.
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ *
+ * @see Graphics#setFont(Font)
+ */
+ public abstract void drawString(String text, int x, int y);
+
+ /**
+ * Draws a string at the specified location, using the current font.
+ *
+ * @param text the string to draw.
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ *
+ * @see Graphics#setFont(Font)
+ */
+ public abstract void drawString(String text, float x, float y);
+
+ /**
+ * Draws an attributed string at the specified location.
+ *
+ * @param iterator the source of the attributed text.
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ */
+ public abstract void drawString(AttributedCharacterIterator iterator,
+ int x, int y);
+
+ /**
+ * Draws an attributed string at the specified location.
+ *
+ * @param iterator the source of the attributed text.
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ */
+ public abstract void drawString(AttributedCharacterIterator iterator,
+ float x, float y);
+
+ /**
+ * Fills the interior of the specified <code>shape</code> using the current
+ * paint.
+ *
+ * @param shape the shape to fill (<code>null</code> not permitted).
+ *
+ * @see #draw(Shape)
+ * @see #getPaint()
+ */
+ public abstract void fill(Shape shape);
+
+ public abstract boolean hit(Rectangle rect, Shape text,
+ boolean onStroke);
+
+ public abstract GraphicsConfiguration getDeviceConfiguration();
+
+ /**
+ * Sets the current compositing rule.
+ *
+ * @param comp the composite.
+ *
+ * @see #getComposite()
+ */
+ public abstract void setComposite(Composite comp);
+
+ /**
+ * Sets the paint to be used for subsequent drawing operations.
+ *
+ * @param paint the paint (<code>null</code> not permitted).
+ *
+ * @see #getPaint()
+ */
+ public abstract void setPaint(Paint paint);
+
+ /**
+ * Sets the stroke to be used for subsequent drawing operations.
+ *
+ * @param stroke the stroke (<code>null</code> not permitted).
+ *
+ * @see #getStroke()
+ */
+ public abstract void setStroke(Stroke stroke);
+
+ /**
+ * Adds or updates a hint in the current rendering hints table.
+ *
+ * @param hintKey the hint key.
+ * @param hintValue the hint value.
+ */
+ public abstract void setRenderingHint(RenderingHints.Key hintKey,
+ Object hintValue);
+
+ /**
+ * Returns the current value of a rendering hint.
+ *
+ * @param hintKey the key for the hint.
+ *
+ * @return The value for the specified hint.
+ */
+ public abstract Object getRenderingHint(RenderingHints.Key hintKey);
+
+ /**
+ * Replaces the current rendering hints with the supplied hints.
+ *
+ * @param hints the hints.
+ *
+ * @see #addRenderingHints(Map)
+ */
+ public abstract void setRenderingHints(Map<?,?> hints);
+
+ /**
+ * Adds/updates the rendering hint.
+ *
+ * @param hints the hints to add or update.
+ */
+ public abstract void addRenderingHints(Map<?,?> hints);
+
+ /**
+ * Returns the current rendering hints.
+ *
+ * @return The current rendering hints.
+ */
+ public abstract RenderingHints getRenderingHints();
+
+ public abstract void translate(int x, int y);
+
+ public abstract void translate(double tx, double ty);
+
+ public abstract void rotate(double theta);
+
+ public abstract void rotate(double theta, double x, double y);
+
+ public abstract void scale(double scaleX, double scaleY);
+
+ public abstract void shear(double shearX, double shearY);
+
+ /**
+ * Sets the current transform to a concatenation of <code>transform</code>
+ * and the existing transform.
+ *
+ * @param transform the transform.
+ */
+ public abstract void transform(AffineTransform transform);
+
+ /**
+ * Sets the current transform. If the caller specifies a <code>null</code>
+ * transform, this method should set the current transform to the
+ * identity transform.
+ *
+ * @param transform the transform (<code>null</code> permitted).
+ *
+ * @see #getTransform()
+ */
+ public abstract void setTransform(AffineTransform transform);
+
+ /**
+ * Returns the current transform.
+ *
+ * @return The current transform.
+ *
+ * @see #setTransform(AffineTransform)
+ */
+ public abstract AffineTransform getTransform();
+
+ /**
+ * Returns the current paint.
+ *
+ * @return The current paint.
+ *
+ * @see #setPaint(Paint)
+ */
+ public abstract Paint getPaint();
+
+ /**
+ * Returns the current compositing rule.
+ *
+ * @return The current compositing rule.
+ *
+ * @see #setComposite(Composite)
+ */
+ public abstract Composite getComposite();
+
+ /**
+ * Sets the background color (used by the
+ * {@link Graphics#clearRect(int, int, int, int)} method).
+ *
+ * @param color the color.
+ *
+ * @see #getBackground()
+ */
+ public abstract void setBackground(Color color);
+
+ /**
+ * Returns the color used by the
+ * {@link Graphics#clearRect(int, int, int, int)} method.
+ *
+ * @return The background color.
+ *
+ * @see #setBackground(Color)
+ */
+ public abstract Color getBackground();
+
+ /**
+ * Returns the current stroke.
+ *
+ * @return The current stroke.
+ *
+ * @see #setStroke(Stroke)
+ */
+ public abstract Stroke getStroke();
+
+ /**
+ * Sets the clip region to the intersection of the current clipping region
+ * and <code>s</code>.
+ *
+ * @param s the shape to intersect with the current clipping region.
+ *
+ * @see Graphics#setClip(Shape)
+ */
+ public abstract void clip(Shape s);
+
+ /**
+ * Returns the font render context.
+ *
+ * @return The font render context.
+ */
+ public abstract FontRenderContext getFontRenderContext();
+
+ /**
+ * Draws a glyph vector at the specified location.
+ *
+ * @param g the glyph vector.
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ */
+ public abstract void drawGlyphVector(GlyphVector g, float x, float y);
+}
diff --git a/libjava/classpath/java/awt/GraphicsConfigTemplate.java b/libjava/classpath/java/awt/GraphicsConfigTemplate.java
new file mode 100644
index 000000000..e46888378
--- /dev/null
+++ b/libjava/classpath/java/awt/GraphicsConfigTemplate.java
@@ -0,0 +1,106 @@
+/* GraphicsConfigTemplate.java -- a template for selecting configurations
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.io.Serializable;
+
+/**
+ * This allows filtering an array of GraphicsConfigurations for the best
+ * one based on various requirements. The resulting configuration has had
+ * all non-default attributes set as required to meet or exceed the request.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see GraphicsConfiguration
+ * @see GraphicsDevice
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public abstract class GraphicsConfigTemplate implements Serializable
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = -8061369279557787079L;
+
+ /** States that a feature is required to select a configuration. */
+ public static final int REQUIRED = 1;
+
+ /**
+ * States that a feature is preferred, but not required, to select a
+ * configuration. In the case of multiple valid configurations, the tie
+ * breaks in favor of the one with the feature.
+ */
+ public static final int PREFERRED = 2;
+
+ /**
+ * States that a feature is not necessary in the configuration. In the case
+ * of multiple valid configurations, the tie breaks in favor of the one
+ * without the feature, to reduce overhead.
+ */
+ public static final int UNNECESSARY = 3;
+
+ /**
+ * The default constructor.
+ */
+ public GraphicsConfigTemplate()
+ {
+ }
+
+ /**
+ * Returns the "best" match among the array of possible configurations, given
+ * the criteria of this template.
+ *
+ * @param array the array to choose from
+ * @return the best match
+ * @throws NullPointerException if array is null
+ */
+ public abstract GraphicsConfiguration getBestConfiguration
+ (GraphicsConfiguration[] array);
+
+ /**
+ * Returns true if the given configuration supports all the features required
+ * by this template.
+ *
+ * @param config the configuration to test
+ * @return true if it is a match
+ * @throws NullPointerException if config is null
+ */
+ public abstract boolean isGraphicsConfigSupported
+ (GraphicsConfiguration config);
+} // class GraphicsConfigTemplate
diff --git a/libjava/classpath/java/awt/GraphicsConfiguration.java b/libjava/classpath/java/awt/GraphicsConfiguration.java
new file mode 100644
index 000000000..bbd9820c9
--- /dev/null
+++ b/libjava/classpath/java/awt/GraphicsConfiguration.java
@@ -0,0 +1,275 @@
+/* GraphicsConfiguration.java -- describes characteristics of graphics
+ Copyright (C) 2000, 2001, 2002 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.geom.AffineTransform;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.VolatileImage;
+
+/**
+ * This class describes the configuration of various graphics devices, such
+ * as a monitor or printer. Different configurations may exist for the same
+ * device, according to the different native modes supported.
+ *
+ * <p>Virtual devices are supported (for example, in a multiple screen
+ * environment, a virtual device covers all screens simultaneously); the
+ * configuration will have a non-zero relative coordinate system in such
+ * a case.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Window
+ * @see Frame
+ * @see GraphicsEnvironment
+ * @see GraphicsDevice
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public abstract class GraphicsConfiguration
+{
+
+ /** The cached image capabilities. */
+ private ImageCapabilities imageCapabilities;
+
+ /** The cached buffer capabilities. */
+ private BufferCapabilities bufferCapabilities;
+
+ /**
+ * The default constructor.
+ *
+ * @see GraphicsDevice#getConfigurations()
+ * @see GraphicsDevice#getDefaultConfiguration()
+ * @see GraphicsDevice#getBestConfiguration(GraphicsConfigTemplate)
+ * @see Graphics2D#getDeviceConfiguration()
+ */
+ protected GraphicsConfiguration ()
+ {
+ }
+
+ /**
+ * Gets the associated device that this configuration describes.
+ *
+ * @return the device
+ */
+ public abstract GraphicsDevice getDevice();
+
+ /**
+ * Returns a buffered image optimized to this device, so that blitting can
+ * be supported in the buffered image.
+ *
+ * @param w the width of the buffer
+ * @param h the height of the buffer
+ * @return the buffered image, or null if none is supported
+ */
+ public abstract BufferedImage createCompatibleImage(int w, int h);
+
+ /**
+ * Returns a buffered volatile image optimized to this device, so that
+ * blitting can be supported in the buffered image. Because the buffer is
+ * volatile, it can be optimized by native graphics accelerators.
+ *
+ * @param w the width of the buffer
+ * @param h the height of the buffer
+ * @return the buffered image, or null if none is supported
+ * @see Component#createVolatileImage(int, int)
+ * @since 1.4
+ */
+ public abstract VolatileImage createCompatibleVolatileImage(int w, int h);
+
+ /**
+ * Returns a buffered volatile image optimized to this device, and with the
+ * given capabilities, so that blitting can be supported in the buffered
+ * image. Because the buffer is volatile, it can be optimized by native
+ * graphics accelerators.
+ *
+ * @param w the width of the buffer
+ * @param h the height of the buffer
+ * @param caps the desired capabilities of the image buffer
+ * @return the buffered image, or null if none is supported
+ * @throws AWTException if the capabilities cannot be met
+ * @since 1.4
+ */
+ public VolatileImage createCompatibleVolatileImage(int w, int h,
+ ImageCapabilities caps)
+ throws AWTException
+ {
+ // Must be overridden by implementations to check caps.
+ return createCompatibleVolatileImage(w, h);
+ }
+
+ /**
+ * Returns a buffered volatile image optimized to this device, and
+ * with the given transparency. Because the buffer is volatile, it
+ * can be optimized by native graphics accelerators.
+ *
+ * @param width the width of the buffer
+ * @param height the height of the buffer
+ * @param transparency the transparency value for the buffer
+ * @return the buffered image, or null if none is supported
+ * @since 1.5
+ */
+ public abstract VolatileImage createCompatibleVolatileImage(int width,
+ int height,
+ int transparency);
+
+ /**
+ * Creates a volatile image with the specified capabilities and transparency.
+ * If the backend cannot meet the requested capabilities and transparency,
+ * an AWTException is thrown.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ * @param caps the requested capabilities
+ * @param transparency the required transparency
+ *
+ * @return a volatile image with the specified capabilites and transparency
+ *
+ * @throws AWTException if the required capabilities and transparency cannot
+ * be met
+ *
+ * @since 1.5
+ */
+ public VolatileImage createCompatibleVolatileImage(int width, int height,
+ ImageCapabilities caps,
+ int transparency)
+ throws AWTException
+ {
+ // Must be overridden by implementations to check caps.
+ return createCompatibleVolatileImage(width, height, transparency);
+ }
+
+ /**
+ * Returns a buffered image optimized to this device, and with the specified
+ * transparency, so that blitting can be supported in the buffered image.
+ *
+ * @param w the width of the buffer
+ * @param h the height of the buffer
+ * @param transparency the transparency of the buffer
+ * @return the buffered image, or null if none is supported
+ * @see Transparency#OPAQUE
+ * @see Transparency#BITMASK
+ * @see Transparency#TRANSLUCENT
+ */
+ public abstract BufferedImage createCompatibleImage(int w, int h,
+ int transparency);
+
+ /**
+ * Gets the color model of the corresponding device.
+ *
+ * @return the color model
+ */
+ public abstract ColorModel getColorModel();
+
+ /**
+ * Gets a color model for the corresponding device which supports the desired
+ * transparency level.
+ *
+ * @param transparency the transparency of the model
+ * @return the color model, with transparency
+ * @see Transparency#OPAQUE
+ * @see Transparency#BITMASK
+ * @see Transparency#TRANSLUCENT
+ */
+ public abstract ColorModel getColorModel(int transparency);
+
+ /**
+ * Returns a transform that maps user coordinates to device coordinates. The
+ * preferred mapping is about 72 user units to 1 inch (2.54 cm) of physical
+ * space. This is often the identity transform. The device coordinates have
+ * the origin at the upper left, with increasing x to the right, and
+ * increasing y to the bottom.
+ *
+ * @return the transformation from user space to device space
+ * @see #getNormalizingTransform()
+ */
+ public abstract AffineTransform getDefaultTransform();
+
+ /**
+ * Returns a transform that maps user coordinates to device coordinates. The
+ * exact mapping is 72 user units to 1 inch (2.54 cm) of physical space.
+ * This is often the identity transform. The device coordinates have the
+ * origin at the upper left, with increasing x to the right, and increasing
+ * y to the bottom. Note that this is more accurate (and thus, sometimes more
+ * costly) than the default transform.
+ *
+ * @return the normalized transformation from user space to device space
+ * @see #getDefaultTransform()
+ */
+ public abstract AffineTransform getNormalizingTransform();
+
+ /**
+ * Returns the bounds of the configuration, in device coordinates. If this
+ * is a virtual device (for example, encompassing several screens), the
+ * bounds may have a non-zero origin.
+ *
+ * @return the device bounds
+ * @since 1.3
+ */
+ public abstract Rectangle getBounds();
+
+ /**
+ * Returns the buffering capabilities of this configuration.
+ *
+ * @return the buffer capabilities
+ * @since 1.4
+ */
+ public BufferCapabilities getBufferCapabilities()
+ {
+ if (imageCapabilities == null)
+ getImageCapabilities();
+
+ if (bufferCapabilities == null)
+ bufferCapabilities = new BufferCapabilities(imageCapabilities,
+ imageCapabilities, null);
+ return bufferCapabilities;
+ }
+
+ /**
+ * Returns the imaging capabilities of this configuration.
+ *
+ * @return the image capabilities
+ * @since 1.4
+ */
+ public ImageCapabilities getImageCapabilities()
+ {
+ if (imageCapabilities == null)
+ imageCapabilities = new ImageCapabilities(false);
+ return imageCapabilities;
+ }
+} // class GraphicsConfiguration
diff --git a/libjava/classpath/java/awt/GraphicsDevice.java b/libjava/classpath/java/awt/GraphicsDevice.java
new file mode 100644
index 000000000..c99c14b1b
--- /dev/null
+++ b/libjava/classpath/java/awt/GraphicsDevice.java
@@ -0,0 +1,292 @@
+/* GraphicsDevice.java -- information about a graphics device
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.image.VolatileImage;
+
+/**
+ * This describes a graphics device available to the given environment. This
+ * includes screen and printer devices, and the different configurations for
+ * each device. Also, this allows you to create virtual devices which operate
+ * over a multi-screen environment.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see GraphicsEnvironment
+ * @see GraphicsConfiguration
+ * @since 1.3
+ * @status updated to 1.4
+ */
+public abstract class GraphicsDevice
+{
+ /** Device is a raster screen. */
+ public static final int TYPE_RASTER_SCREEN = 0;
+
+ /** Device is a printer. */
+ public static final int TYPE_PRINTER = 1;
+
+ /** Device is an image buffer not visible to the user. */
+ public static final int TYPE_IMAGE_BUFFER = 2;
+
+ /** The current full-screen window, or null if there is none. */
+ private Window full_screen;
+
+ /**
+ * The bounds of the fullscreen window before it has been switched to full
+ * screen.
+ */
+ private Rectangle fullScreenOldBounds;
+
+ /** The current display mode, or null if unknown. */
+ private DisplayMode mode;
+
+ /**
+ * The default constructor.
+ *
+ * @see GraphicsEnvironment#getScreenDevices()
+ * @see GraphicsEnvironment#getDefaultScreenDevice()
+ * @see GraphicsConfiguration#getDevice()
+ */
+ protected GraphicsDevice()
+ {
+ }
+
+ /**
+ * Returns the type of the device.
+ *
+ * @return the device type
+ * @see #TYPE_RASTER_SCREEN
+ * @see #TYPE_PRINTER
+ * @see #TYPE_IMAGE_BUFFER
+ */
+ public abstract int getType();
+
+ /**
+ * Returns an identification string for the device. This can be
+ * vendor-specific, and may be useful for debugging.
+ *
+ * @return the identification
+ */
+ public abstract String getIDstring();
+
+ /**
+ * Return all configurations valid for this device.
+ *
+ * @return an array of configurations
+ */
+ public abstract GraphicsConfiguration[] getConfigurations();
+
+ /**
+ * Return the default configuration for this device.
+ *
+ * @return the default configuration
+ */
+ public abstract GraphicsConfiguration getDefaultConfiguration();
+
+ /**
+ * Return the best configuration, according to the criteria in the given
+ * template.
+ *
+ * @param template the template to adjust by
+ * @return the best configuration
+ * @throws NullPointerException if template is null
+ */
+ public GraphicsConfiguration getBestConfiguration
+ (GraphicsConfigTemplate template)
+ {
+ return template.getBestConfiguration(getConfigurations());
+ }
+
+ /**
+ * Returns true if the device supports full-screen exclusive mode. The
+ * default implementation returns true; subclass it if this is not the case.
+ *
+ * @return true if full screen support is available
+ * @since 1.4
+ */
+ public boolean isFullScreenSupported()
+ {
+ return true;
+ }
+
+ /**
+ * Toggle the given window between full screen and normal mode. The previous
+ * full-screen window, if different, is restored; if the given window is
+ * null, no window will be full screen. If
+ * <code>isFullScreenSupported()</code> returns true, full screen mode is
+ * considered to be exclusive, which implies:<ul>
+ * <li>Windows cannot overlap the full-screen window. All other application
+ * windows will always appear beneath the full-screen window in the
+ * Z-order.</li>
+ * <li>Input method windows are disabled. It is advisable to call
+ * <code>Component.enableInputMethods(false)</code> to make a component
+ * a non-client of the input method framework.</li>
+ * </ul><br>
+ * If <code>isFullScreenSupported()</code> returns false, full-screen
+ * exclusive mode is simulated by resizing the window to the size of the
+ * screen and positioning it at (0,0). This is also what this method does.
+ * If a device supports real fullscreen mode then it should override this
+ * method as well as #isFullScreenSupported and #getFullScreenWindow.
+ *
+ * @param w the window to toggle
+ * @see #isFullScreenSupported()
+ * @see #getFullScreenWindow()
+ * @see #setDisplayMode(DisplayMode)
+ * @see Component#enableInputMethods(boolean)
+ * @since 1.4
+ */
+ public synchronized void setFullScreenWindow(Window w)
+ {
+ // Restore the previous window to normal mode and release the reference.
+ if (full_screen != null)
+ {
+ full_screen.setBounds(fullScreenOldBounds);
+ }
+
+ full_screen = null;
+
+ // If w != null, make it full-screen.
+ if (w != null)
+ {
+ fullScreenOldBounds = w.getBounds();
+ full_screen = w;
+ DisplayMode dMode = getDisplayMode();
+ full_screen.setBounds(0, 0, dMode.getWidth(), dMode.getHeight());
+ full_screen.requestFocus();
+ full_screen.setLocationRelativeTo(null);
+ }
+ }
+
+ /**
+ * Returns the current full-screen window of the device, or null if no
+ * window is full-screen.
+ *
+ * @return the full-screen window
+ * @see #setFullScreenWindow(Window)
+ * @since 1.4
+ */
+ public Window getFullScreenWindow()
+ {
+ return full_screen;
+ }
+
+ /**
+ * Returns whether this device supports low-level display changes. This may
+ * depend on whether full-screen exclusive mode is available.
+ *
+ * XXX The default implementation returns false for now.
+ *
+ * @return true if display changes are supported
+ * @see #setDisplayMode(DisplayMode)
+ * @since 1.4
+ */
+ public boolean isDisplayChangeSupported()
+ {
+ return false;
+ }
+
+ /**
+ * Sets the display mode. This may be dependent on the availability of
+ * full-screen exclusive mode.
+ *
+ * @param mode the new mode
+ * @throws IllegalArgumentException if the new mode is not in getDisplayModes
+ * @throws UnsupportedOperationException if ! isDisplayChangeSupported()
+ * @see #getDisplayMode()
+ * @see #getDisplayModes()
+ * @see #isDisplayChangeSupported()
+ * @since 1.4
+ */
+ public void setDisplayMode(DisplayMode mode)
+ {
+ DisplayMode[] array = getDisplayModes();
+ if (! isDisplayChangeSupported())
+ throw new UnsupportedOperationException();
+ int i = array == null ? 0 : array.length;
+ while (--i >= 0)
+ if (array[i].equals(mode))
+ break;
+ if (i < 0)
+ throw new IllegalArgumentException();
+ this.mode = mode;
+ }
+
+ /**
+ * Returns the current display mode of this device, or null if unknown.
+ *
+ * @return the current display mode
+ * @see #setDisplayMode(DisplayMode)
+ * @see #getDisplayModes()
+ * @since 1.4
+ */
+ public DisplayMode getDisplayMode()
+ {
+ return mode;
+ }
+
+ /**
+ * Return an array of all available display modes. This implementation
+ * returns a 0-length array, so subclasses must override this.
+ *
+ * @return the array of available modes
+ * @since 1.4
+ */
+ public DisplayMode[] getDisplayModes()
+ {
+ return new DisplayMode[0];
+ }
+
+ /**
+ * Return the number of bytes available in accelerated memory on this
+ * device. The device may support creation or caching on a first-come,
+ * first-served basis, depending on the operating system and driver.
+ * Memory may be a finite resource, and because of multi-threading, you
+ * are not guaranteed that the result of this method ensures your image
+ * will successfully be put in accelerated memory. A negative result means
+ * the memory is unlimited. The default implementation assumes no special
+ * memory is available, and returns 0.
+ *
+ * @return the size of accelerated memory available
+ * @see VolatileImage#flush()
+ * @see ImageCapabilities#isAccelerated()
+ */
+ public int getAvailableAcceleratedMemory()
+ {
+ return 0;
+ }
+} // class GraphicsDevice
diff --git a/libjava/classpath/java/awt/GraphicsEnvironment.java b/libjava/classpath/java/awt/GraphicsEnvironment.java
new file mode 100644
index 000000000..a82e7a357
--- /dev/null
+++ b/libjava/classpath/java/awt/GraphicsEnvironment.java
@@ -0,0 +1,244 @@
+/* GraphicsEnvironment.java -- information about the graphics environment
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import gnu.java.awt.ClasspathToolkit;
+import gnu.classpath.SystemProperties;
+import java.awt.image.BufferedImage;
+import java.util.Locale;
+
+/**
+ * This descibes the collection of GraphicsDevice and Font objects available
+ * on a given platform. The resources might be local or remote, and specify
+ * the valid configurations for displaying graphics.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see GraphicsDevice
+ * @see GraphicsConfiguration
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public abstract class GraphicsEnvironment
+{
+ private static GraphicsEnvironment localGraphicsEnvironment;
+
+ /**
+ * The environment must be obtained from a factory or query method, hence
+ * this constructor is protected.
+ */
+ protected GraphicsEnvironment()
+ {
+ }
+
+ /**
+ * Returns the local graphics environment. If the java.awt.graphicsenv
+ * system property is set, it instantiates the specified class,
+ * otherwise it assume that the awt toolkit is a ClasspathToolkit
+ * and delegates to it to create the instance.
+ *
+ * @return the local environment
+ */
+ public static GraphicsEnvironment getLocalGraphicsEnvironment()
+ {
+ if (localGraphicsEnvironment != null)
+ return localGraphicsEnvironment;
+
+ String graphicsenv = SystemProperties.getProperty("java.awt.graphicsenv",
+ null);
+ if (graphicsenv != null)
+ {
+ try
+ {
+ // We intentionally use the bootstrap class loader.
+ localGraphicsEnvironment = (GraphicsEnvironment)
+ Class.forName(graphicsenv).newInstance();
+ return localGraphicsEnvironment;
+ }
+ catch (Exception x)
+ {
+ throw (InternalError)
+ new InternalError("Unable to instantiate java.awt.graphicsenv")
+ .initCause(x);
+ }
+ }
+ else
+ {
+ ClasspathToolkit tk;
+ tk = ((ClasspathToolkit) Toolkit.getDefaultToolkit());
+ localGraphicsEnvironment = tk.getLocalGraphicsEnvironment();
+ return localGraphicsEnvironment;
+ }
+ }
+
+ /**
+ * Check if the local environment is headless, meaning that it does not
+ * support a display, keyboard, or mouse. Many methods in the Abstract
+ * Windows Toolkit (java.awt) throw a {@link HeadlessException} if this
+ * returns true.
+ *
+ * This method returns true if the java.awt.headless property is set
+ * to "true".
+ *
+ * @return true if the environment is headless, meaning that graphics are
+ * unsupported
+ * @since 1.4
+ */
+ public static boolean isHeadless()
+ {
+ String headless = SystemProperties.getProperty("java.awt.headless", null);
+ return "true".equalsIgnoreCase(headless);
+ }
+
+ /**
+ * Check if the given environment is headless, meaning that it does not
+ * support a display, keyboard, or mouse. Many methods in the Abstract
+ * Windows Toolkit (java.awt) throw a {@link HeadlessException} if this
+ * returns true. This default implementation returns isHeadless(), so
+ * subclasses need only override it if they differ.
+ *
+ * @return true if the environment is headless, meaning that graphics are
+ * unsupported
+ * @since 1.4
+ */
+ public boolean isHeadlessInstance()
+ {
+ return isHeadless();
+ }
+
+ /**
+ * Get an array of all the GraphicsDevice objects.
+ *
+ * @return the available graphics devices, may be 0 length
+ * @throws HeadlessException if the environment is headless
+ */
+ public abstract GraphicsDevice[] getScreenDevices();
+
+ /**
+ * Get the default screen GraphicsDevice object.
+ *
+ * @return the default screen device
+ * @throws HeadlessException if the environment is headless
+ */
+ public abstract GraphicsDevice getDefaultScreenDevice();
+
+ /**
+ * Return a Graphics2D object which will render into the specified image.
+ *
+ * @param image the image to render into
+ * @return the object that renders into the image
+ */
+ public abstract Graphics2D createGraphics(BufferedImage image);
+
+ /**
+ * Returns an array of the one-point size fonts available in this
+ * environment. From there, the user can select the font and derive the
+ * correct one of proper size and attributes, using <code>deriveFont</code>.
+ * Only one master version of each font appears in this array; if a font
+ * can be derived from another, it must be created in that way.
+ *
+ * @return the array of available fonts
+ * @see #getAvailableFontFamilyNames()
+ * @see Font#deriveFont(int, float)
+ * @since 1.2
+ */
+ public abstract Font[] getAllFonts();
+
+ /**
+ * Returns an array of the font family names available in this environment.
+ * This allows flexibility in choosing the style of font, while still letting
+ * the Font class decide its best match.
+ *
+ * @return the array of available font families
+ * @see #getAllFonts()
+ * @see Font#getFamily()
+ * @since 1.2
+ */
+ public abstract String[] getAvailableFontFamilyNames();
+
+ /**
+ * Returns an array of the font family names available in this environment,
+ * localized to the current Locale if l is non-null. This allows
+ * flexibility in choosing the style of font, while still letting the Font
+ * class decide its best match.
+ *
+ * @param l the locale to use
+ * @return the array of available font families, localized
+ * @see #getAllFonts()
+ * @see Font#getFamily()
+ * @since 1.2
+ */
+ public abstract String[] getAvailableFontFamilyNames(Locale l);
+
+ /**
+ * Returns the point where a window should be centered. You should probably
+ * also check that the window fits within the screen bounds. The default
+ * simply returns the center of the maximum window bounds; subclasses should
+ * override this if native objects (like scrollbars) make that off-centered.
+ *
+ * @return the centering point
+ * @throws HeadlessException if the environment is headless
+ * @see #getMaximumWindowBounds()
+ * @since 1.4
+ */
+ public Point getCenterPoint()
+ {
+ Rectangle r = getMaximumWindowBounds();
+ return new Point(r.x + r.width / 2, r.y + r.height / 2);
+ }
+
+ /**
+ * Returns the maximum bounds for a centered window object. The default
+ * implementation simply returns the bounds of the default configuration
+ * of the default screen; subclasses should override this to if native
+ * objects (like scrollbars) reduce what is truly available. Also,
+ * subclasses should override this if the window should be centered across
+ * a multi-screen display.
+ *
+ * @return the maximum window bounds
+ * @throws HeadlessException if the environment is headless
+ * @see #getCenterPoint()
+ * @see GraphicsConfiguration#getBounds()
+ * @see Toolkit#getScreenInsets(GraphicsConfiguration)
+ * @since 1.4
+ */
+ public Rectangle getMaximumWindowBounds()
+ {
+ return getDefaultScreenDevice().getDefaultConfiguration().getBounds();
+ }
+} // class GraphicsEnvironment
diff --git a/libjava/classpath/java/awt/GridBagConstraints.java b/libjava/classpath/java/awt/GridBagConstraints.java
new file mode 100644
index 000000000..823130058
--- /dev/null
+++ b/libjava/classpath/java/awt/GridBagConstraints.java
@@ -0,0 +1,246 @@
+/* GridBagConstraints.java -- Constraints for GridBag layout manager
+ Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.io.Serializable;
+
+/**
+ * This specifies the constraints for a component managed by the
+ * GridBagLayout layout manager.
+ */
+public class GridBagConstraints implements Cloneable, Serializable
+{
+ static final long serialVersionUID = -1000070633030801713L;
+
+ // Fill values.
+ /**
+ * Don't fill.
+ */
+ public static final int NONE = 0;
+
+ /**
+ * Fill in both directions.
+ */
+ public static final int BOTH = 1;
+
+ /**
+ * Fill horizontally.
+ */
+ public static final int HORIZONTAL = 2;
+
+ /**
+ * Fill vertically.
+ */
+ public static final int VERTICAL = 3;
+
+ // Anchor values.
+ /**
+ * Position in the center.
+ */
+ public static final int CENTER = 10;
+
+ /**
+ * Position to the north.
+ */
+ public static final int NORTH = 11;
+
+ /**
+ * Position to the northeast.
+ */
+ public static final int NORTHEAST = 12;
+
+ /**
+ * Position to the east.
+ */
+ public static final int EAST = 13;
+
+ /**
+ * Position to the southeast.
+ */
+ public static final int SOUTHEAST = 14;
+
+ /**
+ * Position to the south.
+ */
+ public static final int SOUTH = 15;
+
+ /**
+ * Position to the southwest.
+ */
+ public static final int SOUTHWEST = 16;
+
+ /**
+ * Position to the west.
+ */
+ public static final int WEST = 17;
+
+ /**
+ * Position to the northwest.
+ */
+ public static final int NORTHWEST = 18;
+
+ // gridx and gridy values.
+ /**
+ * Occupy all remaining cells except last cell.
+ */
+ public static final int RELATIVE = -1;
+
+ /**
+ * Occupy all remaining cells.
+ */
+ public static final int REMAINDER = 0;
+
+ /**
+ * Position to where a page starts. Equals NORTH for horizontal orientations.
+ */
+ public static final int PAGE_START = 19;
+
+ /**
+ * Position to where a page ends. Equals SOUTH for horizontal orientations.
+ */
+ public static final int PAGE_END = 20;
+
+ /**
+ * Position to where a text line would start. Equals to WEST for
+ * left-to-right orientations.
+ */
+ public static final int LINE_START = 21;
+
+ /**
+ * Position to where a text line would end. Equals to EAST for
+ * left-to-right orientations.
+ */
+ public static final int LINE_END = 22;
+
+ /**
+ * Position to where the first text line would start. Equals to NORTHWEST for
+ * horizontal left-to-right orientations.
+ */
+ public static final int FIRST_LINE_START = 23;
+
+ /**
+ * Position to where the first text line would end. Equals to NORTHEAST for
+ * horizontal left-to-right orientations.
+ */
+ public static final int FIRST_LINE_END = 24;
+
+ /**
+ * Position to where the last text line would start. Equals to SOUTHWEST for
+ * horizontal left-to-right orientations.
+ */
+ public static final int LAST_LINE_START = 25;
+
+ /**
+ * Position to where the last text line would end. Equals to SOUTHEAST for
+ * horizontal left-to-right orientations.
+ */
+ public static final int LAST_LINE_END = 26;
+
+ public int anchor;
+ public int fill;
+ public int gridheight;
+ public int gridwidth;
+ public int gridx;
+ public int gridy;
+ public Insets insets;
+ public int ipadx;
+ public int ipady;
+ public double weightx;
+ public double weighty;
+
+ /**
+ * Create a copy of this object.
+ */
+ public Object clone ()
+ {
+ try
+ {
+ GridBagConstraints g = (GridBagConstraints) super.clone ();
+ g.insets = (Insets) insets.clone ();
+ return g;
+ }
+ catch (CloneNotSupportedException _)
+ {
+ // Can't happen.
+ return null;
+ }
+ }
+
+ /**
+ * Create a new GridBagConstraints object with the default
+ * parameters.
+ */
+ public GridBagConstraints ()
+ {
+ this.anchor = CENTER;
+ this.fill = NONE;
+ this.gridx = RELATIVE;
+ this.gridy = RELATIVE;
+ this.gridwidth = 1;
+ this.gridheight = 1;
+ this.ipadx = 0;
+ this.ipady = 0;
+ this.insets = new Insets (0, 0, 0, 0);
+ this.weightx = 0;
+ this.weighty = 0;
+ }
+
+ /**
+ * Create a new GridBagConstraints object with the indicated
+ * parameters.
+ */
+ public GridBagConstraints (int gridx, int gridy,
+ int gridwidth, int gridheight,
+ double weightx, double weighty,
+ int anchor, int fill,
+ Insets insets, int ipadx, int ipady)
+ {
+ this.anchor = anchor;
+ this.fill = fill;
+ this.gridx = gridx;
+ this.gridy = gridy;
+ this.gridwidth = gridwidth;
+ this.gridheight = gridheight;
+ this.ipadx = ipadx;
+ this.ipady = ipady;
+ this.insets = insets;
+ this.weightx = weightx;
+ this.weighty = weighty;
+ }
+}
diff --git a/libjava/classpath/java/awt/GridBagLayout.java b/libjava/classpath/java/awt/GridBagLayout.java
new file mode 100644
index 000000000..224d53ff2
--- /dev/null
+++ b/libjava/classpath/java/awt/GridBagLayout.java
@@ -0,0 +1,1114 @@
+/* GridBagLayout - Layout manager for components according to GridBagConstraints
+ Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Hashtable;
+
+/**
+ * @author Michael Koch (konqueror@gmx.de)
+ * @author Jeroen Frijters (jeroen@frijters.net)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+public class GridBagLayout
+ implements Serializable, LayoutManager2
+{
+ private static final long serialVersionUID = 8838754796412211005L;
+
+ protected static final int MINSIZE = 1;
+ protected static final int PREFERREDSIZE = 2;
+ protected static final int MAXGRIDSIZE = 512;
+
+ // comptable remembers the original contraints given to us.
+ // internalcomptable is used to keep track of modified constraint values
+ // that we calculate, particularly when we are given RELATIVE and
+ // REMAINDER constraints.
+ // Constraints kept in comptable are never modified, and constraints
+ // kept in internalcomptable can be modified internally only.
+ protected Hashtable<Component,GridBagConstraints> comptable;
+ private Hashtable<Component,GridBagConstraints> internalcomptable;
+ protected GridBagLayoutInfo layoutInfo;
+ protected GridBagConstraints defaultConstraints;
+
+ public double[] columnWeights;
+ public int[] columnWidths;
+ public double[] rowWeights;
+ public int[] rowHeights;
+
+ public GridBagLayout ()
+ {
+ this.comptable = new Hashtable<Component,GridBagConstraints>();
+ this.internalcomptable = new Hashtable<Component,GridBagConstraints>();
+ this.defaultConstraints= new GridBagConstraints();
+ }
+
+ /**
+ * Helper method to calc the sum of a range of elements in an int array.
+ */
+ private int sumIntArray (int[] array, int upto)
+ {
+ int result = 0;
+
+ for (int i = 0; i < upto; i++)
+ result += array [i];
+
+ return result;
+ }
+
+ /**
+ * Helper method to calc the sum of all elements in an int array.
+ */
+ private int sumIntArray (int[] array)
+ {
+ return sumIntArray(array, array.length);
+ }
+
+ /**
+ * Helper method to calc the sum of all elements in an double array.
+ */
+ private double sumDoubleArray (double[] array)
+ {
+ double result = 0;
+
+ for (int i = 0; i < array.length; i++)
+ result += array [i];
+
+ return result;
+ }
+
+ public void addLayoutComponent (String name, Component component)
+ {
+ // do nothing here.
+ }
+
+ public void removeLayoutComponent (Component component)
+ {
+ // do nothing here
+ }
+
+ public void addLayoutComponent (Component component, Object constraints)
+ {
+ if (constraints == null)
+ return;
+
+ if (!(constraints instanceof GridBagConstraints))
+ throw new IllegalArgumentException("constraints "
+ + constraints
+ + " are not an instance of GridBagConstraints");
+
+ setConstraints (component, (GridBagConstraints) constraints);
+ }
+
+ public Dimension preferredLayoutSize (Container parent)
+ {
+ if (parent == null)
+ return new Dimension (0, 0);
+
+ GridBagLayoutInfo li = getLayoutInfo (parent, PREFERREDSIZE);
+ return getMinSize (parent, li);
+ }
+
+ public Dimension minimumLayoutSize (Container parent)
+ {
+ if (parent == null)
+ return new Dimension (0, 0);
+
+ GridBagLayoutInfo li = getLayoutInfo (parent, MINSIZE);
+ return getMinSize (parent, li);
+ }
+
+ public Dimension maximumLayoutSize (Container target)
+ {
+ return new Dimension (Integer.MAX_VALUE, Integer.MAX_VALUE);
+ }
+
+ public void layoutContainer (Container parent)
+ {
+ arrangeGrid (parent);
+ }
+
+ public float getLayoutAlignmentX (Container target)
+ {
+ return Component.CENTER_ALIGNMENT;
+ }
+
+ public float getLayoutAlignmentY (Container target)
+ {
+ return Component.CENTER_ALIGNMENT;
+ }
+
+ public void invalidateLayout (Container target)
+ {
+ this.layoutInfo = null;
+ }
+
+ public void setConstraints (Component component,
+ GridBagConstraints constraints)
+ {
+ GridBagConstraints clone = (GridBagConstraints) constraints.clone();
+
+ if (clone.gridx < 0)
+ clone.gridx = GridBagConstraints.RELATIVE;
+
+ if (clone.gridy < 0)
+ clone.gridy = GridBagConstraints.RELATIVE;
+
+ if (clone.gridwidth == 0)
+ clone.gridwidth = GridBagConstraints.REMAINDER;
+ else if (clone.gridwidth < 0)
+ clone.gridwidth = 1;
+
+ if (clone.gridheight == 0)
+ clone.gridheight = GridBagConstraints.REMAINDER;
+ else if (clone.gridheight < 0)
+ clone.gridheight = 1;
+
+ comptable.put (component, clone);
+ }
+
+ public GridBagConstraints getConstraints (Component component)
+ {
+ return (GridBagConstraints) (lookupConstraints (component).clone());
+ }
+
+ protected GridBagConstraints lookupConstraints (Component component)
+ {
+ GridBagConstraints result = comptable.get (component);
+
+ if (result == null)
+ {
+ setConstraints (component, defaultConstraints);
+ result = comptable.get (component);
+ }
+
+ return result;
+ }
+
+ private GridBagConstraints lookupInternalConstraints (Component component)
+ {
+ GridBagConstraints result = internalcomptable.get (component);
+
+ if (result == null)
+ {
+ result = (GridBagConstraints) lookupConstraints(component).clone();
+ internalcomptable.put (component, result);
+ }
+
+ return result;
+ }
+
+ /**
+ * @since 1.1
+ */
+ public Point getLayoutOrigin ()
+ {
+ if (layoutInfo == null)
+ return new Point (0, 0);
+
+ return new Point (layoutInfo.pos_x, layoutInfo.pos_y);
+ }
+
+ /**
+ * @since 1.1
+ */
+ public int[][] getLayoutDimensions ()
+ {
+ int[][] result = new int [2][];
+ if (layoutInfo == null)
+ {
+ result[0] = new int[0];
+ result[1] = new int[0];
+
+ return result;
+ }
+
+ result [0] = new int [layoutInfo.cols];
+ System.arraycopy (layoutInfo.colWidths, 0, result [0], 0, layoutInfo.cols);
+ result [1] = new int [layoutInfo.rows];
+ System.arraycopy (layoutInfo.rowHeights, 0, result [1], 0, layoutInfo.rows);
+ return result;
+ }
+
+ public double[][] getLayoutWeights ()
+ {
+ double[][] result = new double [2][];
+ if (layoutInfo == null)
+ {
+ result[0] = new double[0];
+ result[1] = new double[0];
+
+ return result;
+ }
+
+ result [0] = new double [layoutInfo.cols];
+ System.arraycopy (layoutInfo.colWeights, 0, result [0], 0, layoutInfo.cols);
+ result [1] = new double [layoutInfo.rows];
+ System.arraycopy (layoutInfo.rowWeights, 0, result [1], 0, layoutInfo.rows);
+ return result;
+ }
+
+ /**
+ * @since 1.1
+ */
+ public Point location (int x, int y)
+ {
+ if (layoutInfo == null)
+ return new Point (0, 0);
+
+ int col;
+ int row;
+ int pixel_x = layoutInfo.pos_x;
+ int pixel_y = layoutInfo.pos_y;
+
+ for (col = 0; col < layoutInfo.cols; col++)
+ {
+ int w = layoutInfo.colWidths [col];
+ if (x < pixel_x + w)
+ break;
+
+ pixel_x += w;
+ }
+
+ for (row = 0; row < layoutInfo.rows; row++)
+ {
+ int h = layoutInfo.rowHeights [row];
+ if (y < pixel_y + h)
+ break;
+
+ pixel_y += h;
+ }
+
+ return new Point (col, row);
+ }
+
+ /**
+ * Return a string representation of this GridBagLayout.
+ *
+ * @return a string representation
+ */
+ public String toString()
+ {
+ return getClass().getName();
+ }
+
+ /**
+ * Move and resize a rectangle according to a set of grid bag
+ * constraints. The x, y, width and height fields of the
+ * rectangle argument are adjusted to the new values.
+ *
+ * @param constraints position and size constraints
+ * @param r rectangle to be moved and resized
+ */
+ protected void AdjustForGravity (GridBagConstraints constraints,
+ Rectangle r)
+ {
+ Insets insets = constraints.insets;
+ if (insets != null)
+ {
+ r.x += insets.left;
+ r.y += insets.top;
+ r.width -= insets.left + insets.right;
+ r.height -= insets.top + insets.bottom;
+ }
+ }
+
+ /**
+ * Obsolete.
+ */
+ protected void ArrangeGrid (Container parent)
+ {
+ Component[] components = parent.getComponents();
+
+ if (components.length == 0)
+ return;
+
+ GridBagLayoutInfo info = getLayoutInfo (parent, PREFERREDSIZE);
+ if (info.cols == 0 && info.rows == 0)
+ return;
+
+ // DEBUG
+ //dumpLayoutInfo (info);
+
+ // Calling setBounds on these components causes this layout to
+ // be invalidated, clearing the layout information cache,
+ // layoutInfo. So we wait until after this for loop to set
+ // layoutInfo.
+ Component lastComp = null;
+
+ Rectangle cell = new Rectangle();
+
+ for (int i = 0; i < components.length; i++)
+ {
+ Component component = components[i];
+
+ // If component is not visible we dont have to care about it.
+ if (! component.isVisible())
+ continue;
+
+ Dimension dim = component.getPreferredSize();
+ GridBagConstraints constraints = lookupInternalConstraints(component);
+
+ if (lastComp != null
+ && constraints.gridheight == GridBagConstraints.REMAINDER)
+ cell.y += cell.height;
+ else
+ cell.y = sumIntArray(info.rowHeights, constraints.gridy);
+
+ if (lastComp != null
+ && constraints.gridwidth == GridBagConstraints.REMAINDER)
+ cell.x += cell.width;
+ else
+ cell.x = sumIntArray(info.colWidths, constraints.gridx);
+
+ cell.width = sumIntArray(info.colWidths, constraints.gridx
+ + constraints.gridwidth) - cell.x;
+ cell.height = sumIntArray(info.rowHeights, constraints.gridy
+ + constraints.gridheight) - cell.y;
+
+ // Adjust for insets.
+ AdjustForGravity( constraints, cell );
+
+ // Note: Documentation says that padding is added on both sides, but
+ // visual inspection shows that the Sun implementation only adds it
+ // once, so we do the same.
+ dim.width += constraints.ipadx;
+ dim.height += constraints.ipady;
+
+ switch (constraints.fill)
+ {
+ case GridBagConstraints.HORIZONTAL:
+ dim.width = cell.width;
+ break;
+ case GridBagConstraints.VERTICAL:
+ dim.height = cell.height;
+ break;
+ case GridBagConstraints.BOTH:
+ dim.width = cell.width;
+ dim.height = cell.height;
+ break;
+ }
+
+ int x = 0;
+ int y = 0;
+
+ switch (constraints.anchor)
+ {
+ case GridBagConstraints.NORTH:
+ x = cell.x + (cell.width - dim.width) / 2;
+ y = cell.y;
+ break;
+ case GridBagConstraints.SOUTH:
+ x = cell.x + (cell.width - dim.width) / 2;
+ y = cell.y + cell.height - dim.height;
+ break;
+ case GridBagConstraints.WEST:
+ x = cell.x;
+ y = cell.y + (cell.height - dim.height) / 2;
+ break;
+ case GridBagConstraints.EAST:
+ x = cell.x + cell.width - dim.width;
+ y = cell.y + (cell.height - dim.height) / 2;
+ break;
+ case GridBagConstraints.NORTHEAST:
+ x = cell.x + cell.width - dim.width;
+ y = cell.y;
+ break;
+ case GridBagConstraints.NORTHWEST:
+ x = cell.x;
+ y = cell.y;
+ break;
+ case GridBagConstraints.SOUTHEAST:
+ x = cell.x + cell.width - dim.width;
+ y = cell.y + cell.height - dim.height;
+ break;
+ case GridBagConstraints.SOUTHWEST:
+ x = cell.x;
+ y = cell.y + cell.height - dim.height;
+ break;
+ default:
+ x = cell.x + (cell.width - dim.width) / 2;
+ y = cell.y + (cell.height - dim.height) / 2;
+ break;
+ }
+ component.setBounds(info.pos_x + x, info.pos_y + y, dim.width,
+ dim.height);
+ lastComp = component;
+ }
+
+ // DEBUG
+ //dumpLayoutInfo(info);
+
+ // Cache layout information.
+ layoutInfo = getLayoutInfo(parent, PREFERREDSIZE);
+ }
+
+ /**
+ * Obsolete.
+ */
+ protected GridBagLayoutInfo GetLayoutInfo (Container parent, int sizeflag)
+ {
+ if (sizeflag != MINSIZE && sizeflag != PREFERREDSIZE)
+ throw new IllegalArgumentException();
+
+ Dimension parentDim = parent.getSize ();
+ Insets parentInsets = parent.getInsets ();
+ parentDim.width -= parentInsets.left + parentInsets.right;
+ parentDim.height -= parentInsets.top + parentInsets.bottom;
+
+ int current_y = 0;
+ int max_x = 0;
+ int max_y = 0;
+
+ // Guaranteed to contain the last component added to the given row
+ // or column, whose gridwidth/height is not REMAINDER.
+ HashMap<Integer,Component> lastInRow = new HashMap<Integer,Component>();
+ HashMap<Integer,Component> lastInCol = new HashMap<Integer,Component>();
+
+ Component[] components = parent.getComponents();
+
+ // Components sorted by gridwidths/heights,
+ // smallest to largest, with REMAINDER and RELATIVE at the end.
+ // These are useful when determining sizes and weights.
+ ArrayList<Component> sortedByWidth =
+ new ArrayList<Component>(components.length);
+ ArrayList<Component> sortedByHeight =
+ new ArrayList<Component>(components.length);
+
+ // STEP 1: first we figure out how many rows/columns
+ for (int i = 0; i < components.length; i++)
+ {
+ Component component = components [i];
+ // If component is not visible we dont have to care about it.
+ if (!component.isVisible())
+ continue;
+
+ // When looking up the constraint for the first time, check the
+ // original unmodified constraint. After the first time, always
+ // refer to the internal modified constraint.
+ GridBagConstraints originalConstraints = lookupConstraints (component);
+ GridBagConstraints constraints = (GridBagConstraints) originalConstraints.clone();
+ internalcomptable.put(component, constraints);
+
+ // Cases:
+ //
+ // 1. gridy == RELATIVE, gridx == RELATIVE
+ //
+ // use y as the row number; check for the next
+ // available slot at row y
+ //
+ // 2. only gridx == RELATIVE
+ //
+ // check for the next available slot at row gridy
+ //
+ // 3. only gridy == RELATIVE
+ //
+ // check for the next available slot at column gridx
+ //
+ // 4. neither gridx or gridy == RELATIVE
+ //
+ // nothing to check; just add it
+
+ // cases 1 and 2
+ if(constraints.gridx == GridBagConstraints.RELATIVE)
+ {
+ if (constraints.gridy == GridBagConstraints.RELATIVE)
+ constraints.gridy = current_y;
+
+ int x;
+
+ // Check the component that occupies the right-most spot in this
+ // row. We want to add this component after it.
+ // If this row is empty, add to the 0 position.
+ if (!lastInRow.containsKey(new Integer(constraints.gridy)))
+ x = 0;
+ else
+ {
+ Component lastComponent = lastInRow.get(new Integer(constraints.gridy));
+ GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
+ x = lastConstraints.gridx + Math.max(1, lastConstraints.gridwidth);
+ }
+
+ // Determine if this component will fit in the slot vertically.
+ // If not, bump it over to where it does fit.
+ for (int y = constraints.gridy + 1; y < constraints.gridy + Math.max(1, constraints.gridheight); y++)
+ {
+ if (lastInRow.containsKey(new Integer(y)))
+ {
+ Component lastComponent = lastInRow.get(new Integer(y));
+ GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
+ x = Math.max (x,
+ lastConstraints.gridx + Math.max(1, lastConstraints.gridwidth));
+ }
+ }
+
+ constraints.gridx = x;
+ }
+ // case 3
+ else if(constraints.gridy == GridBagConstraints.RELATIVE)
+ {
+ int y;
+ // Check the component that occupies the bottom-most spot in
+ // this column. We want to add this component below it.
+ // If this column is empty, add to the 0 position.
+ if (!lastInCol.containsKey(new Integer(constraints.gridx)))
+ {
+ y = current_y;
+ }
+ else
+ {
+ Component lastComponent = lastInCol.get(new Integer(constraints.gridx));
+ GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
+ y = lastConstraints.gridy + Math.max(1, lastConstraints.gridheight);
+ }
+
+ // Determine if this component will fit in the slot horizontally.
+ // If not, bump it down to where it does fit.
+ for (int x = constraints.gridx + 1; x < constraints.gridx + Math.max(1, constraints.gridwidth); x++)
+ {
+ if (lastInCol.containsKey(new Integer(x)))
+ {
+ Component lastComponent = lastInCol.get(new Integer(x));
+ GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
+ y = Math.max (y,
+ lastConstraints.gridy + Math.max(1, lastConstraints.gridheight));
+ }
+ }
+
+ constraints.gridy = y;
+ }
+ // case 4: do nothing
+
+ max_x = Math.max(max_x,
+ constraints.gridx + Math.max(1, constraints.gridwidth));
+ max_y = Math.max(max_y,
+ constraints.gridy + Math.max(1, constraints.gridheight));
+
+ sortBySpan(component, constraints.gridwidth, sortedByWidth, true);
+ sortBySpan(component, constraints.gridheight, sortedByHeight, false);
+
+ // Update our reference points for RELATIVE gridx and gridy.
+ if(constraints.gridwidth == GridBagConstraints.REMAINDER)
+ {
+ current_y = constraints.gridy + Math.max(1, constraints.gridheight);
+ }
+ else if (constraints.gridwidth != GridBagConstraints.REMAINDER)
+ {
+ for (int y = constraints.gridy; y < constraints.gridy + Math.max(1, constraints.gridheight); y++)
+ {
+ if(lastInRow.containsKey(new Integer(y)))
+ {
+ Component lastComponent = lastInRow.get(new Integer(y));
+ GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
+ if (constraints.gridx > lastConstraints.gridx)
+ {
+ lastInRow.put(new Integer(y), component);
+ }
+ }
+ else
+ {
+ lastInRow.put(new Integer(y), component);
+ }
+ }
+
+ for (int x = constraints.gridx; x < constraints.gridx + Math.max(1, constraints.gridwidth); x++)
+ {
+ if(lastInCol.containsKey(new Integer(x)))
+ {
+ Component lastComponent = lastInCol.get(new Integer(x));
+ GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
+ if (constraints.gridy > lastConstraints.gridy)
+ {
+ lastInCol.put(new Integer(x), component);
+ }
+ }
+ else
+ {
+ lastInCol.put(new Integer(x), component);
+ }
+ }
+ }
+ } // end of STEP 1
+
+ GridBagLayoutInfo info = new GridBagLayoutInfo(max_x, max_y);
+
+ // Check if column widths and row heights are overridden.
+
+ for (int x = 0; x < max_x; x++)
+ {
+ if(columnWidths != null && columnWidths.length > x)
+ info.colWidths[x] = columnWidths[x];
+ if(columnWeights != null && columnWeights.length > x)
+ info.colWeights[x] = columnWeights[x];
+ }
+
+ for (int y = 0; y < max_y; y++)
+ {
+ if(rowHeights != null && rowHeights.length > y)
+ info.rowHeights[y] = rowHeights[y];
+ if(rowWeights != null && rowWeights.length > y)
+ info.rowWeights[y] = rowWeights[y];
+ }
+
+ // STEP 2: Fix up any cells with width/height as REMAINDER/RELATIVE.
+ for (int i = 0; i < components.length; i++)
+ {
+ Component component = components [i];
+
+ // If component is not visible we dont have to care about it.
+ if (!component.isVisible())
+ continue;
+
+ GridBagConstraints constraints = lookupInternalConstraints (component);
+
+ if(constraints.gridwidth == GridBagConstraints.REMAINDER || constraints.gridwidth == GridBagConstraints.RELATIVE)
+ {
+ if(constraints.gridwidth == GridBagConstraints.REMAINDER)
+ {
+ for (int y = constraints.gridy; y < constraints.gridy + Math.max(1, constraints.gridheight); y++)
+ {
+ if (lastInRow.containsKey(new Integer(y)))
+ {
+ Component lastComponent = lastInRow.get(new Integer(y));
+ GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
+
+ if (lastConstraints.gridwidth == GridBagConstraints.RELATIVE)
+ {
+ constraints.gridx = max_x - 1;
+ break;
+ }
+ else
+ {
+ constraints.gridx = Math.max (constraints.gridx,
+ lastConstraints.gridx + Math.max (1, lastConstraints.gridwidth));
+ }
+ }
+ }
+ constraints.gridwidth = max_x - constraints.gridx;
+ }
+ else if (constraints.gridwidth == GridBagConstraints.RELATIVE)
+ {
+ constraints.gridwidth = max_x - constraints.gridx - 1;
+ }
+
+ // Re-sort
+ sortedByWidth.remove(sortedByWidth.indexOf(component));
+ sortBySpan(component, constraints.gridwidth, sortedByWidth, true);
+ }
+
+ if(constraints.gridheight == GridBagConstraints.REMAINDER || constraints.gridheight == GridBagConstraints.RELATIVE)
+ {
+ if(constraints.gridheight == GridBagConstraints.REMAINDER)
+ {
+ for (int x = constraints.gridx; x < constraints.gridx + Math.max(1, constraints.gridwidth); x++)
+ {
+ if (lastInCol.containsKey(new Integer(x)))
+ {
+ Component lastComponent = lastInRow.get(new Integer(x));
+ if (lastComponent != null)
+ {
+ GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
+
+ if (lastConstraints.gridheight == GridBagConstraints.RELATIVE)
+ {
+ constraints.gridy = max_y - 1;
+ break;
+ }
+ else
+ {
+ constraints.gridy = Math.max (constraints.gridy,
+ lastConstraints.gridy + Math.max (1, lastConstraints.gridheight));
+ }
+ }
+ }
+ }
+ constraints.gridheight = max_y - constraints.gridy;
+ }
+ else if (constraints.gridheight == GridBagConstraints.RELATIVE)
+ {
+ constraints.gridheight = max_y - constraints.gridy - 1;
+ }
+
+ // Re-sort
+ sortedByHeight.remove(sortedByHeight.indexOf(component));
+ sortBySpan(component, constraints.gridheight, sortedByHeight, false);
+ }
+ } // end of STEP 2
+
+ // STEP 3: Determine sizes and weights for columns.
+ for (int i = 0; i < sortedByWidth.size(); i++)
+ {
+ Component component = sortedByWidth.get(i);
+
+ // If component is not visible we dont have to care about it.
+ if (!component.isVisible())
+ continue;
+
+ GridBagConstraints constraints = lookupInternalConstraints (component);
+
+ int width = (sizeflag == PREFERREDSIZE) ?
+ component.getPreferredSize().width :
+ component.getMinimumSize().width;
+
+ if(constraints.insets != null)
+ width += constraints.insets.left + constraints.insets.right;
+
+ width += constraints.ipadx;
+
+ distributeSizeAndWeight(width,
+ constraints.weightx,
+ constraints.gridx,
+ constraints.gridwidth,
+ info.colWidths,
+ info.colWeights);
+ } // end of STEP 3
+
+ // STEP 4: Determine sizes and weights for rows.
+ for (int i = 0; i < sortedByHeight.size(); i++)
+ {
+ Component component = sortedByHeight.get(i);
+
+ // If component is not visible we dont have to care about it.
+ if (!component.isVisible())
+ continue;
+
+ GridBagConstraints constraints = lookupInternalConstraints (component);
+
+ int height = (sizeflag == PREFERREDSIZE) ?
+ component.getPreferredSize().height :
+ component.getMinimumSize().height;
+
+ if(constraints.insets != null)
+ height += constraints.insets.top + constraints.insets.bottom;
+
+ height += constraints.ipady;
+
+ distributeSizeAndWeight(height,
+ constraints.weighty,
+ constraints.gridy,
+ constraints.gridheight,
+ info.rowHeights,
+ info.rowWeights);
+ } // end of STEP 4
+
+ // Adjust cell sizes iff parent size not zero.
+ if (parentDim.width > 0 && parentDim.height > 0)
+ {
+ calcCellSizes (info.colWidths, info.colWeights, parentDim.width);
+ calcCellSizes (info.rowHeights, info.rowWeights, parentDim.height);
+ }
+
+ int totalWidth = sumIntArray(info.colWidths);
+ int totalHeight = sumIntArray(info.rowHeights);
+
+ // Make sure pos_x and pos_y are never negative.
+ if (totalWidth >= parentDim.width)
+ info.pos_x = parentInsets.left;
+ else
+ info.pos_x = parentInsets.left + (parentDim.width - totalWidth) / 2;
+
+ if (totalHeight >= parentDim.height)
+ info.pos_y = parentInsets.top;
+ else
+ info.pos_y = parentInsets.top + (parentDim.height - totalHeight) / 2;
+
+ // DEBUG
+ //dumpLayoutInfo (info);
+
+ return info;
+ }
+
+ /**
+ * Obsolete.
+ */
+ protected Dimension GetMinSize (Container parent, GridBagLayoutInfo info)
+ {
+ if (parent == null || info == null)
+ return new Dimension (0, 0);
+
+ Insets insets = parent.getInsets();
+ int width = sumIntArray (info.colWidths) + insets.left + insets.right;
+ int height = sumIntArray (info.rowHeights) + insets.top + insets.bottom;
+ return new Dimension (width, height);
+ }
+
+ /**
+ * @since 1.4
+ */
+ protected Dimension getMinSize (Container parent, GridBagLayoutInfo info)
+ {
+ return GetMinSize (parent, info);
+ }
+
+ /**
+ * Helper method used by GetLayoutInfo to keep components sorted, either
+ * by gridwidth or gridheight.
+ *
+ * @param component Component to add to the sorted list.
+ * @param span Either the component's gridwidth or gridheight.
+ * @param list <code>ArrayList</code> of components, sorted by
+ * their span.
+ * @param sortByWidth Flag indicating sorting index. If true, sort by
+ * width. Otherwise, sort by height.
+ * FIXME: Use a better sorting algorithm.
+ */
+ private void sortBySpan (Component component, int span,
+ ArrayList<Component> list, boolean sortByWidth)
+ {
+ if (span == GridBagConstraints.REMAINDER
+ || span == GridBagConstraints.RELATIVE)
+ {
+ // Put all RELATIVE and REMAINDER components at the end.
+ list.add(component);
+ }
+ else
+ {
+ int i = 0;
+ if (list.size() > 0)
+ {
+ GridBagConstraints gbc = lookupInternalConstraints(list.get(i));
+ int otherspan = sortByWidth ?
+ gbc.gridwidth :
+ gbc.gridheight;
+ while (otherspan != GridBagConstraints.REMAINDER
+ && otherspan != GridBagConstraints.RELATIVE
+ && span >= otherspan)
+ {
+ i++;
+ if (i < list.size())
+ {
+ gbc = lookupInternalConstraints(list.get(i));
+ otherspan = sortByWidth ?
+ gbc.gridwidth :
+ gbc.gridheight;
+ }
+ else
+ break;
+ }
+ }
+ list.add(i, component);
+ }
+ }
+
+ /**
+ * Helper method used by GetLayoutInfo to distribute a component's size
+ * and weight.
+ *
+ * @param size Preferred size of component, with inset and padding
+ * already added.
+ * @param weight Weight of component.
+ * @param start Starting position of component. Either
+ * constraints.gridx or gridy.
+ * @param span Span of component. either contraints.gridwidth or
+ * gridheight.
+ * @param sizes Sizes of rows or columns.
+ * @param weights Weights of rows or columns.
+ */
+ private void distributeSizeAndWeight (int size, double weight,
+ int start, int span,
+ int[] sizes, double[] weights)
+ {
+ if (span == 1)
+ {
+ sizes[start] = Math.max(sizes[start], size);
+ weights[start] = Math.max(weights[start], weight);
+ }
+ else
+ {
+ int numOccupied = span;
+ int lastOccupied = -1;
+
+ for(int i = start; i < start + span; i++)
+ {
+ if (sizes[i] == 0.0)
+ numOccupied--;
+ else
+ {
+ size -= sizes[i];
+ lastOccupied = i;
+ }
+ }
+
+ // A component needs to occupy at least one row.
+ if(numOccupied == 0)
+ sizes[start + span - 1] = size;
+ else if (size > 0)
+ sizes[lastOccupied] += size;
+
+ calcCellWeights(weight, weights, start, span);
+ }
+ }
+
+ /**
+ * Helper method used by GetLayoutInfo to calculate weight distribution.
+ * @param weight Weight of component.
+ * @param weights Weights of rows/columns.
+ * @param start Starting position of component in grid (gridx/gridy).
+ * @param span Span of component (gridwidth/gridheight).
+ */
+ private void calcCellWeights (double weight, double[] weights, int start, int span)
+ {
+ double totalWeight = 0.0;
+ for(int k = start; k < start + span; k++)
+ totalWeight += weights[k];
+
+ if(weight > totalWeight)
+ {
+ if (totalWeight == 0.0)
+ {
+ weights[start + span - 1] += weight;
+ }
+ else
+ {
+ double diff = weight - totalWeight ;
+ double remaining = diff;
+
+ for(int k = start; k < start + span; k++)
+ {
+ double extraWeight = diff * weights[k] / totalWeight;
+ weights[k] += extraWeight;
+ remaining -= extraWeight;
+ }
+
+ if (remaining > 0.0 && weights[start + span - 1] != 0.0)
+ {
+ weights[start + span - 1] += remaining;
+ }
+ }
+ }
+ }
+
+ /**
+ * Helper method used by GetLayoutInfo to distribute extra space
+ * based on weight distribution.
+ *
+ * @param sizes Sizes of rows/columns.
+ * @param weights Weights of rows/columns.
+ * @param range Dimension of container.
+ */
+ private void calcCellSizes (int[] sizes, double[] weights, int range)
+ {
+ int totalSize = sumIntArray (sizes);
+ double totalWeight = sumDoubleArray (weights);
+
+ int diff = range - totalSize;
+
+ if (diff == 0)
+ return;
+
+ for (int i = 0; i < sizes.length; i++)
+ {
+ int newsize = (int) (sizes[i] + (((double) diff) * weights [i] / totalWeight ));
+
+ if (newsize > 0)
+ sizes[i] = newsize;
+ }
+ }
+
+ private void dumpLayoutInfo (GridBagLayoutInfo info)
+ {
+ System.out.println ("GridBagLayoutInfo:");
+ System.out.println ("cols: " + info.cols + ", rows: " + info.rows);
+ System.out.print ("colWidths: ");
+ dumpArray(info.colWidths);
+ System.out.print ("rowHeights: ");
+ dumpArray(info.rowHeights);
+ System.out.print ("colWeights: ");
+ dumpArray(info.colWeights);
+ System.out.print ("rowWeights: ");
+ dumpArray(info.rowWeights);
+ }
+
+ private void dumpArray(int[] array)
+ {
+ String sep = "";
+ for(int i = 0; i < array.length; i++)
+ {
+ System.out.print(sep);
+ System.out.print(array[i]);
+ sep = ", ";
+ }
+ System.out.println();
+ }
+
+ private void dumpArray(double[] array)
+ {
+ String sep = "";
+ for(int i = 0; i < array.length; i++)
+ {
+ System.out.print(sep);
+ System.out.print(array[i]);
+ sep = ", ";
+ }
+ System.out.println();
+ }
+
+ /**
+ * @since 1.4
+ */
+ protected void arrangeGrid (Container parent)
+ {
+ ArrangeGrid (parent);
+ }
+
+ /**
+ * @since 1.4
+ */
+ protected GridBagLayoutInfo getLayoutInfo (Container parent, int sizeflag)
+ {
+ return GetLayoutInfo (parent, sizeflag);
+ }
+
+ /**
+ * Move and resize a rectangle according to a set of grid bag
+ * constraints. The x, y, width and height fields of the
+ * rectangle argument are adjusted to the new values.
+ *
+ * @param constraints position and size constraints
+ * @param r rectangle to be moved and resized
+ *
+ * @since 1.4
+ */
+ protected void adjustForGravity (GridBagConstraints constraints,
+ Rectangle r)
+ {
+ AdjustForGravity (constraints, r);
+ }
+}
diff --git a/libjava/classpath/java/awt/GridBagLayoutInfo.java b/libjava/classpath/java/awt/GridBagLayoutInfo.java
new file mode 100644
index 000000000..43ba09d72
--- /dev/null
+++ b/libjava/classpath/java/awt/GridBagLayoutInfo.java
@@ -0,0 +1,70 @@
+/* GridBagLayoutInfo -
+ Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.io.Serializable;
+
+/**
+ * @author Michael Koch (konqueror@gmx.de)
+ */
+class GridBagLayoutInfo implements Serializable
+{
+ private static final long serialVersionUID = -4899416460737170217L;
+
+ int pos_x;
+ int pos_y;
+ int cols;
+ int rows;
+ int colWidths[];
+ int rowHeights[];
+ double colWeights[];
+ double rowWeights[];
+
+ GridBagLayoutInfo (int cols, int rows)
+ {
+ this.pos_x = 0;
+ this.pos_y = 0;
+ this.cols = cols;
+ this.rows = rows;
+ this.colWidths = new int [cols];
+ this.rowHeights = new int [rows];
+ this.colWeights = new double [cols];
+ this.rowWeights = new double [rows];
+ }
+}
diff --git a/libjava/classpath/java/awt/GridLayout.java b/libjava/classpath/java/awt/GridLayout.java
new file mode 100644
index 000000000..a8b0189de
--- /dev/null
+++ b/libjava/classpath/java/awt/GridLayout.java
@@ -0,0 +1,354 @@
+/* GridLayout.java -- Grid-based layout engine
+ Copyright (C) 1999, 2000, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.io.Serializable;
+
+/** This class implements a grid-based layout scheme. Components are
+ * all given the same size and are laid out from left to right and top
+ * to bottom. A GridLayout is configured with a number of rows and a
+ * number of columns. If both are specified, then the number of
+ * columns is ignored and is derived from the number of rows and the
+ * total number of components. If either is zero then that dimension
+ * is computed based on the actual size of the container. An
+ * exception is thrown if an attempt is made to set both the number of
+ * rows and the number of columns to 0. This class also supports
+ * horizontal and vertical gaps; these are used as spacing between
+ * cells.
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class GridLayout implements LayoutManager, Serializable
+{
+ static final long serialVersionUID = -7411804673224730901L;
+
+ /** Add a new component to the layout. This particular implementation
+ * does nothing.
+ * @param name The name of the component to add.
+ * @param comp The component to add.
+ */
+ public void addLayoutComponent (String name, Component comp)
+ {
+ // Nothing.
+ }
+
+ /** Return the number of columns in this layout. */
+ public int getColumns ()
+ {
+ return cols;
+ }
+
+ /** Return the horizontal gap. */
+ public int getHgap ()
+ {
+ return hgap;
+ }
+
+ /** Return the number of rows in this layout. */
+ public int getRows ()
+ {
+ return rows;
+ }
+
+ /** Return the vertical gap. */
+ public int getVgap ()
+ {
+ return vgap;
+ }
+
+ /** Create a new <code>GridLayout</code> with one row and any number
+ * of columns. Both gaps are set to 0.
+ */
+ public GridLayout ()
+ {
+ this (1, 0, 0, 0);
+ }
+
+ /** Create a new <code>GridLayout</code> with the specified number
+ * of rows and columns. Both gaps are set to 0. Note that the row
+ * and column settings cannot both be zero. If both the row and
+ * column values are non-zero, the rows value takes precedence.
+ * @param rows Number of rows
+ * @param cols Number of columns
+ * @exception IllegalArgumentException If rows and columns are both
+ * 0, or if either are negative
+ */
+ public GridLayout (int rows, int cols)
+ {
+ this (rows, cols, 0, 0);
+ }
+
+ /** Create a new GridLayout with the specified number of rows and
+ * columns and the specified gaps.
+ * Note that the row and column settings cannot both be
+ * zero. If both the row and column values are non-zero, the rows value
+ * takes precedence.
+ * @param rows Number of rows
+ * @param cols Number of columns
+ * @param hgap The horizontal gap
+ * @param vgap The vertical gap
+ * @exception IllegalArgumentException If rows and columns are both
+ * 0, if either are negative, or if either gap is negative
+ */
+ public GridLayout (int rows, int cols, int hgap, int vgap)
+ {
+ if (rows < 0)
+ throw new IllegalArgumentException ("number of rows cannot be negative");
+ if (cols < 0)
+ throw new IllegalArgumentException ("number of columns cannot be negative");
+ if (rows == 0 && cols == 0)
+ throw new IllegalArgumentException ("both rows and columns cannot be 0");
+ if (hgap < 0)
+ throw new IllegalArgumentException ("horizontal gap must be nonnegative");
+ if (vgap < 0)
+ throw new IllegalArgumentException ("vertical gap must be nonnegative");
+ this.rows = rows;
+ this.cols = cols;
+ this.hgap = hgap;
+ this.vgap = vgap;
+ }
+
+ /** Lay out the container's components based on current settings.
+ * The free space in the container is divided evenly into the specified
+ * number of rows and columns in this object.
+ * @param parent The container to lay out
+ */
+ public void layoutContainer (Container parent)
+ {
+ synchronized (parent.getTreeLock ())
+ {
+ int num = parent.ncomponents;
+
+ // There's no point, and handling this would mean adding special
+ // cases.
+ if (num == 0)
+ return;
+
+ // This is more efficient than calling getComponents().
+ Component[] comps = parent.component;
+
+ int real_rows = rows;
+ int real_cols = cols;
+ if (real_rows == 0)
+ real_rows = (num + real_cols - 1) / real_cols;
+ else
+ real_cols = (num + real_rows - 1) / real_rows;
+
+ // We might have less than a single row. In this case we expand
+ // to fill.
+ if (num < real_cols)
+ real_cols = num;
+
+ Dimension d = parent.getSize ();
+ Insets ins = parent.getInsets ();
+
+ // Compute width and height of each cell in the grid.
+ int tw = d.width - ins.left - ins.right;
+ tw = (tw - (real_cols - 1) * hgap) / real_cols;
+ int th = d.height - ins.top - ins.bottom;
+ th = (th - (real_rows - 1) * vgap) / real_rows;
+
+ // If the cells are too small, still try to do something.
+ if (tw < 0)
+ tw = 1;
+ if (th < 0)
+ th = 1;
+
+ int x = ins.left;
+ int y = ins.top;
+ int i = 0;
+ int recount = 0;
+
+ while (i < num)
+ {
+ comps[i].setBounds (x, y, tw, th);
+
+ ++i;
+ ++recount;
+ if (recount == real_cols)
+ {
+ recount = 0;
+ y += vgap + th;
+ x = ins.left;
+ }
+ else
+ x += hgap + tw;
+ }
+ }
+ }
+
+ /** Get the minimum layout size of the container.
+ * @param cont The parent container
+ */
+ public Dimension minimumLayoutSize (Container cont)
+ {
+ return getSize (cont, true);
+ }
+
+ /** Get the preferred layout size of the container.
+ * @param cont The parent container
+ */
+ public Dimension preferredLayoutSize (Container cont)
+ {
+ return getSize (cont, false);
+ }
+
+ /** Remove the indicated component from this layout manager.
+ * This particular implementation does nothing.
+ * @param comp The component to remove
+ */
+ public void removeLayoutComponent (Component comp)
+ {
+ // Nothing.
+ }
+
+ /** Set the number of columns.
+ * @param newCols
+ * @exception IllegalArgumentException If the number of columns is
+ * negative, or if the number of columns is zero and the number
+ * of rows is already 0.
+ */
+ public void setColumns (int newCols)
+ {
+ if (newCols < 0)
+ throw new IllegalArgumentException ("number of columns cannot be negative");
+ if (newCols == 0 && rows == 0)
+ throw new IllegalArgumentException ("number of rows is already 0");
+ this.cols = newCols;
+ }
+
+ /** Set the horizontal gap. An Exception is not thrown if hgap < 0.
+ * @param hgap The horizontal gap
+ */
+ public void setHgap (int hgap)
+ {
+ this.hgap = hgap;
+ }
+
+ /** Set the number of rows
+ * @param newRows
+ * @exception IllegalArgumentException If the number of rows is
+ * negative, or if the number of rows is zero and the number
+ * of columns is already 0.
+ */
+ public void setRows (int newRows)
+ {
+ if (newRows < 0)
+ throw new IllegalArgumentException ("number of rows cannot be negative");
+ if (newRows == 0 && cols == 0)
+ throw new IllegalArgumentException ("number of columns is already 0");
+ this.rows = newRows;
+ }
+
+ /** Set the vertical gap. An Exception is not thrown if vgap < 0.
+ * @param vgap The vertical gap
+ */
+ public void setVgap (int vgap)
+ {
+ this.vgap = vgap;
+ }
+
+ /** Return String description of this object. */
+ public String toString ()
+ {
+ return (getClass ().getName () + "["
+ + "hgap=" + hgap + ",vgap=" + vgap
+ + ",rows=" + rows + ",cols=" + cols
+ + "]");
+ }
+
+ // This method is used to compute the various sizes.
+ private Dimension getSize (Container parent, boolean is_min)
+ {
+ synchronized (parent.getTreeLock ())
+ {
+ int w = 0, h = 0, num = parent.ncomponents;
+ // This is more efficient than calling getComponents().
+ Component[] comps = parent.component;
+
+ for (int i = 0; i < num; ++i)
+ {
+ Dimension d;
+
+ if (is_min)
+ d = comps[i].getMinimumSize ();
+ else
+ d = comps[i].getPreferredSize ();
+
+ w = Math.max (d.width, w);
+ h = Math.max (d.height, h);
+ }
+
+ int real_rows = rows;
+ int real_cols = cols;
+ if (real_rows == 0)
+ real_rows = (num + real_cols - 1) / real_cols;
+ else
+ real_cols = (num + real_rows - 1) / real_rows;
+
+ Insets ins = parent.getInsets ();
+ // We subtract out an extra gap here because the gaps are only
+ // between cells.
+ w = ins.left + ins.right + real_cols * (w + hgap) - hgap;
+ h = ins.top + ins.bottom + real_rows * (h + vgap) - vgap;
+ return new Dimension (w, h);
+ }
+ }
+
+ /**
+ * @serial The number of columns in the grid.
+ */
+ private int cols;
+
+ /**
+ * @serial The number of rows in the grid.
+ */
+ private int rows;
+
+ /**
+ * @serial The horizontal gap between columns
+ */
+ private int hgap;
+
+ /**
+ * @serial The vertical gap between rows
+ */
+ private int vgap;
+}
diff --git a/libjava/classpath/java/awt/HeadlessException.java b/libjava/classpath/java/awt/HeadlessException.java
new file mode 100644
index 000000000..b180b1d86
--- /dev/null
+++ b/libjava/classpath/java/awt/HeadlessException.java
@@ -0,0 +1,72 @@
+/* HeadlessException.java -- operation not possible in headless environment
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This exception is thrown when code dependent on a keyboard, mouse, or
+ * display is executed in a headless environment.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public class HeadlessException extends UnsupportedOperationException
+{
+ /**
+ * Compatible with JDK 1.4+.
+ */
+ private static final long serialVersionUID = 167183644944358563L;
+
+ /**
+ * Create a new instance with no detailed error message.
+ */
+ public HeadlessException()
+ {
+ }
+
+ /**
+ * Create a new instance with the specified detailed error message.
+ *
+ * @param message the detailed error message
+ */
+ public HeadlessException(String message)
+ {
+ super(message);
+ }
+} // class HeadlessException
diff --git a/libjava/classpath/java/awt/IllegalComponentStateException.java b/libjava/classpath/java/awt/IllegalComponentStateException.java
new file mode 100644
index 000000000..4a47f1da9
--- /dev/null
+++ b/libjava/classpath/java/awt/IllegalComponentStateException.java
@@ -0,0 +1,71 @@
+/* IllegalComponentStateException.java -- bad component state
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This exception is thrown when the requested operation failed because
+ * a component was not in the proper state.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @status updated to 1.4
+ */
+public class IllegalComponentStateException extends IllegalStateException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -1889339587208144238L;
+
+ /**
+ * Create a new instance with no detailed error message.
+ */
+ public IllegalComponentStateException()
+ {
+ }
+
+ /**
+ * Create a new instance with the specified detailed error message.
+ *
+ * @param message the detailed error message
+ */
+ public IllegalComponentStateException(String message)
+ {
+ super(message);
+ }
+} // class IllegalComponentStateException
diff --git a/libjava/classpath/java/awt/Image.java b/libjava/classpath/java/awt/Image.java
new file mode 100644
index 000000000..7b2cee7ae
--- /dev/null
+++ b/libjava/classpath/java/awt/Image.java
@@ -0,0 +1,242 @@
+/* Image.java -- superclass for images
+ Copyright (C) 1999, 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.image.AreaAveragingScaleFilter;
+import java.awt.image.FilteredImageSource;
+import java.awt.image.ImageFilter;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.image.ReplicateScaleFilter;
+
+/**
+ * This is the abstract superclass of all image objects in Java.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.0
+ * @status updated to 1.5
+ */
+public abstract class Image
+{
+ /**
+ * This variable is returned whenever a property that is not defined
+ * is requested.
+ */
+ // For debug purposes, this might as well be a unique string.
+ public static final Object UndefinedProperty
+ = new String("undefined property");
+
+ /**
+ * Constant indicating that the default scaling algorithm should be used.
+ *
+ * @since 1.1
+ */
+ public static final int SCALE_DEFAULT = 1;
+
+ /**
+ * Constant indicating that a fast scaling algorithm should be used.
+ *
+ * @since 1.1
+ */
+ public static final int SCALE_FAST = 2;
+
+ /**
+ * Constant indicating that a smooth scaling algorithm should be used.
+ *
+ * @since 1.1
+ */
+ public static final int SCALE_SMOOTH = 4;
+
+ /**
+ * Constant indicating that the <code>ReplicateScaleFilter</code> class
+ * algorithm should be used for scaling.
+ *
+ * @see ReplicateScaleFilter
+ * @since 1.1
+ */
+ public static final int SCALE_REPLICATE = 8;
+
+ /**
+ * Constant indicating that the area averaging scaling algorithm should be
+ * used.
+ *
+ * @see java.awt.image.AreaAveragingScaleFilter
+ * @since 1.1
+ */
+ public static final int SCALE_AREA_AVERAGING = 16;
+
+ /**
+ * The acceleration priority of the image
+ * @since 1.5
+ */
+ protected float accelerationPriority;
+
+ /**
+ * A default constructor for subclasses.
+ */
+ public Image()
+ {
+ }
+
+ /**
+ * Returns the width of the image, or -1 if it is unknown. If the
+ * image width is unknown, the observer object will be notified when
+ * the value is known.
+ *
+ * @param observer the image observer for this object
+ * @return the width in pixels
+ * @see #getHeight(ImageObserver)
+ */
+ public abstract int getWidth(ImageObserver observer);
+
+ /**
+ * Returns the height of the image, or -1 if it is unknown. If the
+ * image height is unknown, the observer object will be notified when
+ * the value is known.
+ *
+ * @param observer the image observer for this object
+ * @return the height in pixels
+ * @see #getWidth(ImageObserver)
+ */
+ public abstract int getHeight(ImageObserver observer);
+
+ /**
+ * Returns the image producer object for this object. The producer is the
+ * object which generates pixels for this image.
+ *
+ * @return the image producer for this object
+ */
+ public abstract ImageProducer getSource();
+
+ /**
+ * Returns a graphics context object for drawing an off-screen object.
+ * This method is only valid for off-screen objects.
+ *
+ * @return a graphics context object for an off-screen object
+ */
+ public abstract Graphics getGraphics();
+
+ /**
+ * This method requests a named property for an object. The value of the
+ * property is returned. The value <code>UndefinedProperty</code> is
+ * returned if there is no property with the specified name. The value
+ * <code>null</code> is returned if the properties for the object are
+ * not yet known. In this case, the specified image observer is notified
+ * when the properties are known.
+ *
+ * @param name the requested property name
+ * @param observer the image observer for this object
+ * @return the named property, if available
+ * @see #UndefinedProperty
+ */
+ public abstract Object getProperty(String name, ImageObserver observer);
+
+ /**
+ * Scales the image to the requested dimension. A new Image with asynchronous
+ * loading will be produced according to the hints of the algorithm
+ * requested. If either the width or height is non-positive, it is adjusted
+ * to preserve the original aspect ratio.
+ * If an illegal value of <code>flags</code> is passed,
+ * the default algorithm is used.
+ *
+ * @param width the width of the scaled image
+ * @param height the height of the scaled image
+ * @param flags a value indicating the algorithm to use
+ * @return the scaled <code>Image</code> object
+ * @see #SCALE_DEFAULT
+ * @see #SCALE_FAST
+ * @see #SCALE_SMOOTH
+ * @see #SCALE_REPLICATE
+ * @see #SCALE_AREA_AVERAGING
+ * @since 1.1
+ */
+ public Image getScaledInstance(int width, int height, int flags)
+ {
+ ImageFilter filter;
+ switch (flags)
+ {
+ case SCALE_AREA_AVERAGING:
+ case SCALE_SMOOTH:
+ filter = new AreaAveragingScaleFilter(width, height);
+ break;
+ case SCALE_DEFAULT:
+ case SCALE_FAST:
+ case SCALE_REPLICATE:
+ default:
+ filter = new ReplicateScaleFilter(width, height);
+ }
+
+ ImageProducer producer = new FilteredImageSource(getSource(), filter);
+ return Toolkit.getDefaultToolkit().createImage(producer);
+ }
+
+ /**
+ * Flushes (that is, destroys) any resources used for this image. This
+ * includes the actual image data.
+ */
+ public abstract void flush();
+
+ /**
+ * Sets the acceleration priority of the image.
+ * This is a value from 0 (lowest) to 1 (highest), which may
+ * be used as a hint for image acceleration.
+ * E.g. higher priority images may be stored in video memory.
+ * @param priority - the priority
+ * @throws IllegalArgumentException if priority is not >= 0 and <= 1.
+ *
+ * @since 1.5
+ */
+ public void setAccelerationPriority(float priority)
+ {
+ if( priority < 0f || priority > 1f)
+ throw new IllegalArgumentException("Invalid priority value.");
+ accelerationPriority = priority;
+ }
+
+ /**
+ * Returns the acceleration priority of the image.
+ *
+ * @see #setAccelerationPriority(float)
+ * @since 1.5
+ */
+ public float getAccelerationPriority()
+ {
+ return accelerationPriority;
+ }
+} // class Image
diff --git a/libjava/classpath/java/awt/ImageCapabilities.java b/libjava/classpath/java/awt/ImageCapabilities.java
new file mode 100644
index 000000000..2fe71d1e2
--- /dev/null
+++ b/libjava/classpath/java/awt/ImageCapabilities.java
@@ -0,0 +1,107 @@
+/* ImageCapabilities.java -- the capabilities of an image buffer
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This class represents the capabilities of an image buffer. An
+ * image buffer may be backed by accelerated graphics resources.
+ * Those resources may or may not be volatile. This class is used to
+ * describe these image buffer characteristics.
+ */
+public class ImageCapabilities implements Cloneable
+{
+ /**
+ * Whether or not this the image buffer uses accelerated graphics
+ * resources.
+ */
+ private final boolean accelerated;
+
+ /**
+ * Create a new image capability descriptor.
+ *
+ * @param accelerated true if the image buffer uses accelerated
+ * graphics resources
+ */
+ public ImageCapabilities(boolean accelerated)
+ {
+ this.accelerated = accelerated;
+ }
+
+ /**
+ * Returns whether or not the image buffer uses accelerated graphics
+ * resources.
+ *
+ * @return true if the image buffer uses accelerated graphics
+ * resources; false otherwise
+ */
+ public boolean isAccelerated()
+ {
+ return accelerated;
+ }
+
+ /**
+ * Returns whether or not the image buffer's resources are volatile,
+ * meaning that they can be reclaimed by the graphics system at any
+ * time.
+ *
+ * @return true if the image buffer's resources are volatile; false
+ * otherwise
+ */
+ public boolean isTrueVolatile()
+ {
+ return true;
+ }
+
+ /**
+ * Clone this image capability descriptor.
+ *
+ * @return a clone of this image capability descriptor
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e);
+ }
+ }
+}
diff --git a/libjava/classpath/java/awt/Insets.java b/libjava/classpath/java/awt/Insets.java
new file mode 100644
index 000000000..1747cae6a
--- /dev/null
+++ b/libjava/classpath/java/awt/Insets.java
@@ -0,0 +1,177 @@
+/* Insets.java -- information about a container border
+ Copyright (C) 1999, 2000, 2002, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.io.Serializable;
+
+/**
+ * This class represents the "margin" or space around a container.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @status
+ */
+public class Insets implements Cloneable, Serializable
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -2272572637695466749L;
+
+ /**
+ * The gap from the top.
+ *
+ * @serial the top inset
+ */
+ public int top;
+
+ /**
+ * The gap from the left.
+ *
+ * @serial the left inset
+ */
+ public int left;
+
+ /**
+ * The gap from the bottom.
+ *
+ * @serial the bottom inset
+ */
+ public int bottom;
+
+ /**
+ * The gap from the right.
+ *
+ * @serial the right inset
+ */
+ public int right;
+
+ /**
+ * Initializes a new instance of <code>Inset</code> with the specified
+ * inset values.
+ *
+ * @param top the top inset
+ * @param left the left inset
+ * @param bottom the bottom inset
+ * @param right the right inset
+ */
+ public Insets(int top, int left, int bottom, int right)
+ {
+ this.top = top;
+ this.left = left;
+ this.bottom = bottom;
+ this.right = right;
+ }
+
+ /**
+ * Set the contents of this Insets object to the specified values.
+ *
+ * @param top the top inset
+ * @param left the left inset
+ * @param bottom the bottom inset
+ * @param right the right inset
+ *
+ * @since 1.5
+ */
+ public void set(int top, int left, int bottom, int right)
+ {
+ this.top = top;
+ this.left = left;
+ this.bottom = bottom;
+ this.right = right;
+ }
+
+ /**
+ * Tests whether this object is equal to the specified object. The other
+ * object must be an instance of Insets with identical field values.
+ *
+ * @param obj the object to test against
+ * @return true if the specified object is equal to this one
+ *
+ * @since 1.1
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof Insets))
+ return false;
+ Insets i = (Insets) obj;
+ return top == i.top && bottom == i.bottom
+ && left == i.left && right == i.right;
+ }
+
+ /**
+ * Returns a hashcode for this instance. The formula is unspecified, but
+ * appears to be <code>XXX what is it? </code>.
+ *
+ * @return the hashcode
+ */
+ public int hashCode()
+ {
+ // This can't be right...
+ return top + bottom + left + right;
+ }
+
+ /**
+ * Returns a string representation of this object, which will be non-null.
+ *
+ * @return a string representation of this object
+ */
+ public String toString()
+ {
+ return getClass().getName() + "[top=" + top + ",left=" + left
+ + ",bottom=" + bottom + ",right=" + right + ']';
+ }
+
+ /**
+ * Returns a copy of this object.
+ *
+ * @return a copy of this object
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // Impossible
+ }
+ }
+} // class Insets
diff --git a/libjava/classpath/java/awt/ItemSelectable.java b/libjava/classpath/java/awt/ItemSelectable.java
new file mode 100644
index 000000000..f155f723e
--- /dev/null
+++ b/libjava/classpath/java/awt/ItemSelectable.java
@@ -0,0 +1,75 @@
+/* ItemSelectable.java -- items that can be selected
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.ItemListener;
+
+/**
+ * This interface is for objects that can have one or more items selected.
+ * For example, radio buttons.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public interface ItemSelectable
+{
+ /**
+ * Returns the list of objects that are selected in this component.
+ *
+ * @return the list of selected objects, or null
+ */
+ Object[] getSelectedObjects();
+
+ /**
+ * Adds an item listener to this object. It will receive selection events
+ * for this object by the user (but not programatically). If listener is
+ * null, it is ignored.
+ *
+ * @param listener the item listener to add
+ */
+ void addItemListener(ItemListener listener);
+
+ /**
+ * Removes an item listener from this object.
+ *
+ * @param listener the item listener to remove
+ */
+ void removeItemListener(ItemListener listener);
+} // interface ItemSelectable
diff --git a/libjava/classpath/java/awt/JobAttributes.java b/libjava/classpath/java/awt/JobAttributes.java
new file mode 100644
index 000000000..e84901d33
--- /dev/null
+++ b/libjava/classpath/java/awt/JobAttributes.java
@@ -0,0 +1,502 @@
+/* JobAttributes.java --
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import gnu.java.lang.CPStringBuilder;
+
+/**
+ * Needs documentation...
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.3
+ * @status updated to 1.4, lacks documentation
+ */
+public final class JobAttributes implements Cloneable
+{
+ public static final class DefaultSelectionType extends AttributeValue
+ {
+ private static final String[] NAMES = { "all", "range", "selection" };
+ public static final DefaultSelectionType ALL
+ = new DefaultSelectionType(0);
+ public static final DefaultSelectionType RANGE
+ = new DefaultSelectionType(1);
+ public static final DefaultSelectionType SELECTION
+ = new DefaultSelectionType(2);
+ private DefaultSelectionType(int value)
+ {
+ super(value, NAMES);
+ }
+ } // class DefaultSelectionType
+
+ public static final class DestinationType extends AttributeValue
+ {
+ private static final String[] NAMES = { "file", "printer" };
+ public static final DestinationType FILE = new DestinationType(0);
+ public static final DestinationType PRINTER = new DestinationType(1);
+ private DestinationType(int value)
+ {
+ super(value, NAMES);
+ }
+ } // class DestinationType
+
+ public static final class DialogType extends AttributeValue
+ {
+ private static final String[] NAMES = { "common", "native", "none" };
+ public static final DialogType COMMON = new DialogType(0);
+ public static final DialogType NATIVE = new DialogType(1);
+ public static final DialogType NONE = new DialogType(2);
+ private DialogType(int value)
+ {
+ super(value, NAMES);
+ }
+ } // class DialogType
+
+ public static final class MultipleDocumentHandlingType
+ extends AttributeValue
+ {
+ private static final String[] NAMES = {
+ "separate-documents-collated-copies",
+ "separate-documents-uncollated-copies"
+ };
+ public static final MultipleDocumentHandlingType
+ SEPARATE_DOCUMENTS_COLLATED_COPIES
+ = new MultipleDocumentHandlingType(0);
+ public static final MultipleDocumentHandlingType
+ SEPARATE_DOCUMENTS_UNCOLLATED_COPIES
+ = new MultipleDocumentHandlingType(1);
+ private MultipleDocumentHandlingType(int value)
+ {
+ super(value, NAMES);
+ }
+ } // class MultipleDocumentHandlingType
+
+ public static final class SidesType extends AttributeValue
+ {
+ private static final String[] NAMES
+ = { "one-sided", "two-sided-long-edge", "two-sided-short-edge" };
+ public static final SidesType ONE_SIDED = new SidesType(0);
+ public static final SidesType TWO_SIDED_LONG_EDGE = new SidesType(1);
+ public static final SidesType TWO_SIDED_SHORT_EDGE = new SidesType(2);
+ private SidesType(int value)
+ {
+ super(value, NAMES);
+ }
+ } // class SidesType
+
+ private int copies;
+ private DefaultSelectionType selection;
+ private DestinationType destination;
+ private DialogType dialog;
+ private String filename;
+ private int maxPage;
+ private int minPage;
+ private MultipleDocumentHandlingType multiple;
+ private int[][] pageRanges; // null for default value
+ private int fromPage; // 0 for default value
+ private int toPage; // 0 for default value
+ private String printer;
+ private SidesType sides;
+
+ public JobAttributes()
+ {
+ copies = 1;
+ selection = DefaultSelectionType.ALL;
+ destination = DestinationType.PRINTER;
+ dialog = DialogType.NATIVE;
+ maxPage = Integer.MAX_VALUE;
+ minPage = 1;
+ multiple
+ = MultipleDocumentHandlingType.SEPARATE_DOCUMENTS_UNCOLLATED_COPIES;
+ sides = SidesType.ONE_SIDED;
+ }
+
+ public JobAttributes(JobAttributes attr)
+ {
+ set(attr);
+ }
+
+ public JobAttributes(int copies, DefaultSelectionType selection,
+ DestinationType destination, DialogType dialog,
+ String filename, int max, int min,
+ MultipleDocumentHandlingType multiple,
+ int[][] pageRanges, String printer, SidesType sides)
+ {
+ if (copies <= 0 || selection == null || destination == null
+ || dialog == null || max < min || min <= 0 || multiple == null
+ || sides == null)
+ throw new IllegalArgumentException();
+ this.copies = copies;
+ this.selection = selection;
+ this.destination = destination;
+ this.dialog = dialog;
+ this.filename = filename;
+ maxPage = max;
+ minPage = min;
+ this.multiple = multiple;
+ setPageRanges(pageRanges);
+ this.printer = printer;
+ this.sides = sides;
+ }
+
+ public Object clone()
+ {
+ return new JobAttributes(this);
+ }
+
+ public void set(JobAttributes attr)
+ {
+ copies = attr.copies;
+ selection = attr.selection;
+ destination = attr.destination;
+ dialog = attr.dialog;
+ filename = attr.filename;
+ maxPage = attr.maxPage;
+ minPage = attr.minPage;
+ multiple = attr.multiple;
+ pageRanges = (int[][]) attr.pageRanges.clone();
+ printer = attr.printer;
+ sides = attr.sides;
+ fromPage = attr.fromPage;
+ toPage = attr.toPage;
+ }
+
+ public int getCopies()
+ {
+ return copies;
+ }
+
+ public void setCopies(int copies)
+ {
+ if (copies <= 0)
+ throw new IllegalArgumentException();
+ this.copies = copies;
+ }
+
+ public void setCopiesToDefault()
+ {
+ copies = 1;
+ }
+
+ public DefaultSelectionType getDefaultSelection()
+ {
+ return selection;
+ }
+
+ public void setDefaultSelection(DefaultSelectionType selection)
+ {
+ if (selection == null)
+ throw new IllegalArgumentException();
+ this.selection = selection;
+ }
+
+ public DestinationType getDestination()
+ {
+ return destination;
+ }
+
+ public void setDestination(DestinationType destination)
+ {
+ if (destination == null)
+ throw new IllegalArgumentException();
+ this.destination = destination;
+ }
+
+ public DialogType getDialog()
+ {
+ return dialog;
+ }
+
+ public void setDialog(DialogType dialog)
+ {
+ if (dialog == null)
+ throw new IllegalArgumentException();
+ this.dialog = dialog;
+ }
+
+ public String getFileName()
+ {
+ return filename;
+ }
+
+ public void setFileName(String filename)
+ {
+ this.filename = filename;
+ }
+
+ public int getFromPage()
+ {
+ return fromPage != 0 ? fromPage
+ : pageRanges != null ? pageRanges[0][0]
+ : toPage != 0 ? toPage : minPage;
+ }
+
+ public void setFromPage(int fromPage)
+ {
+ if (fromPage < minPage || (fromPage > toPage && toPage != 0)
+ || fromPage > maxPage)
+ throw new IllegalArgumentException();
+ if (pageRanges == null)
+ this.fromPage = fromPage;
+ }
+
+ public int getMaxPage()
+ {
+ return maxPage;
+ }
+
+ public void setMaxPage(int maxPage)
+ {
+ if (maxPage < minPage)
+ throw new IllegalArgumentException();
+ this.maxPage = maxPage;
+ if (maxPage < fromPage)
+ fromPage = maxPage;
+ if (maxPage < toPage)
+ toPage = maxPage;
+ if (pageRanges != null)
+ {
+ int i = pageRanges.length - 1;
+ while (i >= 0 && maxPage < pageRanges[i][1])
+ i--;
+ if (maxPage >= pageRanges[++i][0])
+ pageRanges[i++][1] = maxPage;
+ if (i == 0)
+ pageRanges = null;
+ else if (i < pageRanges.length)
+ {
+ int[][] tmp = new int[i][];
+ System.arraycopy(pageRanges, 0, tmp, 0, i);
+ pageRanges = tmp;
+ }
+ }
+ }
+
+ public int getMinPage()
+ {
+ return minPage;
+ }
+
+ public void setMinPage(int minPage)
+ {
+ if (minPage <= 0 || minPage > maxPage)
+ throw new IllegalArgumentException();
+ this.minPage = minPage;
+ if (minPage > toPage)
+ toPage = minPage;
+ if (minPage > fromPage)
+ fromPage = minPage;
+ if (pageRanges != null)
+ {
+ int size = pageRanges.length;
+ int i = 0;
+ while (i < size && minPage > pageRanges[i][0])
+ i++;
+ if (minPage <= pageRanges[i - 1][1])
+ pageRanges[--i][0] = minPage;
+ if (i == size)
+ pageRanges = null;
+ else if (i > 0)
+ {
+ int[][] tmp = new int[size - i][];
+ System.arraycopy(pageRanges, i, tmp, 0, size - i);
+ pageRanges = tmp;
+ }
+ }
+ }
+
+ public MultipleDocumentHandlingType getMultipleDocumentHandling()
+ {
+ return multiple;
+ }
+
+ public void setMultipleDocumentHandling
+ (MultipleDocumentHandlingType multiple)
+ {
+ if (multiple == null)
+ throw new IllegalArgumentException();
+ this.multiple = multiple;
+ }
+
+ public void setMultipleDocumentHandlingToDefault()
+ {
+ multiple
+ = MultipleDocumentHandlingType.SEPARATE_DOCUMENTS_UNCOLLATED_COPIES;
+ }
+
+ public int[][] getPageRanges()
+ {
+ if (pageRanges == null)
+ return new int[][] { { getFromPage(), getToPage() } };
+ // Perform a deep clone, so user code cannot affect original arrays.
+ int i = pageRanges.length;
+ int[][] result = new int[i][];
+ while (--i >= 0)
+ result[i] = (int[]) pageRanges[i].clone();
+ return result;
+ }
+
+ public void setPageRanges(int[][] pageRanges)
+ {
+ int size = pageRanges == null ? 0 : pageRanges.length;
+ if (size == 0)
+ throw new IllegalArgumentException();
+ while (--size >= 0)
+ {
+ int[] range = pageRanges[size];
+ if (range == null || range.length != 2
+ || range[0] < minPage || range[1] < range[0] || range[1] > maxPage
+ || (size != 0 && range[0] <= pageRanges[size - 1][1]))
+ throw new IllegalArgumentException();
+ }
+ size = pageRanges.length;
+ if (fromPage > 0 && pageRanges[0][0] > fromPage)
+ fromPage = pageRanges[0][0];
+ if (toPage > 0 && pageRanges[size - 1][1] < toPage)
+ toPage = pageRanges[size - 1][1];
+ this.pageRanges = new int[size][];
+ while (--size >= 0)
+ this.pageRanges[size] = (int[]) pageRanges[size].clone();
+ }
+
+ public String getPrinter()
+ {
+ return printer;
+ }
+
+ public void setPrinter(String printer)
+ {
+ this.printer = printer;
+ }
+
+ public SidesType getSides()
+ {
+ return sides;
+ }
+
+ public void setSides(SidesType sides)
+ {
+ if (sides == null)
+ throw new IllegalArgumentException();
+ this.sides = sides;
+ }
+
+ public void setSidesToDefault()
+ {
+ sides = SidesType.ONE_SIDED;
+ }
+
+ public int getToPage()
+ {
+ return toPage != 0 ? toPage
+ : pageRanges != null ? pageRanges[pageRanges.length - 1][1]
+ : fromPage != 0 ? fromPage : maxPage;
+ }
+
+ public void setToPage(int toPage)
+ {
+ if (toPage < minPage || (fromPage > toPage && fromPage != 0)
+ || toPage > maxPage)
+ throw new IllegalArgumentException();
+ if (pageRanges == null)
+ this.toPage = toPage;
+ }
+
+ public boolean equals(Object o)
+ {
+ if (this == o)
+ return true;
+ if (! (o instanceof JobAttributes))
+ return false;
+ JobAttributes ja = (JobAttributes) o;
+ if (copies != ja.copies || selection != ja.selection
+ || destination != ja.destination || dialog != ja.dialog
+ || ! filename.equals(ja.filename) || maxPage != ja.maxPage
+ || minPage != ja.minPage || multiple != ja.multiple
+ || fromPage != ja.fromPage || toPage != ja.toPage
+ || ! printer.equals(ja.printer) || sides != ja.sides
+ || (pageRanges == null) != (ja.pageRanges == null))
+ return false;
+ if (pageRanges != ja.pageRanges)
+ for (int i = pageRanges.length; --i >= 0; )
+ if (pageRanges[i][0] != ja.pageRanges[i][0]
+ || pageRanges[i][1] != ja.pageRanges[i][1])
+ return false;
+ return true;
+ }
+
+ public int hashCode()
+ {
+ int hash = (selection.value << 6) ^ (destination.value << 5)
+ ^ (dialog.value << 3) ^ (multiple.value << 2) ^ sides.value
+ ^ (filename == null ? 0 : filename.hashCode())
+ ^ (printer == null ? 0 : printer.hashCode());
+ // The effect of the above fields on the hashcode match the JDK. However,
+ // I am unable to reverse engineer the effect of the fields listed below,
+ // so I am using my own implementation. Note that this still satisfies
+ // the general contract of hashcode, it just doesn't match the JDK.
+ hash ^= (copies << 27) ^ (maxPage << 22) ^ (minPage << 17);
+ if (pageRanges == null)
+ hash ^= (getFromPage() << 13) ^ (getToPage() << 8);
+ else
+ for (int i = pageRanges.length; --i >= 0; )
+ hash ^= (pageRanges[i][0] << 13) ^ (pageRanges[i][1] << 8);
+ return hash;
+ }
+
+ public String toString()
+ {
+ CPStringBuilder s = new CPStringBuilder("copies=").append(copies)
+ .append(",defaultSelection=").append(selection).append(",destination=")
+ .append(destination).append(",dialog=").append(dialog)
+ .append(",fileName=").append(filename).append(",fromPage=")
+ .append(getFromPage()).append(",maxPage=").append(maxPage)
+ .append(",minPage=").append(minPage)
+ .append(",multiple-document-handling=").append(multiple)
+ .append(",page-ranges=[");
+ if (pageRanges == null)
+ s.append(minPage).append(':').append(minPage).append(']');
+ else
+ for (int i = 0; i < pageRanges.length; i++)
+ s.append(pageRanges[i][0]).append(':').append(pageRanges[i][1])
+ .append(',');
+ s.setLength(s.length() - 1);
+ return s.append("],printer=").append(printer).append(",sides=")
+ .append(sides).append(",toPage=").append(getToPage()).toString();
+ }
+} // class JobAttributes
diff --git a/libjava/classpath/java/awt/KeyEventDispatcher.java b/libjava/classpath/java/awt/KeyEventDispatcher.java
new file mode 100644
index 000000000..30997278e
--- /dev/null
+++ b/libjava/classpath/java/awt/KeyEventDispatcher.java
@@ -0,0 +1,82 @@
+/* KeyEventDispatcher.java -- dispatches key events
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.KeyEvent;
+
+/**
+ * An instance of this interface coordinates with a KeyboardFocusManager to
+ * target and dispatch all key events. This allows retargeting, consuming,
+ * changing, or otherwise manipulating the key event before sending it on to
+ * a target.
+ *
+ * <p>By default, the KeyboardFocusManager is the sink for all key events not
+ * dispatched by other dispatchers. Therefore, it is unnecessary for the user
+ * to register the focus manager as a dispatcher.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see KeyboardFocusManager#addKeyEventDispatcher(KeyEventDispatcher)
+ * @see KeyboardFocusManager#removeKeyEventDispatcher(KeyEventDispatcher)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public interface KeyEventDispatcher
+{
+ /**
+ * Called by the KeyboardFocusManager to request that a key event be
+ * dispatched. The dispatcher is free to retarget the event, consume it,
+ * dispatch it, or make other changes. This is usually done to allow
+ * delivery of key events to objects other than the window in focus, such
+ * as for navigating non-focusable components. If this dispatcher chooses
+ * to dispatch the event itself, it should call <code>redispatchEvent</code>
+ * to avoid infinite recursion.
+ *
+ * <p>If the return value is false, the KeyEvent is passed to the next
+ * dispatcher in the chain, ending with the KeyboardFocusManager. If the
+ * return value is true, the event has been consumed (although it might
+ * have been ignored), and no further action will be taken on the event. Be
+ * sure to check whether the event was consumed before dispatching it
+ * further.
+ *
+ * @param e the key event
+ * @return true if the event has been consumed
+ * @see KeyboardFocusManager#redispatchEvent(Component, AWTEvent)
+ */
+ boolean dispatchKeyEvent(KeyEvent e);
+} // interface KeyEventDispatcher
diff --git a/libjava/classpath/java/awt/KeyEventPostProcessor.java b/libjava/classpath/java/awt/KeyEventPostProcessor.java
new file mode 100644
index 000000000..0b39dc250
--- /dev/null
+++ b/libjava/classpath/java/awt/KeyEventPostProcessor.java
@@ -0,0 +1,81 @@
+/* KeyEventPostProcessor.java -- performs actions after a key event dispatch
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.KeyEvent;
+
+/**
+ * An instance of this interface coordinates with a KeyboardFocusManager to
+ * target and dispatch all key events that are otherwise unconsumed. This
+ * allows events which take place when nothing has focus to still operate,
+ * such as menu keyboard shortcuts.
+ *
+ * <p>By default, the KeyboardFocusManager is the sink for all key events not
+ * post-processed elsewhere. Therefore, it is unnecessary for the user
+ * to register the focus manager as a dispatcher.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see KeyboardFocusManager#addKeyEventPostProcessor(KeyEventPostProcessor)
+ * @see KeyboardFocusManager#removeKeyEventPostProcessor(KeyEventPostProcessor)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public interface KeyEventPostProcessor
+{
+ /**
+ * Called by the KeyboardFocusManager to request that a key event be
+ * post-processed. Typically, the event has already been dispatched and
+ * handled, unless no object has focus. Thus, this allows global event
+ * handling for things like menu shortcuts. If this post-processor chooses
+ * to dispatch the event, it should call <code>redispatchEvent</code>
+ * to avoid infinite recursion.
+ *
+ * <p>If the return value is false, the KeyEvent is passed to the next
+ * dispatcher in the chain, ending with the KeyboardFocusManager. If the
+ * return value is true, the event has been consumed (although it might
+ * have been ignored), and no further action will be taken on the event. Be
+ * sure to check whether the event was consumed before dispatching it
+ * further.
+ *
+ * @param e the key event
+ * @return true if the event has been consumed
+ * @see KeyboardFocusManager#redispatchEvent(Component, AWTEvent)
+ */
+ boolean postProcessKeyEvent(KeyEvent e);
+} // interface KeyEventPostProcessor
diff --git a/libjava/classpath/java/awt/KeyboardFocusManager.java b/libjava/classpath/java/awt/KeyboardFocusManager.java
new file mode 100644
index 000000000..691351175
--- /dev/null
+++ b/libjava/classpath/java/awt/KeyboardFocusManager.java
@@ -0,0 +1,1479 @@
+/* KeyboardFocusManager.java -- manage component focusing via the keyboard
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.applet.Applet;
+import java.awt.FocusTraversalPolicy;
+import java.awt.event.FocusEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.WindowEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.beans.PropertyVetoException;
+import java.beans.VetoableChangeListener;
+import java.beans.VetoableChangeSupport;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * The <code>KeyboardFocusManager</code> handles the focusing of
+ * windows for receiving keyboard events. The manager handles
+ * the dispatch of all <code>FocusEvent</code>s and
+ * <code>KeyEvent</code>s, along with <code>WindowEvent</code>s
+ * relating to the focused window. Users can use the manager
+ * to ascertain the current focus owner and fire events.
+ * <br />
+ * <br />
+ * The focus owner is the <code>Component</code> that receives
+ * key events. The focus owner is either the currently focused
+ * window or a component within this window.
+ * <br />
+ * <br />
+ * The underlying native windowing system may denote the active
+ * window or its children with special decorations (e.g. a highlighted
+ * title bar). The active window is always either a <code>Frame</code>
+ * or <code>Dialog</code>, and is either the currently focused
+ * window or its owner.
+ * <br />
+ * <br />
+ * Applets may be partitioned into different applet contexts, according
+ * to their code base. In this case, each context has its own
+ * <code>KeyboardFocusManager</code>, as opposed to the global
+ * manager maintained by applets which share the same context.
+ * Each context is insulated from the others, and they don't interact.
+ * The resulting behaviour, as with context division, depends on the browser
+ * supporting the applets. Regardless, there can only ever be
+ * one focused window, one active window and one focus owner
+ * per <code>ClassLoader</code>.
+ * <br />
+ * <br />
+ * To support this separation of focus managers, the manager instances
+ * and the internal state information is grouped by the
+ * <code>ThreadGroup</code> to which it pertains. With respect to
+ * applets, each code base has its own <code>ThreadGroup</code>, so the
+ * isolation of each context is enforced within the manager.
+ * <br />
+ * <br />
+ * By default, the manager defines TAB and Ctrl+TAB as the
+ * forward focus traversal keys and Shift+TAB and Ctrl+Shift+TAB
+ * as the backward focus traversal keys. No up or down cycle
+ * traversal keys are defined by default. Traversal takes effect
+ * on the firing of a relevant <code>KEY_PRESSED</code> event.
+ * However, all other key events related to the use of the
+ * defined focus traversal key sequence are consumed and not
+ * dispatched.
+ * <br />
+ * <br />
+ * These default traversal keys come into effect on all windows
+ * for which no alternative set of keys is defined. This also
+ * applies recursively to any child components of such a window,
+ * which define no traversal keys of their own.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Thomas Fitzsimmons (fitzsim@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.4
+ */
+public abstract class KeyboardFocusManager
+ implements KeyEventDispatcher, KeyEventPostProcessor
+{
+ /** Identifies {@link AWTKeyStroke}s that move the focus forward in
+ the focus cycle. */
+ public static final int FORWARD_TRAVERSAL_KEYS = 0;
+
+ /** Identifies {@link AWTKeyStroke}s that move the focus backward in
+ the focus cycle. */
+ public static final int BACKWARD_TRAVERSAL_KEYS = 1;
+
+ /** Identifies {@link AWTKeyStroke}s that move the focus up to the
+ parent focus cycle root. */
+ public static final int UP_CYCLE_TRAVERSAL_KEYS = 2;
+
+ /** Identifies {@link AWTKeyStroke}s that move the focus down to the
+ child focus cycle root. */
+ public static final int DOWN_CYCLE_TRAVERSAL_KEYS = 3;
+
+ /** The set of {@link AWTKeyStroke}s that cause focus to be moved to
+ the next focusable Component in the focus cycle. */
+ private static final Set DEFAULT_FORWARD_KEYS;
+
+ /** The set of {@link AWTKeyStroke}s that cause focus to be moved to
+ the previous focusable Component in the focus cycle. */
+ private static final Set DEFAULT_BACKWARD_KEYS;
+
+ /** Populate the DEFAULT_FORWARD_KEYS and DEFAULT_BACKWARD_KEYS
+ {@link java.util.Set}s. */
+ static
+ {
+ Set s = new HashSet();
+ s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0));
+ s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
+ KeyEvent.CTRL_DOWN_MASK));
+ DEFAULT_FORWARD_KEYS = Collections.unmodifiableSet(s);
+ s = new HashSet();
+ s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
+ KeyEvent.SHIFT_DOWN_MASK));
+ s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
+ KeyEvent.SHIFT_DOWN_MASK
+ | KeyEvent.CTRL_DOWN_MASK));
+ DEFAULT_BACKWARD_KEYS = Collections.unmodifiableSet(s);
+ }
+
+ /** The global object {@link java.util.Map}s. */
+
+ /** For security reasons, {@link java.applet.Applet}s in different
+ codebases must be insulated from one another. Since {@link
+ KeyboardFocusManager}s have the ability to return {@link
+ Component}s from a given {@link java.applet.Applet}, each
+ codebase must have an independent {@link KeyboardFocusManager}.
+ Since each codebase has its own {@link ThreadGroup} in which its
+ {@link Applet}s run, it makes sense to partition {@link
+ KeyboardFocusManager}s according to {@link
+ java.lang.ThreadGroup}. Thus, currentKeyboardFocusManagers is a
+ {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}. */
+ private static Map currentKeyboardFocusManagers = new HashMap ();
+
+ /** {@link java.applet.Applet}s in one codebase must not be allowed
+ to access {@link Component}s in {@link java.applet.Applet}s in
+ other codebases. To enforce this restriction, we key the
+ following {@link java.util.Map}s on {@link java.lang.ThreadGroup}s (which
+ are per-codebase). For example, if {@link
+ java.lang.ThreadGroup} A calls {@link #setGlobalFocusOwner},
+ passing {@link Component} C, currentFocusOwners[A] is assigned
+ C, and all other currentFocusOwners values are nullified. Then
+ if {@link java.lang.ThreadGroup} A subsequently calls {@link
+ #getGlobalFocusOwner}, it will return currentFocusOwners[A],
+ that is, {@link Component} C. If another {@link
+ java.lang.ThreadGroup} K calls {@link #getGlobalFocusOwner}, it
+ will return currentFocusOwners[K], that is, null.
+
+ Since this is a static field, we ensure that there is only one
+ focused {@link Component} per class loader. */
+ private static Map currentFocusOwners = new HashMap ();
+
+ /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s
+ that stores the {@link Component} that owns the permanent
+ keyboard focus. @see currentFocusOwners */
+ private static Map currentPermanentFocusOwners = new HashMap ();
+
+ /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s
+ that stores the focused {@link Window}. @see
+ currentFocusOwners */
+ private static Map currentFocusedWindows = new HashMap ();
+
+ /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s
+ that stores the active {@link Window}. @see
+ currentFocusOwners */
+ private static Map currentActiveWindows = new HashMap ();
+
+ /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s
+ that stores the focus cycle root {@link Container}. @see
+ currentFocusOwners */
+ private static Map currentFocusCycleRoots = new HashMap ();
+
+ /** The default {@link FocusTraversalPolicy} that focus-managing
+ {@link Container}s will use to define their initial focus
+ traversal policy. */
+ private FocusTraversalPolicy defaultPolicy;
+
+ /** An array that stores the {@link #FORWARD_TRAVERSAL_KEYS}, {@link
+ #BACKWARD_TRAVERSAL_KEYS}, {@link #UP_CYCLE_TRAVERSAL_KEYS} and
+ {@link #DOWN_CYCLE_TRAVERSAL_KEYS} {@link AWTKeyStroke}s {@link
+ java.util.Set}s. */
+ private Set[] defaultFocusKeys = new Set[]
+ {
+ DEFAULT_FORWARD_KEYS, DEFAULT_BACKWARD_KEYS,
+ Collections.EMPTY_SET, Collections.EMPTY_SET
+ };
+
+ /**
+ * A utility class to support the handling of events relating to property changes.
+ */
+ private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport (this);
+
+ /**
+ * A utility class to support the handling of events relating to vetoable changes.
+ */
+ private final VetoableChangeSupport vetoableChangeSupport = new VetoableChangeSupport (this);
+
+ /** A list of {@link KeyEventDispatcher}s that process {@link
+ KeyEvent}s before they are processed the default keyboard focus
+ manager. */
+ private final ArrayList keyEventDispatchers = new ArrayList();
+
+ /** A list of {@link KeyEventPostProcessor}s that process unconsumed
+ {@link KeyEvent}s. */
+ private final ArrayList keyEventPostProcessors = new ArrayList();
+
+ /**
+ * Construct a KeyboardFocusManager.
+ */
+ public KeyboardFocusManager ()
+ {
+ }
+
+ /**
+ * Retrieve the keyboard focus manager associated with the {@link
+ * java.lang.ThreadGroup} to which the calling thread belongs.
+ *
+ * @return the keyboard focus manager associated with the current
+ * thread group
+ */
+ public static KeyboardFocusManager getCurrentKeyboardFocusManager ()
+ {
+ ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
+
+ if (currentKeyboardFocusManagers.get (currentGroup) == null)
+ setCurrentKeyboardFocusManager (null);
+
+ return (KeyboardFocusManager) currentKeyboardFocusManagers.get (currentGroup);
+ }
+
+ /**
+ * Set the keyboard focus manager associated with the {@link
+ * java.lang.ThreadGroup} to which the calling thread belongs.
+ *
+ * @param m the keyboard focus manager for the current thread group
+ */
+ public static void setCurrentKeyboardFocusManager (KeyboardFocusManager m)
+ {
+ SecurityManager sm = System.getSecurityManager ();
+ if (sm != null)
+ sm.checkPermission (new AWTPermission ("replaceKeyboardFocusManager"));
+
+ ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
+ KeyboardFocusManager manager;
+
+ if (m == null)
+ manager = new DefaultKeyboardFocusManager();
+ else
+ manager = m;
+
+ currentKeyboardFocusManagers.put (currentGroup, manager);
+ }
+
+ /**
+ * Retrieve the {@link Component} that has the keyboard focus, or
+ * null if the focus owner was not set by a thread in the current
+ * {@link java.lang.ThreadGroup}.
+ *
+ * @return the keyboard focus owner or null
+ */
+ public Component getFocusOwner ()
+ {
+ return (Component) getObject (currentFocusOwners);
+ }
+
+ /**
+ * Retrieve the {@link Component} that has the keyboard focus,
+ * regardless of whether or not it was set by a thread in the
+ * current {@link java.lang.ThreadGroup}. If there is no temporary
+ * focus owner in effect then this method will return the same value
+ * as {@link #getGlobalPermanentFocusOwner}.
+ *
+ * @return the keyboard focus owner
+ * @throws SecurityException if this is not the keyboard focus
+ * manager associated with the current {@link java.lang.ThreadGroup}
+ */
+ protected Component getGlobalFocusOwner ()
+ {
+ return (Component) getGlobalObject(currentFocusOwners, true);
+ }
+
+ /**
+ * Set the {@link Component} that will be returned by {@link
+ * #getFocusOwner} (when it is called from the current {@link
+ * java.lang.ThreadGroup}) and {@link #getGlobalFocusOwner}. This
+ * method does not actually transfer the keyboard focus.
+ *
+ * @param owner the Component to return from getFocusOwner and
+ * getGlobalFocusOwner
+ *
+ * @see Component#requestFocus()
+ * @see Component#requestFocusInWindow()
+ */
+ protected void setGlobalFocusOwner (Component owner)
+ {
+ if (owner == null || owner.focusable)
+ setGlobalObject (currentFocusOwners, owner, "focusOwner");
+ }
+
+ /**
+ * Clear the global focus owner and deliver a FOCUS_LOST event to
+ * the previously-focused {@link Component}. Until another {@link
+ * Component} becomes the keyboard focus owner, key events will be
+ * discarded by top-level windows.
+ */
+ public void clearGlobalFocusOwner ()
+ {
+ synchronized (currentFocusOwners)
+ {
+ Component focusOwner = getGlobalFocusOwner ();
+ Component permanentFocusOwner = getGlobalPermanentFocusOwner ();
+
+ setGlobalFocusOwner (null);
+ setGlobalPermanentFocusOwner (null);
+
+ // Inform the old focus owner that it has lost permanent
+ // focus.
+ if (focusOwner != null)
+ {
+ // We can't cache the event queue, because of
+ // bootstrapping issues. We need to set the default
+ // KeyboardFocusManager in EventQueue before the event
+ // queue is started.
+ EventQueue q = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
+ if (focusOwner != permanentFocusOwner)
+ q.postEvent (new FocusEvent (focusOwner, FocusEvent.FOCUS_LOST, true));
+ else
+ q.postEvent (new FocusEvent (focusOwner, FocusEvent.FOCUS_LOST, false));
+ }
+
+ if (focusOwner != permanentFocusOwner)
+ {
+ EventQueue q = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
+ q.postEvent (new FocusEvent (permanentFocusOwner, FocusEvent.FOCUS_LOST, false));
+ }
+ }
+ }
+
+ /**
+ * Retrieve the {@link Component} that has the permanent keyboard
+ * focus, or null if the focus owner was not set by a thread in the
+ * current {@link java.lang.ThreadGroup}.
+ *
+ * @return the keyboard focus owner or null
+ */
+ public Component getPermanentFocusOwner ()
+ {
+ return (Component) getObject (currentPermanentFocusOwners);
+ }
+
+ /**
+ * Retrieve the {@link Component} that has the permanent keyboard
+ * focus, regardless of whether or not it was set by a thread in the
+ * current {@link java.lang.ThreadGroup}.
+ *
+ * @return the keyboard focus owner
+ * @throws SecurityException if this is not the keyboard focus
+ * manager associated with the current {@link java.lang.ThreadGroup}
+ */
+ protected Component getGlobalPermanentFocusOwner ()
+ {
+ return (Component) getGlobalObject (currentPermanentFocusOwners, true);
+ }
+
+ /**
+ * Set the {@link Component} that will be returned by {@link
+ * #getPermanentFocusOwner} (when it is called from the current
+ * {@link java.lang.ThreadGroup}) and {@link
+ * #getGlobalPermanentFocusOwner}. This method does not actually
+ * transfer the keyboard focus.
+ *
+ * @param focusOwner the Component to return from
+ * getPermanentFocusOwner and getGlobalPermanentFocusOwner
+ *
+ * @see Component#requestFocus()
+ * @see Component#requestFocusInWindow()
+ */
+ protected void setGlobalPermanentFocusOwner (Component focusOwner)
+ {
+ if (focusOwner == null || focusOwner.focusable)
+ setGlobalObject (currentPermanentFocusOwners, focusOwner,
+ "permanentFocusOwner");
+ }
+
+ /**
+ * Retrieve the {@link Window} that is or contains the keyboard
+ * focus owner, or null if the focused window was not set by a
+ * thread in the current {@link java.lang.ThreadGroup}.
+ *
+ * @return the focused window or null
+ */
+ public Window getFocusedWindow ()
+ {
+ return (Window) getObject (currentFocusedWindows);
+ }
+
+ /**
+ * Retrieve the {@link Window} that is or contains the focus owner,
+ * regardless of whether or not the {@link Window} was set focused
+ * by a thread in the current {@link java.lang.ThreadGroup}.
+ *
+ * @return the focused window
+ * @throws SecurityException if this is not the keyboard focus
+ * manager associated with the current {@link java.lang.ThreadGroup}
+ */
+ protected Window getGlobalFocusedWindow ()
+ {
+ return (Window) getGlobalObject (currentFocusedWindows, true);
+ }
+
+ /**
+ * Set the {@link Window} that will be returned by {@link
+ * #getFocusedWindow} (when it is called from the current {@link
+ * java.lang.ThreadGroup}) and {@link #getGlobalFocusedWindow}.
+ * This method does not actually cause <code>window</code> to become
+ * the focused {@link Window}.
+ *
+ * @param window the Window to return from getFocusedWindow and
+ * getGlobalFocusedWindow
+ */
+ protected void setGlobalFocusedWindow (Window window)
+ {
+ if (window == null || window.focusable)
+ setGlobalObject (currentFocusedWindows, window, "focusedWindow");
+ }
+
+ /**
+ * Retrieve the active {@link Window}, or null if the active window
+ * was not set by a thread in the current {@link
+ * java.lang.ThreadGroup}.
+ *
+ * @return the active window or null
+ */
+ public Window getActiveWindow()
+ {
+ return (Window) getObject (currentActiveWindows);
+ }
+
+ /**
+ * Retrieve the active {@link Window}, regardless of whether or not
+ * the {@link Window} was made active by a thread in the current
+ * {@link java.lang.ThreadGroup}.
+ *
+ * @return the active window
+ * @throws SecurityException if this is not the keyboard focus
+ * manager associated with the current {@link java.lang.ThreadGroup}
+ */
+ protected Window getGlobalActiveWindow()
+ {
+ return (Window) getGlobalObject (currentActiveWindows, true);
+ }
+
+ /**
+ * Set the {@link Window} that will be returned by {@link
+ * #getActiveWindow} (when it is called from the current {@link
+ * java.lang.ThreadGroup}) and {@link #getGlobalActiveWindow}. This
+ * method does not actually cause <code>window</code> to be made
+ * active.
+ *
+ * @param window the Window to return from getActiveWindow and
+ * getGlobalActiveWindow
+ */
+ protected void setGlobalActiveWindow(Window window)
+ {
+ setGlobalObject (currentActiveWindows, window, "activeWindow");
+ }
+
+ /**
+ * Retrieve the default {@link FocusTraversalPolicy}.
+ * Focus-managing {@link Container}s use the returned object to
+ * define their initial focus traversal policy.
+ *
+ * @return a non-null default FocusTraversalPolicy object
+ */
+ public FocusTraversalPolicy getDefaultFocusTraversalPolicy ()
+ {
+ if (defaultPolicy == null)
+ defaultPolicy = new DefaultFocusTraversalPolicy ();
+ return defaultPolicy;
+ }
+
+ /**
+ * Set the {@link FocusTraversalPolicy} returned by {@link
+ * #getDefaultFocusTraversalPolicy}. Focus-managing {@link
+ * Container}s created after this call will use policy as their
+ * initial focus traversal policy. Existing {@link Container}s'
+ * focus traversal policies will not be affected by calls to this
+ * method.
+ *
+ * @param policy the FocusTraversalPolicy that will be returned by
+ * subsequent calls to getDefaultFocusTraversalPolicy
+ * @throws IllegalArgumentException if policy is null
+ */
+ public void setDefaultFocusTraversalPolicy (FocusTraversalPolicy policy)
+ {
+ if (policy == null)
+ throw new IllegalArgumentException ();
+ firePropertyChange ("defaultFocusTraversalPolicy", defaultPolicy, policy);
+ defaultPolicy = policy;
+ }
+
+ /**
+ * Set the default {@link java.util.Set} of focus traversal keys for
+ * one of the focus traversal directions.
+ *
+ * @param id focus traversal direction identifier
+ * @param keystrokes set of AWTKeyStrokes
+ *
+ * @see #FORWARD_TRAVERSAL_KEYS
+ * @see #BACKWARD_TRAVERSAL_KEYS
+ * @see #UP_CYCLE_TRAVERSAL_KEYS
+ * @see #DOWN_CYCLE_TRAVERSAL_KEYS
+ */
+ public void setDefaultFocusTraversalKeys (int id,
+ Set<? extends AWTKeyStroke>
+ keystrokes)
+ {
+ if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
+ throw new IllegalArgumentException ();
+
+ if (keystrokes == null)
+ throw new IllegalArgumentException ();
+
+ Set sa;
+ Set sb;
+ Set sc;
+ String type;
+ switch (id)
+ {
+ case FORWARD_TRAVERSAL_KEYS:
+ sa = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
+ sb = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
+ sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
+ type = "forwardDefaultFocusTraversalKeys";
+ break;
+ case BACKWARD_TRAVERSAL_KEYS:
+ sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
+ sb = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
+ sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
+ type = "backwardDefaultFocusTraversalKeys";
+ break;
+ case UP_CYCLE_TRAVERSAL_KEYS:
+ sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
+ sb = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
+ sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
+ type = "upCycleDefaultFocusTraversalKeys";
+ break;
+ case DOWN_CYCLE_TRAVERSAL_KEYS:
+ sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
+ sb = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
+ sc = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
+ type = "downCycleDefaultFocusTraversalKeys";
+ break;
+ default:
+ throw new IllegalArgumentException ();
+ }
+ int i = keystrokes.size ();
+ Iterator iter = keystrokes.iterator ();
+ while (--i >= 0)
+ {
+ Object o = iter.next ();
+ if (!(o instanceof AWTKeyStroke)
+ || sa.contains (o) || sb.contains (o) || sc.contains (o)
+ || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED)
+ throw new IllegalArgumentException ();
+ }
+ keystrokes = Collections.unmodifiableSet (new HashSet (keystrokes));
+ firePropertyChange (type, defaultFocusKeys[id], keystrokes);
+ defaultFocusKeys[id] = keystrokes;
+ }
+
+ /**
+ * Retrieve the default {@link java.util.Set} of focus traversal
+ * keys for one of the focus traversal directions.
+ *
+ * @param id focus traversal direction identifier
+ *
+ * @return the default set of AWTKeyStrokes
+ *
+ * @see #FORWARD_TRAVERSAL_KEYS
+ * @see #BACKWARD_TRAVERSAL_KEYS
+ * @see #UP_CYCLE_TRAVERSAL_KEYS
+ * @see #DOWN_CYCLE_TRAVERSAL_KEYS
+ */
+ public Set<AWTKeyStroke> getDefaultFocusTraversalKeys (int id)
+ {
+ if (id < FORWARD_TRAVERSAL_KEYS || id > DOWN_CYCLE_TRAVERSAL_KEYS)
+ throw new IllegalArgumentException ();
+ return defaultFocusKeys[id];
+ }
+
+ /**
+ * Retrieve the current focus cycle root, or null if the focus owner
+ * was not set by a thread in the current {@link
+ * java.lang.ThreadGroup}.
+ *
+ * @return the current focus cycle root or null
+ */
+ public Container getCurrentFocusCycleRoot ()
+ {
+ return (Container) getObject (currentFocusCycleRoots);
+ }
+
+ /**
+ * Retrieve the current focus cycle root, regardless of whether or
+ * not it was made set by a thread in the current {@link
+ * java.lang.ThreadGroup}.
+ *
+ * @return the current focus cycle root
+ * @throws SecurityException if this is not the keyboard focus
+ * manager associated with the current {@link java.lang.ThreadGroup}
+ */
+ protected Container getGlobalCurrentFocusCycleRoot ()
+ {
+ return (Container) getGlobalObject (currentFocusCycleRoots, true);
+ }
+
+ /**
+ * Set the {@link Container} that will be returned by {@link
+ * #getCurrentFocusCycleRoot} (when it is called from the current
+ * {@link java.lang.ThreadGroup}) and {@link
+ * #getGlobalCurrentFocusCycleRoot}. This method does not actually
+ * make <code>cycleRoot</code> the current focus cycle root.
+ *
+ * @param cycleRoot the focus cycle root to return from
+ * getCurrentFocusCycleRoot and getGlobalCurrentFocusCycleRoot
+ */
+ public void setGlobalCurrentFocusCycleRoot (Container cycleRoot)
+ {
+ setGlobalObject (currentFocusCycleRoots, cycleRoot, "currentFocusCycleRoot");
+ }
+
+ /**
+ * Registers the supplied property change listener for receiving
+ * events caused by the following property changes:
+ *
+ * <ul>
+ * <li>the current focus owner ("focusOwner")</li>
+ * <li>the permanent focus owner ("permanentFocusOwner")</li>
+ * <li>the focused window ("focusedWindow")</li>
+ * <li>the active window ("activeWindow")</li>
+ * <li>the default focus traversal policy ("defaultFocusTraversalPolicy")</li>
+ * <li>the default set of forward traversal keys ("forwardDefaultFocusTraversalKeys")</li>
+ * <li>the default set of backward traversal keys ("backwardDefaultFocusTraversalKeys")</li>
+ * <li>the default set of up cycle traversal keys ("upCycleDefaultFocusTraversalKeys")</li>
+ * <li>the default set of down cycle traversal keys ("downCycleDefaultFocusTraversalKeys")</li>
+ * <li>the current focus cycle root ("currentFocusCycleRoot")</li>
+ * </ul>
+ *
+ * If the supplied listener is null, nothing occurs.
+ *
+ * @param l the new listener to register.
+ * @see KeyboardFocusManager#addPropertyChangeListener(String, java.beans.PropertyChangeListener)
+ */
+ public void addPropertyChangeListener(PropertyChangeListener l)
+ {
+ if (l != null)
+ propertyChangeSupport.addPropertyChangeListener(l);
+ }
+
+ /**
+ * Removes the supplied property change listener from the list
+ * of registered listeners. If the supplied listener is null,
+ * nothing occurs.
+ *
+ * @param l the listener to remove.
+ */
+ public void removePropertyChangeListener(PropertyChangeListener l)
+ {
+ if (l != null)
+ propertyChangeSupport.removePropertyChangeListener(l);
+ }
+
+ /**
+ * Returns the currently registered property change listeners
+ * in array form. The returned array is empty if no listeners are
+ * currently registered.
+ *
+ * @return an array of registered property change listeners.
+ */
+ public PropertyChangeListener[] getPropertyChangeListeners()
+ {
+ return propertyChangeSupport.getPropertyChangeListeners();
+ }
+
+ /**
+ * Registers a property change listener for receiving events relating
+ * to a change to a specified property. The supplied property name can be
+ * either user-defined or one from the following list of properties
+ * relevant to this class:
+ *
+ * <ul>
+ * <li>the current focus owner ("focusOwner")</li>
+ * <li>the permanent focus owner ("permanentFocusOwner")</li>
+ * <li>the focused window ("focusedWindow")</li>
+ * <li>the active window ("activeWindow")</li>
+ * <li>the default focus traversal policy ("defaultFocusTraversalPolicy")</li>
+ * <li>the default set of forward traversal keys ("forwardDefaultFocusTraversalKeys")</li>
+ * <li>the default set of backward traversal keys ("backwardDefaultFocusTraversalKeys")</li>
+ * <li>the default set of up cycle traversal keys ("upCycleDefaultFocusTraversalKeys")</li>
+ * <li>the default set of down cycle traversal keys ("downCycleDefaultFocusTraversalKeys")</li>
+ * <li>the current focus cycle root ("currentFocusCycleRoot")</li>
+ * </ul>
+ *
+ * Nothing occurs if a null listener is supplied. null is regarded as a valid property name.
+ *
+ * @param name the name of the property to handle change events for.
+ * @param l the listener to register for changes to the specified property.
+ * @see KeyboardFocusManager#addPropertyChangeListener(java.beans.PropertyChangeListener)
+ */
+ public void addPropertyChangeListener(String name, PropertyChangeListener l)
+ {
+ if (l != null)
+ propertyChangeSupport.addPropertyChangeListener(name, l);
+ }
+
+ /**
+ * Removes the supplied property change listener registered for the
+ * specified property from the list of registered listeners. If the
+ * supplied listener is null, nothing occurs.
+ *
+ * @param name the name of the property the listener is
+ * monitoring changes to.
+ * @param l the listener to remove.
+ */
+ public void removePropertyChangeListener(String name,
+ PropertyChangeListener l)
+ {
+ if (l != null)
+ propertyChangeSupport.removePropertyChangeListener(name, l);
+ }
+
+ /**
+ * Returns the currently registered property change listeners
+ * in array form, which listen for changes to the supplied property.
+ * The returned array is empty, if no listeners are currently registered
+ * for events pertaining to the supplied property.
+ *
+ * @param name The property the returned listeners monitor for changes.
+ * @return an array of registered property change listeners which
+ * listen for changes to the supplied property.
+ */
+ public PropertyChangeListener[] getPropertyChangeListeners(String name)
+ {
+ return propertyChangeSupport.getPropertyChangeListeners(name);
+ }
+
+ /**
+ * Fires a property change event as a response to a change to
+ * to the specified property. The event is only fired if a
+ * change has actually occurred (i.e. o and n are different).
+ *
+ * @param name The name of the property to which a change occurred.
+ * @param o The old value of the property.
+ * @param n The new value of the property.
+ */
+ protected void firePropertyChange(String name, Object o, Object n)
+ {
+ propertyChangeSupport.firePropertyChange(name, o, n);
+ }
+
+ /**
+ * Registers a vetoable property change listener for receiving events
+ * relating to the following properties:
+ *
+ * <ul>
+ * <li>the current focus owner ("focusOwner")</li>
+ * <li>the permanent focus owner ("permanentFocusOwner")</li>
+ * <li>the focused window ("focusedWindow")</li>
+ * <li>the active window ("activeWindow")</li>
+ * </ul>
+ *
+ * Nothing occurs if a null listener is supplied.
+ *
+ * @param l the listener to register.
+ * @see KeyboardFocusManager#addVetoableChangeListener(String, java.beans.VetoableChangeListener)
+ */
+ public void addVetoableChangeListener(VetoableChangeListener l)
+ {
+ if (l != null)
+ vetoableChangeSupport.addVetoableChangeListener(l);
+ }
+
+ /**
+ * Removes the supplied vetoable property change listener from
+ * the list of registered listeners. If the supplied listener
+ * is null, nothing occurs.
+ *
+ * @param l the listener to remove.
+ */
+ public void removeVetoableChangeListener(VetoableChangeListener l)
+ {
+ if (l != null)
+ vetoableChangeSupport.removeVetoableChangeListener(l);
+ }
+
+ /**
+ * Returns the currently registered vetoable property change listeners
+ * in array form. The returned array is empty if no listeners are
+ * currently registered.
+ *
+ * @return an array of registered vetoable property change listeners.
+ * @since 1.4
+ */
+ public VetoableChangeListener[] getVetoableChangeListeners()
+ {
+ return vetoableChangeSupport.getVetoableChangeListeners();
+ }
+
+ /**
+ * Registers a vetoable property change listener for receiving events relating
+ * to a vetoable change to a specified property. The supplied property name can be
+ * either user-defined or one from the following list of properties
+ * relevant to this class:
+ *
+ * <ul>
+ * <li>the current focus owner ("focusOwner")</li>
+ * <li>the permanent focus owner ("permanentFocusOwner")</li>
+ * <li>the focused window ("focusedWindow")</li>
+ * <li>the active window ("activeWindow")</li>
+ * </ul>
+ *
+ * Nothing occurs if a null listener is supplied. null is regarded as a valid property name.
+ *
+ * @param name the name of the property to handle change events for.
+ * @param l the listener to register for changes to the specified property.
+ * @see KeyboardFocusManager#addVetoableChangeListener(java.beans.VetoableChangeListener)
+ */
+ public void addVetoableChangeListener(String name, VetoableChangeListener l)
+ {
+ if (l != null)
+ vetoableChangeSupport.addVetoableChangeListener(name, l);
+ }
+
+ /**
+ * Removes the supplied vetoable property change listener registered
+ * for the specified property from the list of registered listeners.
+ * If the supplied listener is null, nothing occurs.
+ *
+ * @param name the name of the vetoable property the listener is
+ * monitoring changes to.
+ * @param l the listener to remove.
+ */
+ public void removeVetoableChangeListener(String name,
+ VetoableChangeListener l)
+ {
+ if (l != null)
+ vetoableChangeSupport.removeVetoableChangeListener(name, l);
+ }
+
+ /**
+ * Returns the currently registered vetoable property change listeners
+ * in array form, which listen for changes to the supplied property.
+ * The returned array is empty, if no listeners are currently registered
+ * for events pertaining to the supplied property.
+ *
+ * @param name The property the returned listeners monitor for changes.
+ * @return an array of registered property change listeners which
+ * listen for changes to the supplied property.
+ * @since 1.4
+ */
+ public VetoableChangeListener[] getVetoableChangeListeners(String name)
+ {
+ return vetoableChangeSupport.getVetoableChangeListeners(name);
+ }
+
+ /**
+ * Fires a property change event as a response to a vetoable change to
+ * to the specified property. The event is only fired if a
+ * change has actually occurred (i.e. o and n are different).
+ * In the event that the property change is vetoed, the following
+ * occurs:
+ *
+ * <ol>
+ * <li>
+ * This method throws a <code>PropertyVetoException</code> to
+ * the proposed change.
+ * </li>
+ * <li>
+ * A new event is fired to reverse the previous change.
+ * </li>
+ * <li>
+ * This method again throws a <code>PropertyVetoException</code>
+ * in response to the reversion.
+ * </li>
+ * </ol>
+ *
+ * @param name The name of the property to which a change occurred.
+ * @param o The old value of the property.
+ * @param n The new value of the property.
+ * @throws PropertyVetoException if one of the listeners vetos
+ * the change by throwing this exception.
+ */
+ protected void fireVetoableChange(String name, Object o, Object n)
+ throws PropertyVetoException
+ {
+ vetoableChangeSupport.fireVetoableChange(name, o, n);
+ }
+
+ /**
+ * Adds a key event dispatcher to the list of registered dispatchers.
+ * When a key event is fired, each dispatcher's <code>dispatchKeyEvent</code>
+ * method is called in the order that they were added, prior to the manager
+ * dispatching the event itself. Notifications halt when one of the
+ * dispatchers returns true.
+ * <br />
+ * <br />
+ * The same dispatcher can exist multiple times within the list
+ * of registered dispatchers, and there is no limit on the length
+ * of this list. A null dispatcher is simply ignored.
+ *
+ * @param dispatcher The dispatcher to register.
+ */
+ public void addKeyEventDispatcher(KeyEventDispatcher dispatcher)
+ {
+ if (dispatcher != null)
+ keyEventDispatchers.add(dispatcher);
+ }
+
+ /**
+ * Removes the specified key event dispatcher from the list of
+ * registered dispatchers. The manager always dispatches events,
+ * regardless of its existence within the list. The manager
+ * can be added and removed from the list, as with any other
+ * dispatcher, but this does not affect its ability to dispatch
+ * key events. Non-existent and null dispatchers are simply ignored
+ * by this method.
+ *
+ * @param dispatcher The dispatcher to remove.
+ */
+ public void removeKeyEventDispatcher(KeyEventDispatcher dispatcher)
+ {
+ keyEventDispatchers.remove(dispatcher);
+ }
+
+ /**
+ * Returns the currently registered key event dispatchers in <code>List</code>
+ * form. At present, this only includes dispatchers explicitly registered
+ * via the <code>addKeyEventDispatcher()</code> method, but this behaviour
+ * is subject to change and should not be depended on. The manager itself
+ * may be a member of the list, but only if explicitly registered. If no
+ * dispatchers have been registered, the list will be empty.
+ *
+ * @return A list of explicitly registered key event dispatchers.
+ * @see KeyboardFocusManager#addKeyEventDispatcher(java.awt.KeyEventDispatcher)
+ */
+ protected List<KeyEventDispatcher> getKeyEventDispatchers ()
+ {
+ return (List<KeyEventDispatcher>) keyEventDispatchers.clone ();
+ }
+
+ /**
+ * Adds a key event post processor to the list of registered post processors.
+ * Post processors work in the same way as key event dispatchers, except
+ * that they are invoked after the manager has dispatched the key event,
+ * and not prior to this. Each post processor's <code>postProcessKeyEvent</code>
+ * method is called to see if any post processing needs to be performed. THe
+ * processors are called in the order in which they were added to the list,
+ * and notifications continue until one returns true. As with key event
+ * dispatchers, the manager is implicitly called following this process,
+ * regardless of whether or not it is present within the list.
+ * <br />
+ * <br />
+ * The same post processor can exist multiple times within the list
+ * of registered post processors, and there is no limit on the length
+ * of this list. A null post processor is simply ignored.
+ *
+ * @param postProcessor the post processor to register.
+ * @see KeyboardFocusManager#addKeyEventDispatcher(java.awt.KeyEventDispatcher)
+ */
+ public void addKeyEventPostProcessor (KeyEventPostProcessor postProcessor)
+ {
+ if (postProcessor != null)
+ keyEventPostProcessors.add (postProcessor);
+ }
+
+ /**
+ * Removes the specified key event post processor from the list of
+ * registered post processors. The manager always post processes events,
+ * regardless of its existence within the list. The manager
+ * can be added and removed from the list, as with any other
+ * post processor, but this does not affect its ability to post process
+ * key events. Non-existent and null post processors are simply ignored
+ * by this method.
+ *
+ * @param postProcessor the post processor to remove.
+ */
+ public void removeKeyEventPostProcessor (KeyEventPostProcessor postProcessor)
+ {
+ keyEventPostProcessors.remove (postProcessor);
+ }
+
+ /**
+ * Returns the currently registered key event post processors in <code>List</code>
+ * form. At present, this only includes post processors explicitly registered
+ * via the <code>addKeyEventPostProcessor()</code> method, but this behaviour
+ * is subject to change and should not be depended on. The manager itself
+ * may be a member of the list, but only if explicitly registered. If no
+ * post processors have been registered, the list will be empty.
+ *
+ * @return A list of explicitly registered key event post processors.
+ * @see KeyboardFocusManager#addKeyEventPostProcessor(java.awt.KeyEventPostProcessor)
+ */
+ protected List<KeyEventPostProcessor> getKeyEventPostProcessors ()
+ {
+ return (List<KeyEventPostProcessor>) keyEventPostProcessors.clone ();
+ }
+
+ /**
+ * The AWT event dispatcher uses this method to request that the manager
+ * handle a particular event. If the manager fails or refuses to
+ * dispatch the supplied event (this method returns false), the
+ * AWT event dispatcher will try to dispatch the event itself.
+ * <br />
+ * <br />
+ * The manager is expected to handle all <code>FocusEvent</code>s
+ * and <code>KeyEvent</code>s, and <code>WindowEvent</code>s
+ * relating to the focus. Dispatch is done with regard to the
+ * the focus owner and the currently focused and active windows.
+ * In handling the event, the source of the event may be overridden.
+ * <br />
+ * <br />
+ * The actual dispatching is performed by calling
+ * <code>redispatchEvent()</code>. This avoids the infinite recursion
+ * of dispatch requests which may occur if this method is called on
+ * the target component.
+ *
+ * @param e the event to dispatch.
+ * @return true if the event was dispatched.
+ * @see KeyboardFocusManager#redispatchEvent(java.awt.Component, java.awt.AWTEvent)
+ * @see KeyEvent
+ * @see FocusEvent
+ * @see WindowEvent
+ */
+ public abstract boolean dispatchEvent (AWTEvent e);
+
+ /**
+ * Handles redispatching of an event so that recursion of
+ * dispatch requests does not occur. Event dispatch methods
+ * within this manager (<code>dispatchEvent()</code>) and
+ * the key event dispatchers should use this method to handle
+ * dispatching rather than the dispatch method of the target
+ * component.
+ * <br />
+ * <br />
+ * <strong>
+ * This method is not intended for general consumption, and is
+ * only for the use of the aforementioned classes.
+ * </strong>
+ *
+ * @param target the target component to which the event is
+ * dispatched.
+ * @param e the event to dispatch.
+ */
+ public final void redispatchEvent (Component target, AWTEvent e)
+ {
+ e.isFocusManagerEvent = true;
+ target.dispatchEvent (e);
+ e.isFocusManagerEvent = false;
+ }
+
+ /**
+ * Attempts to dispatch key events for which no key event dispatcher
+ * has so far succeeded. This method is usually called by
+ * <code>dispatchEvent()</code> following the sending of the key
+ * event to any registered key event dispatchers. If the key
+ * event reaches this stage, none of the dispatchers returned
+ * true. This is, of course, always the case if there are no
+ * registered dispatchers.
+ * <br />
+ * <br />
+ * If this method also fails to handle the key event, then
+ * false is returned to the caller. In the case of
+ * <code>dispatchEvent()</code>, the calling method may try
+ * to handle the event itself or simply forward on the
+ * false result to its caller. When the event is dispatched
+ * by this method, a true result is propogated through the
+ * calling methods.
+ *
+ * @param e the key event to dispatch.
+ * @return true if the event was dispatched successfully.
+ */
+ public abstract boolean dispatchKeyEvent (KeyEvent e);
+
+ /**
+ * Handles the post processing of key events. By default,
+ * this method will map unhandled key events to appropriate
+ * <code>MenuShortcut</code>s. The event is consumed
+ * in the process and the shortcut is activated. This
+ * method is usually called by <code>dispatchKeyEvent</code>.
+ *
+ * @param e the key event to post process.
+ * @return true by default, as the event was handled.
+ */
+ public abstract boolean postProcessKeyEvent (KeyEvent e);
+
+ /**
+ * Handles focus traversal operations for key events which
+ * represent focus traversal keys in relation to the supplied
+ * component. The supplied component is assumed to have the
+ * focus, whether it does so or not, and the operation is
+ * carried out as appropriate, with this in mind.
+ *
+ * @param focused the component on which to perform focus traversal,
+ * on the assumption that this component has the focus.
+ * @param e the possible focus traversal key event.
+ */
+ public abstract void processKeyEvent (Component focused, KeyEvent e);
+
+ /**
+ * Delays all key events following the specified timestamp until the
+ * supplied component has focus. The AWT calls this method when it is
+ * determined that a focus change may occur within the native windowing
+ * system. Any key events which occur following the time specified by
+ * after are delayed until a <code>FOCUS_GAINED</code> event is received
+ * for the untilFocused component. The manager is responsible for ensuring
+ * this takes place.
+ *
+ * @param after the timestamp beyond which all key events are delayed until
+ * the supplied component gains focus.
+ * @param untilFocused the component to wait on gaining focus.
+ */
+ protected abstract void enqueueKeyEvents (long after, Component untilFocused);
+
+ /**
+ * Removes the key event block specified by the supplied timestamp and component.
+ * All delayed key events are released for normal dispatching following its
+ * removal and subsequent key events that would have been blocked are now
+ * immediately dispatched. If the specified timestamp is below 0, then
+ * the request with the oldest timestamp is removed.
+ *
+ * @param after the timestamp of the key event block to be removed, or a
+ * value smaller than 0 if the oldest is to be removed.
+ * @param untilFocused the component of the key event block to be removed.
+ */
+ protected abstract void dequeueKeyEvents (long after, Component untilFocused);
+
+ /**
+ * Discards all key event blocks relating to focus requirements for
+ * the supplied component, regardless of timestamp.
+ *
+ * @param comp the component of the key event block(s) to be removed.
+ */
+ protected abstract void discardKeyEvents (Component comp);
+
+ /**
+ * Moves the current focus to the next component following
+ * comp, based on the current focus traversal policy. By
+ * default, only visible, displayable, accepted components
+ * can receive focus. <code>Canvas</code>es, <code>Panel</code>s,
+ * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
+ * <code>Window</code>s and lightweight components are judged
+ * to be unacceptable by default. See the
+ * <code>DefaultFocusTraversalPolicy</code> for more details.
+ *
+ * @param comp the component prior to the one which will
+ * become the focus, following execution of this method.
+ * @see DefaultFocusTraversalPolicy
+ */
+ public abstract void focusNextComponent(Component comp);
+
+ /**
+ * Moves the current focus to the previous component, prior to
+ * comp, based on the current focus traversal policy. By
+ * default, only visible, displayable, accepted components
+ * can receive focus. <code>Canvas</code>es, <code>Panel</code>s,
+ * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
+ * <code>Window</code>s and lightweight components are judged
+ * to be unacceptable by default. See the
+ * <code>DefaultFocusTraversalPolicy</code> for more details.
+ *
+ * @param comp the component following the one which will
+ * become the focus, following execution of this method.
+ * @see DefaultFocusTraversalPolicy
+ */
+ public abstract void focusPreviousComponent(Component comp);
+
+ /**
+ * Moves the current focus upwards by one focus cycle.
+ * Both the current focus owner and current focus cycle root
+ * become the focus cycle root of the supplied component.
+ * However, in the case of a <code>Window</code>, the default
+ * focus component becomes the focus owner and the focus cycle
+ * root is not changed.
+ *
+ * @param comp the component used as part of the focus traversal.
+ */
+ public abstract void upFocusCycle(Component comp);
+
+ /**
+ * Moves the current focus downwards by one focus cycle.
+ * If the supplied container is a focus cycle root, then this
+ * becomes the current focus cycle root and the focus goes
+ * to the default component of the specified container.
+ * Nothing happens for non-focus cycle root containers.
+ *
+ * @param cont the container used as part of the focus traversal.
+ */
+ public abstract void downFocusCycle(Container cont);
+
+ /**
+ * Moves the current focus to the next component, based on the
+ * current focus traversal policy. By default, only visible,
+ * displayable, accepted component can receive focus.
+ * <code>Canvas</code>es, <code>Panel</code>s,
+ * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
+ * <code>Window</code>s and lightweight components are judged
+ * to be unacceptable by default. See the
+ * <code>DefaultFocusTraversalPolicy</code> for more details.
+ *
+ * @see DefaultFocusTraversalPolicy
+ */
+ public final void focusNextComponent()
+ {
+ focusNextComponent (null);
+ }
+
+ /**
+ * Moves the current focus to the previous component, based on the
+ * current focus traversal policy. By default, only visible,
+ * displayable, accepted component can receive focus.
+ * <code>Canvas</code>es, <code>Panel</code>s,
+ * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
+ * <code>Window</code>s and lightweight components are judged
+ * to be unacceptable by default. See the
+ * <code>DefaultFocusTraversalPolicy</code> for more details.
+ *
+ * @see DefaultFocusTraversalPolicy
+ */
+ public final void focusPreviousComponent()
+ {
+ focusPreviousComponent (null);
+ }
+
+ /**
+ * Moves the current focus upwards by one focus cycle,
+ * so that the new focus owner is the focus cycle root
+ * of the current owner. The current focus cycle root then
+ * becomes the focus cycle root of the new focus owner.
+ * However, in the case of the focus cycle root of the
+ * current focus owner being a <code>Window</code>, the default
+ * component of this window becomes the focus owner and the
+ * focus cycle root is not changed.
+ */
+ public final void upFocusCycle()
+ {
+ upFocusCycle (null);
+ }
+
+ /**
+ * Moves the current focus downwards by one focus cycle,
+ * iff the current focus cycle root is a <code>Container</code>.
+ * Usually, the new focus owner is set to the default component
+ * of the container and the current focus cycle root is set
+ * to the current focus owner. Nothing occurs if the current
+ * focus cycle root is not a container.
+ */
+ public final void downFocusCycle()
+ {
+ Component focusOwner = getGlobalFocusOwner ();
+ if (focusOwner instanceof Container
+ && ((Container) focusOwner).isFocusCycleRoot ())
+ downFocusCycle ((Container) focusOwner);
+ }
+
+ /**
+ * Retrieve an object from one of the global object {@link
+ * java.util.Map}s, if the object was set by the a thread in the
+ * current {@link java.lang.ThreadGroup}. Otherwise, return null.
+ *
+ * @param globalMap one of the global object Maps
+ *
+ * @return a global object set by the current ThreadGroup, or null
+ *
+ * @see #getFocusOwner()
+ * @see #getPermanentFocusOwner()
+ * @see #getFocusedWindow()
+ * @see #getActiveWindow()
+ * @see #getCurrentFocusCycleRoot()
+ */
+ private Object getObject (Map globalMap)
+ {
+ ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
+ return globalMap.get (currentGroup);
+ }
+
+ /**
+ * Retrieve an object from one of the global object {@link
+ * java.util.Map}s, regardless of whether or not the object was set
+ * by a thread in the current {@link java.lang.ThreadGroup}.
+ *
+ * @param globalMap one of the global object Maps
+ *
+ * @return a global object set by the current ThreadGroup, or null
+ *
+ * @throws SecurityException if this is not the keyboard focus
+ * manager associated with the current {@link java.lang.ThreadGroup}
+ *
+ * @see #getGlobalFocusOwner()
+ * @see #getGlobalPermanentFocusOwner()
+ * @see #getGlobalFocusedWindow()
+ * @see #getGlobalActiveWindow()
+ * @see #getGlobalCurrentFocusCycleRoot()
+ */
+ private Object getGlobalObject (Map globalMap, boolean checkThread)
+ {
+ if (checkThread)
+ {
+ ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
+ KeyboardFocusManager managerForCallingThread =
+ (KeyboardFocusManager) currentKeyboardFocusManagers.get(currentGroup);
+
+ if (this != managerForCallingThread)
+ throw new SecurityException ("Attempted to retrieve an object from a "
+ + "keyboard focus manager that isn't "
+ + "associated with the current thread group.");
+ }
+ synchronized (globalMap)
+ {
+ Collection globalObjects = globalMap.values ();
+ Iterator i = globalObjects.iterator ();
+ Component globalObject;
+
+ while (i.hasNext ())
+ {
+ globalObject = (Component) i.next ();
+ if (globalObject != null)
+ return globalObject;
+ }
+ }
+
+ // No Object was found.
+ return null;
+ }
+
+ /**
+ * Set an object in one of the global object {@link java.util.Map}s,
+ * that will be returned by subsequent calls to getGlobalObject on
+ * the same {@link java.util.Map}.
+ *
+ * @param globalMap one of the global object Maps
+ * @param newObject the object to set
+ * @param property the property that will change
+ *
+ * @see #setGlobalFocusOwner(Component)
+ * @see #setGlobalPermanentFocusOwner(Component)
+ * @see #setGlobalFocusedWindow(Window)
+ * @see #setGlobalActiveWindow(Window)
+ * @see #setGlobalCurrentFocusCycleRoot(Container)
+ */
+ private void setGlobalObject (Map globalMap,
+ Object newObject,
+ String property)
+ {
+ synchronized (globalMap)
+ {
+ // Save old object.
+ Object oldObject = getGlobalObject(globalMap, false);
+
+ // Nullify old object.
+ Collection threadGroups = globalMap.keySet ();
+ Iterator i = threadGroups.iterator ();
+ while (i.hasNext ())
+ {
+ ThreadGroup oldThreadGroup = (ThreadGroup) i.next ();
+ if (globalMap.get (oldThreadGroup) != null)
+ {
+ globalMap.put (oldThreadGroup, null);
+ // There should only be one object set at a time, so
+ // we can short circuit.
+ break;
+ }
+ }
+
+ ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
+ firePropertyChange (property, oldObject, newObject);
+ try
+ {
+ fireVetoableChange (property, oldObject, newObject);
+ // Set new object.
+ globalMap.put (currentGroup, newObject);
+ }
+ catch (PropertyVetoException e)
+ {
+ }
+ }
+ }
+
+
+ /**
+ * Maps focus requests from heavyweight to lightweight components.
+ */
+ private static HashMap focusRequests = new HashMap();
+
+ /**
+ * Retargets focus events that come from the peer (which only know about
+ * heavyweight components) to go to the correct lightweight component
+ * if appropriate.
+ *
+ * @param ev the event to check
+ *
+ * @return the retargetted event
+ */
+ static AWTEvent retargetFocusEvent(AWTEvent ev)
+ {
+ if (ev instanceof FocusEvent)
+ {
+ FocusEvent fe = (FocusEvent) ev;
+ Component target = fe.getComponent();
+ if (focusRequests.containsKey(target))
+ {
+ Component lightweight = (Component) focusRequests.get(target);
+ ev = new FocusEvent(lightweight, fe.id, fe.isTemporary());
+ focusRequests.remove(target);
+ }
+ }
+ return ev;
+ }
+
+ /**
+ * Adds a lightweight focus request for a heavyweight component.
+ *
+ * @param heavyweight the heavyweight from which we will receive a focus
+ * event soon
+ * @param lightweight the lightweight that ultimately receives the request
+ */
+ static void addLightweightFocusRequest(Component heavyweight,
+ Component lightweight)
+ {
+ focusRequests.put(heavyweight, lightweight);
+ }
+}
diff --git a/libjava/classpath/java/awt/Label.java b/libjava/classpath/java/awt/Label.java
new file mode 100644
index 000000000..1522dac36
--- /dev/null
+++ b/libjava/classpath/java/awt/Label.java
@@ -0,0 +1,294 @@
+/* Label.java -- Java label widget
+ Copyright (C) 1999, 2000, 2002, 2004, 2005, 2006, Free Software
+ Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.peer.LabelPeer;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+
+/**
+ * This component is used for displaying simple text strings that cannot
+ * be edited by the user.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+public class Label extends Component implements Accessible
+{
+
+ /**
+ * Alignment constant aligning the text to the left of its window.
+ */
+ public static final int LEFT = 0;
+
+ /**
+ * Alignment constant aligning the text in the center of its window.
+ */
+ public static final int CENTER = 1;
+
+ /**
+ * Alignment constant aligning the text to the right of its window.
+ */
+ public static final int RIGHT = 2;
+
+ // Serialization version constant:
+ private static final long serialVersionUID = 3094126758329070636L;
+
+ /**
+ * @serial Indicates the alignment of the text within this label's window.
+ * This is one of the constants in this class. The default value is
+ * <code>LEFT</code>.
+ */
+ private int alignment;
+
+ /**
+ * @serial The text displayed in the label
+ */
+ private String text;
+
+ /**
+ * Initializes a new instance of <code>Label</code> with no text.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public Label()
+ {
+ this("", LEFT);
+ }
+
+ /**
+ * Initializes a new instance of <code>Label</code> with the specified
+ * text that is aligned to the left.
+ *
+ * @param text The text of the label.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public Label(String text)
+ {
+ this(text, LEFT);
+ }
+
+ /**
+ * Initializes a new instance of <code>Label</code> with the specified
+ * text and alignment.
+ *
+ * @param text The text of the label.
+ * @param alignment The desired alignment for the text in this label,
+ * which must be one of <code>LEFT</code>, <code>CENTER</code>, or
+ * <code>RIGHT</code>.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public Label(String text, int alignment)
+ {
+ setAlignment(alignment);
+ setText(text);
+
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException();
+ }
+
+ /**
+ * Returns the constant indicating the alignment of the text in this
+ * label. The value returned will be one of the alignment constants
+ * from this class.
+ *
+ * @return The alignment of the text in the label.
+ */
+ public int getAlignment()
+ {
+ return(alignment);
+ }
+
+ /**
+ * Sets the text alignment of this label to the specified value.
+ *
+ * @param alignment The desired alignment for the text in this label,
+ * which must be one of <code>LEFT</code>, <code>CENTER</code>, or
+ * <code>RIGHT</code>.
+ */
+ public synchronized void setAlignment(int alignment)
+ {
+ if (alignment != CENTER && alignment != LEFT && alignment != RIGHT)
+ throw new IllegalArgumentException("invalid alignment: " + alignment);
+ this.alignment = alignment;
+ if (peer != null)
+ {
+ LabelPeer lp = (LabelPeer) peer;
+ lp.setAlignment(alignment);
+ }
+ }
+
+ /**
+ * Returns the text displayed in this label.
+ *
+ * @return The text for this label.
+ */
+ public String getText()
+ {
+ return text;
+ }
+
+ /**
+ * Sets the text in this label to the specified value.
+ *
+ * @param text The new text for this label.
+ */
+ public synchronized void setText(String text)
+ {
+ if ((this.text == null && text != null)
+ || (this.text != null && ! this.text.equals(text)))
+ {
+ this.text = text;
+
+ if (peer != null)
+ {
+ LabelPeer lp = (LabelPeer) peer;
+ lp.setText(text);
+ }
+ invalidate();
+ }
+ }
+
+ /**
+ * Notifies this label that it has been added to a container, causing
+ * the peer to be created. This method is called internally by the AWT
+ * system.
+ */
+ public void addNotify()
+ {
+ if (peer == null)
+ peer = getToolkit().createLabel(this);
+ super.addNotify();
+ }
+
+ /**
+ * Returns a parameter string useful for debugging.
+ *
+ * @return A debugging string.
+ */
+ protected String paramString()
+ {
+ return ("text=" + getText() + ",alignment=" +
+ getAlignment() + "," + super.paramString());
+ }
+
+ /**
+ * This class provides accessibility support for the label.
+ */
+ protected class AccessibleAWTLabel
+ extends AccessibleAWTComponent
+ {
+ /**
+ * For compatability with Sun's JDK 1.4.2 rev. 5
+ */
+ private static final long serialVersionUID = -3568967560160480438L;
+
+ /**
+ * Constructor for the accessible label.
+ */
+ public AccessibleAWTLabel()
+ {
+ }
+
+ /**
+ * Returns the accessible name for the label. This is
+ * the text used in the label.
+ *
+ * @return a <code>String</code> containing the accessible
+ * name for this label.
+ */
+ public String getAccessibleName()
+ {
+ return getText();
+ }
+
+ /**
+ * Returns the accessible role for the label.
+ *
+ * @return an instance of <code>AccessibleRole</code>, describing
+ * the role of the label.
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.LABEL;
+ }
+
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>Label</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTLabel();
+ return accessibleContext;
+ }
+
+ /**
+ * Generate a unique name for this button.
+ *
+ * @return A unique name for this button.
+ */
+ String generateName()
+ {
+ return "label" + getUniqueLong();
+ }
+
+ /**
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long nextLabelNumber;
+
+ private static synchronized long getUniqueLong()
+ {
+ return nextLabelNumber++;
+ }
+
+}
diff --git a/libjava/classpath/java/awt/LayoutManager.java b/libjava/classpath/java/awt/LayoutManager.java
new file mode 100644
index 000000000..62ff8087e
--- /dev/null
+++ b/libjava/classpath/java/awt/LayoutManager.java
@@ -0,0 +1,92 @@
+/* LayoutManager.java -- lay out elements in a Container
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This interface is for laying out containers in a particular sequence.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see Container
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public interface LayoutManager
+{
+ /**
+ * Adds the specified component to the layout group.
+ *
+ * @param name the name of the component to add
+ * @param component the component to add
+ */
+ void addLayoutComponent(String name, Component component);
+
+ /**
+ * Removes the specified component from the layout group.
+ *
+ * @param component the component to remove
+ */
+ void removeLayoutComponent(Component component);
+
+ /**
+ * Calculates the preferred size for this container, taking into account
+ * the components it contains.
+ *
+ * @param parent the parent container to lay out
+ * @return the preferred dimensions of this container
+ * @see #minimumLayoutSize(Container)
+ */
+ Dimension preferredLayoutSize(Container parent);
+
+ /**
+ * Calculates the minimum size for this container, taking into account
+ * the components it contains.
+ *
+ * @param parent the parent container to lay out
+ * @return the minimum dimensions of this container
+ * @see #preferredLayoutSize(Container)
+ */
+ Dimension minimumLayoutSize(Container parent);
+
+ /**
+ * Lays out the components in the given container.
+ *
+ * @param parent the container to lay out
+ */
+ void layoutContainer(Container parent);
+} // interface LayoutManager
diff --git a/libjava/classpath/java/awt/LayoutManager2.java b/libjava/classpath/java/awt/LayoutManager2.java
new file mode 100644
index 000000000..45fc5430f
--- /dev/null
+++ b/libjava/classpath/java/awt/LayoutManager2.java
@@ -0,0 +1,100 @@
+/* LayoutManager2.java -- enhanced layout manager
+ Copyright (C) 1999, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * Layout manager for laying out containers based on contraints. The
+ * constraints control how the layout will proceed.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see LayoutManager
+ * @see Container
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public interface LayoutManager2 extends LayoutManager
+{
+ /**
+ * Adds the specified component to the layout, with the specified
+ * constraints object.
+ *
+ * @param component the component to add
+ * @param constraints the constraints to satisfy
+ */
+ void addLayoutComponent(Component component, Object constraints);
+
+ /**
+ * Determines the maximum size of the specified target container.
+ *
+ * @param target the container to lay out
+ * @return the maximum size of the container
+ * @see Component#getMaximumSize()
+ */
+ Dimension maximumLayoutSize(Container target);
+
+ /**
+ * Returns the preferred X axis alignment for the specified target
+ * container. This value will range from 0 to 1 where 0 is alignment
+ * closest to the origin, 0.5 is centered, and 1 is aligned furthest
+ * from the origin.
+ *
+ * @param target the target container
+ * @return the x-axis alignment preference
+ */
+ float getLayoutAlignmentX(Container target);
+
+ /**
+ * Returns the preferred Y axis alignment for the specified target
+ * container. This value will range from 0 to 1 where 0 is alignment
+ * closest to the origin, 0.5 is centered, and 1 is aligned furthest
+ * from the origin.
+ *
+ * @param target the target container
+ * @return the y-axis alignment preference
+ */
+ float getLayoutAlignmentY(Container target);
+
+ /**
+ * Forces the layout manager to purge any cached information about the
+ * layout of the target container. This will force it to be recalculated.
+ *
+ * @param target the target container
+ */
+ void invalidateLayout(Container target);
+} // interface LayoutManager2
diff --git a/libjava/classpath/java/awt/LightweightDispatcher.java b/libjava/classpath/java/awt/LightweightDispatcher.java
new file mode 100644
index 000000000..11b83d8bf
--- /dev/null
+++ b/libjava/classpath/java/awt/LightweightDispatcher.java
@@ -0,0 +1,362 @@
+/* LightweightDispatcher.java -- Dispatches mouse events to lightweights
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.InputEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseWheelEvent;
+import java.awt.peer.LightweightPeer;
+import java.util.WeakHashMap;
+
+/**
+ * Redispatches mouse events to lightweight components. The native peers know
+ * nothing about the lightweight components and thus mouse events are always
+ * targetted at Windows or heavyweight components. This class listenes directly
+ * on the eventqueue and dispatches mouse events to lightweight components.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+final class LightweightDispatcher
+{
+
+ /**
+ * Maps thread groups to lightweight dispatcher instances. We need to
+ * have one instance per thread group so that 2 or more applets or otherwise
+ * separated applications (like in OSGI) do not interfer with each other.
+ */
+ private static WeakHashMap instances = new WeakHashMap();
+
+ /**
+ * The last mouse event target. If the target changes, additional
+ * MOUSE_ENTERED and MOUSE_EXITED events must be dispatched.
+ */
+ private Component lastTarget;
+
+ /**
+ * The current mouseEventTarget.
+ */
+ private Component mouseEventTarget;
+
+ /**
+ * Returns an instance of LightweightDispatcher for the current thread's
+ * thread group.
+ *
+ * @return an instance of LightweightDispatcher for the current thread's
+ * thread group
+ */
+ static LightweightDispatcher getInstance()
+ {
+ Thread t = Thread.currentThread();
+ ThreadGroup tg = t.getThreadGroup();
+ LightweightDispatcher instance = (LightweightDispatcher) instances.get(tg);
+ if (instance == null)
+ {
+ instance = new LightweightDispatcher();
+ instances.put(tg, instance);
+ }
+ return instance;
+ }
+
+ /**
+ * Creates a new LightweightDispatcher. This is private to prevent access
+ * from outside. Use {@link #getInstance()} instead.
+ */
+ private LightweightDispatcher()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Receives notification if a mouse event passes along the eventqueue.
+ *
+ * @param event the event
+ */
+ public boolean dispatchEvent(final AWTEvent event)
+ {
+ if (event instanceof MouseEvent)
+ {
+ MouseEvent mouseEvent = (MouseEvent) event;
+ return handleMouseEvent(mouseEvent);
+ }
+ return false;
+ }
+
+ /**
+ * Handles all mouse events that are targetted at toplevel containers
+ * (Window instances) and dispatches them to the correct lightweight child.
+ *
+ * @param ev the mouse event
+ * @return whether or not we found a lightweight that handled the event.
+ */
+ private boolean handleMouseEvent(final MouseEvent ev)
+ {
+ Container container = (Container) ev.getSource();
+ Component target = findTarget(container, ev.getX(), ev.getY());
+ trackEnterExit(target, ev);
+ int id = ev.getID();
+
+ // Dont update the mouseEventTarget when dragging. Also, MOUSE_CLICKED
+ // must be dispatched to the original target of MOUSE_PRESSED, so don't
+ // update in this case either.
+ if (! isDragging(ev) && id != MouseEvent.MOUSE_CLICKED)
+ mouseEventTarget = (target != container) ? target : null;
+
+ if (mouseEventTarget != null)
+ {
+ switch (id)
+ {
+ case MouseEvent.MOUSE_ENTERED:
+ case MouseEvent.MOUSE_EXITED:
+ // This is already handled in trackEnterExit().
+ break;
+ case MouseEvent.MOUSE_PRESSED:
+ case MouseEvent.MOUSE_RELEASED:
+ case MouseEvent.MOUSE_MOVED:
+ redispatch(ev, mouseEventTarget, id);
+ break;
+ case MouseEvent.MOUSE_CLICKED:
+ // MOUSE_CLICKED must be dispatched to the original target of
+ // MOUSE_PRESSED.
+ if (target == mouseEventTarget)
+ redispatch(ev, mouseEventTarget, id);
+ break;
+ case MouseEvent.MOUSE_DRAGGED:
+ if (isDragging(ev))
+ redispatch(ev, mouseEventTarget, id);
+ break;
+ case MouseEvent.MOUSE_WHEEL:
+ redispatch(ev, mouseEventTarget, id);
+ }
+ ev.consume();
+ }
+
+ return ev.isConsumed();
+ }
+
+ /**
+ * Finds the actual target for a mouseevent, starting at <code>c</code>.
+ * This searches through the children of the container and finds the first
+ * one which is showing, at the location from the mouse event and has
+ * a MouseListener or MouseMotionListener attached. If no such child component
+ * is found, null is returned.
+ *
+ * @param c the container to search through
+ * @param loc the mouse event point
+ *
+ * @return the actual receiver of the mouse event, or null, if no such
+ * component has been found
+ */
+ private Component findTarget(final Container c, final int x, final int y)
+ {
+ Component target = null;
+
+ // First we check the children of the container.
+
+ // Note: It is important that we use the package private Container
+ // fields ncomponents and component here. There are applications
+ // that override getComponentCount()
+ // and getComponent() to hide internal components, which makes
+ // the LightweightDispatcher not work correctly in these cases.
+ // As a positive sideeffect this is slightly more efficient.
+ int nChildren = c.ncomponents;
+ for (int i = 0; i < nChildren && target == null; i++)
+ {
+ Component child = c.component[i];
+ int childX = x - child.x;
+ int childY = y - child.y;
+ if (child != null && child.visible
+ && child.peer instanceof LightweightPeer
+ && child.contains(childX, childY))
+ {
+ // Check if there's a deeper possible target.
+ if (child instanceof Container)
+ {
+ Component deeper = findTarget((Container) child,
+ childX, childY);
+ if (deeper != null)
+ target = deeper;
+ }
+ // Check if the child itself is interested in mouse events.
+ else if (isMouseListening(child))
+ target = child;
+ }
+ }
+
+ // Check the container itself, if we didn't find a target yet.
+ if (target == null && c.contains(x, y) && isMouseListening(c))
+ target = c;
+
+ return target;
+ }
+
+ /**
+ * Checks if the specified component would be interested in a mouse event.
+ *
+ * @param c the component to check
+ *
+ * @return <code>true</code> if the component has mouse listeners installed,
+ * <code>false</code> otherwise
+ */
+ private boolean isMouseListening(final Component c)
+ {
+ // Note: It is important to NOT check if the component is listening
+ // for a specific event (for instance, mouse motion events). The event
+ // gets dispatched to the component if the component is listening
+ // for ANY mouse event, even when the component is not listening for the
+ // specific type of event. There are applications that depend on this
+ // (sadly).
+ return c.mouseListener != null
+ || c.mouseMotionListener != null
+ || c.mouseWheelListener != null
+ || (c.eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0
+ || (c.eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0
+ || (c.eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0;
+ }
+
+ /**
+ * Tracks MOUSE_ENTERED and MOUSE_EXIT as well as MOUSE_MOVED and
+ * MOUSE_DRAGGED and creates synthetic MOUSE_ENTERED and MOUSE_EXITED for
+ * lightweight component.s
+ *
+ * @param target the current mouse event target
+ * @param ev the mouse event
+ */
+ private void trackEnterExit(final Component target, final MouseEvent ev)
+ {
+ int id = ev.getID();
+ if (target != lastTarget)
+ {
+ if (lastTarget != null)
+ redispatch(ev, lastTarget, MouseEvent.MOUSE_EXITED);
+ if (id == MouseEvent.MOUSE_EXITED)
+ ev.consume();
+ if (target != null)
+ redispatch(ev, target, MouseEvent.MOUSE_ENTERED);
+ if (id == MouseEvent.MOUSE_ENTERED)
+ ev.consume();
+ lastTarget = target;
+ }
+
+ }
+
+ /**
+ * Redispatches the specified mouse event to the specified target with the
+ * specified id.
+ *
+ * @param ev the mouse event
+ * @param target the new target
+ * @param id the new id
+ */
+ private void redispatch(MouseEvent ev, Component target, int id)
+ {
+ Component source = ev.getComponent();
+ assert target != null;
+ if (target.isShowing())
+ {
+ // Translate coordinates.
+ int x = ev.getX();
+ int y = ev.getY();
+ for (Component c = target; c != null && c != source; c = c.getParent())
+ {
+ x -= c.x;
+ y -= c.y;
+ }
+
+ // Retarget event.
+ MouseEvent retargeted;
+ if (id == MouseEvent.MOUSE_WHEEL)
+ {
+ MouseWheelEvent mwe = (MouseWheelEvent) ev;
+ retargeted = new MouseWheelEvent(target, id, ev.getWhen(),
+ ev.getModifiers()
+ | ev.getModifiersEx(), x, y,
+ ev.getClickCount(),
+ ev.isPopupTrigger(),
+ mwe.getScrollType(),
+ mwe.getScrollAmount(),
+ mwe.getWheelRotation());
+ }
+ else
+ {
+ retargeted = new MouseEvent(target, id, ev.getWhen(),
+ ev.getModifiers() | ev.getModifiersEx(),
+ x, y, ev.getClickCount(),
+ ev.isPopupTrigger(), ev.getButton());
+ }
+
+ if (target == source)
+ ((Container) target).dispatchNoLightweight(retargeted);
+ else
+ target.dispatchEvent(retargeted);
+ }
+ }
+
+ /**
+ * Determines if we are in the middle of a drag operation, that is, if
+ * any of the buttons is held down.
+ *
+ * @param ev the mouse event to check
+ *
+ * @return <code>true</code> if we are in the middle of a drag operation,
+ * <code>false</code> otherwise
+ */
+ private boolean isDragging(MouseEvent ev)
+ {
+ int mods = ev.getModifiersEx();
+ int id = ev.getID();
+ if (id == MouseEvent.MOUSE_PRESSED || id == MouseEvent.MOUSE_RELEASED)
+ {
+ switch (ev.getButton())
+ {
+ case MouseEvent.BUTTON1:
+ mods ^= InputEvent.BUTTON1_DOWN_MASK;
+ break;
+ case MouseEvent.BUTTON2:
+ mods ^= InputEvent.BUTTON2_DOWN_MASK;
+ break;
+ case MouseEvent.BUTTON3:
+ mods ^= InputEvent.BUTTON3_DOWN_MASK;
+ break;
+ }
+ }
+ return (mods & (InputEvent.BUTTON1_DOWN_MASK
+ | InputEvent.BUTTON2_DOWN_MASK
+ | InputEvent.BUTTON3_DOWN_MASK)) != 0;
+ }
+}
diff --git a/libjava/classpath/java/awt/List.java b/libjava/classpath/java/awt/List.java
new file mode 100644
index 000000000..dc1199bbc
--- /dev/null
+++ b/libjava/classpath/java/awt/List.java
@@ -0,0 +1,1222 @@
+/* List.java -- A listbox widget
+ Copyright (C) 1999, 2002, 2004, 2006, Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.peer.ListPeer;
+import java.util.EventListener;
+import java.util.Vector;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleSelection;
+import javax.accessibility.AccessibleState;
+import javax.accessibility.AccessibleStateSet;
+
+/**
+ * Class that implements a listbox widget
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class List extends Component
+ implements ItemSelectable, Accessible
+{
+
+ /**
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_list_number;
+
+ // Serialization constant
+ private static final long serialVersionUID = -3304312411574666869L;
+
+ // FIXME: Need read/writeObject
+
+ /**
+ * @serial The items in the list.
+ */
+ private Vector items = new Vector();
+
+ /**
+ * @serial Indicates whether or not multiple items can be selected
+ * simultaneously.
+ */
+ private boolean multipleMode;
+
+ /**
+ * @serial The number of rows in the list. This is set on creation
+ * only and cannot be modified.
+ */
+ private int rows;
+
+ /**
+ * @serial An array of the item indices that are selected.
+ */
+ private int[] selected;
+
+ /**
+ * @serial An index value used by <code>makeVisible()</code> and
+ * <code>getVisibleIndex</code>.
+ */
+ private int visibleIndex = -1;
+
+ // The list of ItemListeners for this object.
+ private ItemListener item_listeners;
+
+ // The list of ActionListeners for this object.
+ private ActionListener action_listeners;
+
+ /**
+ * Initializes a new instance of <code>List</code> with no visible lines
+ * and multi-select disabled.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ * @since 1.1
+ */
+ public List()
+ {
+ this(4, false);
+ }
+
+ /**
+ * Initializes a new instance of <code>List</code> with the specified
+ * number of visible lines and multi-select disabled.
+ *
+ * @param rows The number of visible rows in the list.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public List(int rows)
+ {
+ this(rows, false);
+ }
+
+ /**
+ * Initializes a new instance of <code>List</code> with the specified
+ * number of lines and the specified multi-select setting.
+ *
+ * @param rows The number of visible rows in the list.
+ * @param multipleMode <code>true</code> if multiple lines can be selected
+ * simultaneously, <code>false</code> otherwise.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public List(int rows, boolean multipleMode)
+ {
+ if (rows == 0)
+ this.rows = 4;
+ else
+ this.rows = rows;
+
+ this.multipleMode = multipleMode;
+ selected = new int[0];
+
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException();
+
+ }
+
+ /**
+ * Returns the number of items in this list.
+ *
+ * @return The number of items in this list.
+ *
+ * @since 1.1
+ */
+ public int getItemCount()
+ {
+ return countItems();
+ }
+
+ /**
+ * Returns the number of items in this list.
+ *
+ * @return The number of items in this list.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getItemCount()</code>
+ */
+ public int countItems()
+ {
+ return items.size();
+ }
+
+ /**
+ * Returns the complete list of items.
+ *
+ * @return The complete list of items in the list.
+ *
+ * @since 1.1
+ */
+ public synchronized String[] getItems()
+ {
+ String[] l_items = new String[getItemCount()];
+
+ items.copyInto(l_items);
+ return(l_items);
+ }
+
+ /**
+ * Returns the item at the specified index.
+ *
+ * @param index The index of the item to retrieve.
+ *
+ * @exception IndexOutOfBoundsException If the index value is not valid.
+ */
+ public String getItem(int index)
+ {
+ return((String) items.elementAt(index));
+ }
+
+ /**
+ * Returns the number of visible rows in the list.
+ *
+ * @return The number of visible rows in the list.
+ */
+ public int getRows()
+ {
+ return(rows);
+ }
+
+ /**
+ * Tests whether or not multi-select mode is enabled.
+ *
+ * @return <code>true</code> if multi-select mode is enabled,
+ * <code>false</code> otherwise.
+ *
+ * @since 1.1
+ */
+ public boolean isMultipleMode()
+ {
+ return allowsMultipleSelections ();
+ }
+
+ /**
+ * Tests whether or not multi-select mode is enabled.
+ *
+ * @return <code>true</code> if multi-select mode is enabled,
+ * <code>false</code> otherwise.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>isMultipleMode()</code>.
+ */
+ public boolean allowsMultipleSelections()
+ {
+ return multipleMode;
+ }
+
+ /**
+ * This method enables or disables multiple selection mode for this
+ * list.
+ *
+ * @param multipleMode <code>true</code> to enable multiple mode,
+ * <code>false</code> otherwise.
+ *
+ * @since 1.1
+ */
+ public void setMultipleMode(boolean multipleMode)
+ {
+ setMultipleSelections (multipleMode);
+ }
+
+ /**
+ * This method enables or disables multiple selection mode for this
+ * list.
+ *
+ * @param multipleMode <code>true</code> to enable multiple mode,
+ * <code>false</code> otherwise.
+ *
+ * @deprecated
+ */
+ public void setMultipleSelections(boolean multipleMode)
+ {
+ this.multipleMode = multipleMode;
+
+ ListPeer peer = (ListPeer) getPeer();
+ if (peer != null)
+ peer.setMultipleMode(multipleMode);
+
+ }
+
+ /**
+ * Returns the minimum size of this component.
+ *
+ * @return The minimum size of this component.
+ *
+ * @since 1.1
+ */
+ public Dimension getMinimumSize()
+ {
+ return getMinimumSize(getRows());
+ }
+
+ /**
+ * Returns the minimum size of this component.
+ *
+ * @return The minimum size of this component.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getMinimumSize</code>.
+ */
+ public Dimension minimumSize()
+ {
+ return minimumSize(getRows());
+ }
+
+ /**
+ * Returns the minimum size of this component assuming it had the specified
+ * number of rows.
+ *
+ * @param rows The number of rows to size for.
+ *
+ * @return The minimum size of this component.
+ *
+ * @since 1.1
+ */
+ public Dimension getMinimumSize(int rows)
+ {
+ return minimumSize(rows);
+ }
+
+ /**
+ * Returns the minimum size of this component assuming it had the specified
+ * number of rows.
+ *
+ * @param rows The number of rows to size for.
+ *
+ * @return The minimum size of this component.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getMinimumSize(int)</code>>
+ */
+ public Dimension minimumSize(int rows)
+ {
+ ListPeer peer = (ListPeer) getPeer();
+ if (peer != null)
+ return peer.minimumSize(rows);
+ else
+ return new Dimension(0, 0);
+ }
+
+ /**
+ * Returns the preferred size of this component.
+ *
+ * @return The preferred size of this component.
+ *
+ * @since 1.1
+ */
+ public Dimension getPreferredSize()
+ {
+ return getPreferredSize(getRows());
+ }
+
+ /**
+ * Returns the preferred size of this component.
+ *
+ * @return The preferred size of this component.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getPreferredSize</code>.
+ */
+ public Dimension preferredSize()
+ {
+ return preferredSize(getRows());
+ }
+
+ /**
+ * Returns the preferred size of this component assuming it had the specified
+ * number of rows.
+ *
+ * @param rows The number of rows to size for.
+ *
+ * @return The preferred size of this component.
+ *
+ * @since 1.1
+ */
+ public Dimension getPreferredSize(int rows)
+ {
+ return preferredSize(rows);
+ }
+
+ /**
+ * Returns the preferred size of this component assuming it had the specified
+ * number of rows.
+ *
+ * @param rows The number of rows to size for.
+ *
+ * @return The preferred size of this component.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getPreferredSize(int)</code>>
+ */
+ public Dimension preferredSize(int rows)
+ {
+ ListPeer peer = (ListPeer)getPeer();
+ if (peer != null)
+ return peer.preferredSize(rows);
+ else
+ return getSize();
+ }
+
+ /**
+ * This method adds the specified item to the end of the list.
+ *
+ * @param item The item to add to the list.
+ *
+ * @since 1.1
+ */
+ public void add(String item)
+ {
+ add (item, -1);
+ }
+
+ /**
+ * This method adds the specified item to the end of the list.
+ *
+ * @param item The item to add to the list.
+ *
+ * @deprecated Use add() instead.
+ */
+ public void addItem(String item)
+ {
+ addItem(item, -1);
+ }
+
+ /**
+ * Adds the specified item to the specified location in the list.
+ * If the desired index is -1 or greater than the number of rows
+ * in the list, then the item is added to the end.
+ *
+ * @param item The item to add to the list.
+ * @param index The location in the list to add the item, or -1 to add
+ * to the end.
+ *
+ * @since 1.1
+ */
+ public void add(String item, int index)
+ {
+ addItem(item, index);
+ }
+
+ /**
+ * Adds the specified item to the specified location in the list.
+ * If the desired index is -1 or greater than the number of rows
+ * in the list, then the item is added to the end.
+ *
+ * @param item The item to add to the list.
+ * @param index The location in the list to add the item, or -1 to add
+ * to the end.
+ *
+ * @deprecated Use add() instead.
+ */
+ public void addItem(String item, int index)
+ {
+ if (item == null)
+ item = "";
+
+ if (index < -1)
+ index = -1;
+
+ if ((index == -1) || (index >= items.size ()))
+ items.addElement (item);
+ else
+ items.insertElementAt(item, index);
+
+ ListPeer peer = (ListPeer) getPeer();
+ if (peer != null)
+ peer.add (item, index);
+ }
+
+ /**
+ * Deletes the item at the specified index.
+ *
+ * @param index The index of the item to delete.
+ *
+ * @exception IllegalArgumentException If the index is not valid
+ *
+ * @deprecated
+ */
+ public void delItem(int index) throws IllegalArgumentException
+ {
+ boolean selected = false;
+ if (isSelected(index))
+ {
+ selected = true;
+ deselect(index);
+ }
+
+ items.removeElementAt (index);
+
+ if (selected)
+ select(index);
+
+ ListPeer peer = (ListPeer) getPeer();
+ if (peer != null)
+ peer.delItems (index, index);
+ }
+
+ /**
+ * Deletes the item at the specified index.
+ *
+ * @param index The index of the item to delete.
+ *
+ * @exception IllegalArgumentException If the index is not valid
+ *
+ * @since 1.1
+ */
+ public void remove(int index) throws IllegalArgumentException
+ {
+ delItem(index);
+ }
+
+ /**
+ * Deletes all items in the specified index range.
+ *
+ * @param start The beginning index of the range to delete.
+ * @param end The ending index of the range to delete.
+ *
+ * @exception IllegalArgumentException If the indexes are not valid
+ *
+ * @deprecated This method is deprecated for some unknown reason.
+ */
+ public synchronized void delItems(int start, int end)
+ throws IllegalArgumentException
+ {
+ // We must run the loop in reverse direction.
+ for (int i = end; i >= start; --i)
+ items.removeElementAt (i);
+ if (peer != null)
+ {
+ ListPeer l = (ListPeer) peer;
+ l.delItems (start, end);
+ }
+ }
+
+ /**
+ * Deletes the first occurrence of the specified item from the list.
+ *
+ * @param item The item to delete.
+ *
+ * @exception IllegalArgumentException If the specified item does not exist.
+ *
+ * @since 1.1
+ */
+ public synchronized void remove(String item) throws IllegalArgumentException
+ {
+ int index = items.indexOf(item);
+ if (index == -1)
+ throw new IllegalArgumentException("List element to delete not found");
+
+ remove(index);
+ }
+
+ /**
+ * Deletes all of the items from the list.
+ *
+ * @since 1.1
+ */
+ public synchronized void removeAll()
+ {
+ clear();
+ }
+
+ /**
+ * Deletes all of the items from the list.
+ *
+ * @deprecated This method is deprecated in favor of <code>removeAll()</code>.
+ */
+ public void clear()
+ {
+ items.clear();
+
+ ListPeer peer = (ListPeer) getPeer();
+ if (peer != null)
+ peer.removeAll();
+
+ selected = new int[0];
+ }
+
+ /**
+ * Replaces the item at the specified index with the specified item.
+ *
+ * @param item The new item value.
+ * @param index The index of the item to replace.
+ *
+ * @exception ArrayIndexOutOfBoundsException If the index is not valid.
+ */
+ public synchronized void replaceItem(String item, int index)
+ throws ArrayIndexOutOfBoundsException
+ {
+ if ((index < 0) || (index >= items.size()))
+ throw new ArrayIndexOutOfBoundsException("Bad list index: " + index);
+
+ items.insertElementAt(item, index + 1);
+ items.removeElementAt (index);
+
+ if (peer != null)
+ {
+ ListPeer l = (ListPeer) peer;
+
+ /* We add first and then remove so that the selected
+ item remains the same */
+ l.add (item, index + 1);
+ l.delItems (index, index);
+ }
+ }
+
+ /**
+ * Returns the index of the currently selected item. -1 will be returned
+ * if there are no selected rows or if there are multiple selected rows.
+ *
+ * @return The index of the selected row.
+ */
+ public synchronized int getSelectedIndex()
+ {
+ if (peer != null)
+ {
+ ListPeer l = (ListPeer) peer;
+ selected = l.getSelectedIndexes ();
+ }
+
+ if (selected == null || selected.length != 1)
+ return -1;
+
+ return selected[0];
+ }
+
+ /**
+ * Returns an array containing the indexes of the rows that are
+ * currently selected.
+ *
+ * @return A list of indexes of selected rows.
+ */
+ public synchronized int[] getSelectedIndexes()
+ {
+ if (peer != null)
+ {
+ ListPeer l = (ListPeer) peer;
+ selected = l.getSelectedIndexes();
+ }
+
+ return selected;
+ }
+
+ /**
+ * Returns the item that is currently selected, or <code>null</code> if there
+ * is no item selected. FIXME: What happens if multiple items selected?
+ *
+ * @return The selected item, or <code>null</code> if there is no
+ * selected item.
+ */
+ public synchronized String getSelectedItem()
+ {
+ int index = getSelectedIndex();
+ if (index == -1)
+ return(null);
+
+ return((String) items.elementAt(index));
+ }
+
+ /**
+ * Returns the list of items that are currently selected in this list.
+ *
+ * @return The list of currently selected items.
+ */
+ public synchronized String[] getSelectedItems()
+ {
+ int[] indexes = getSelectedIndexes();
+ if (indexes == null)
+ return(new String[0]);
+
+ String[] retvals = new String[indexes.length];
+ if (retvals.length > 0)
+ for (int i = 0 ; i < retvals.length; i++)
+ retvals[i] = (String)items.elementAt(indexes[i]);
+
+ return(retvals);
+ }
+
+ /**
+ * Returns the list of items that are currently selected in this list as
+ * an array of type <code>Object[]</code> instead of <code>String[]</code>.
+ *
+ * @return The list of currently selected items.
+ */
+ public synchronized Object[] getSelectedObjects()
+ {
+ int[] indexes = getSelectedIndexes();
+ if (indexes == null)
+ return(new Object[0]);
+
+ Object[] retvals = new Object[indexes.length];
+ if (retvals.length > 0)
+ for (int i = 0 ; i < retvals.length; i++)
+ retvals[i] = items.elementAt(indexes[i]);
+
+ return(retvals);
+ }
+
+ /**
+ * Tests whether or not the specified index is selected.
+ *
+ * @param index The index to test.
+ *
+ * @return <code>true</code> if the index is selected, <code>false</code>
+ * otherwise.
+ *
+ * @since 1.1
+ */
+ public boolean isIndexSelected(int index)
+ {
+ return isSelected(index);
+ }
+
+ /**
+ * Tests whether or not the specified index is selected.
+ *
+ * @param index The index to test.
+ *
+ * @return <code>true</code> if the index is selected, <code>false</code>
+ * otherwise.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>isIndexSelected(int)</code>.
+ */
+ public boolean isSelected(int index)
+ {
+ int[] indexes = getSelectedIndexes();
+
+ for (int i = 0; i < indexes.length; i++)
+ if (indexes[i] == index)
+ return true;
+
+ return false;
+ }
+
+ /**
+ * This method ensures that the item at the specified index is visible.
+ *
+ * @param index The index of the item to be made visible.
+ */
+ public synchronized void makeVisible(int index)
+ throws IllegalArgumentException
+ {
+ visibleIndex = index;
+ if (peer != null)
+ {
+ ListPeer l = (ListPeer) peer;
+ l.makeVisible (index);
+ }
+ }
+
+ /**
+ * Returns the index of the last item that was made visible via the
+ * <code>makeVisible()</code> method.
+ *
+ * @return The index of the last item made visible via the
+ * <code>makeVisible()</code> method.
+ */
+ public int getVisibleIndex()
+ {
+ return visibleIndex;
+ }
+
+ /**
+ * Makes the item at the specified index selected.
+ *
+ * @param index The index of the item to select.
+ */
+ public synchronized void select(int index)
+ {
+ ListPeer lp = (ListPeer) getPeer();
+ if (lp != null)
+ lp.select(index);
+
+ if (selected != null)
+ {
+ boolean found = false;
+ for (int i = 0; i < selected.length; i++)
+ {
+ if (selected[i] == index)
+ found = true;
+ }
+ if (! found)
+ {
+ if (! isMultipleMode())
+ {
+ selected = new int[] { index };
+ return;
+ }
+ int[] temp = new int[selected.length + 1];
+ System.arraycopy(selected, 0, temp, 0, selected.length);
+ temp[selected.length] = index;
+ selected = temp;
+ }
+ }
+ else
+ {
+ selected = new int[1];
+ selected[0] = index;
+ }
+ }
+
+ /**
+ * Makes the item at the specified index not selected.
+ *
+ * @param index The index of the item to unselect.
+ */
+ public synchronized void deselect(int index)
+ {
+ if (isSelected(index))
+ {
+ ListPeer lp = (ListPeer)getPeer();
+ if (lp != null)
+ lp.deselect(index);
+
+ int[] temp = new int[selected.length - 1];
+ for (int i = 0; i < temp.length; i++)
+ {
+ if (selected[i] != index)
+ temp[i] = selected[i];
+ else
+ {
+ System.arraycopy(selected, i + 1, temp, i,
+ selected.length - i - 1);
+ break;
+ }
+ }
+ selected = temp;
+ }
+ }
+
+ /**
+ * Notifies this object to create its native peer.
+ */
+ public void addNotify()
+ {
+ if (peer == null)
+ peer = getToolkit ().createList(this);
+ super.addNotify ();
+ }
+
+ /**
+ * Notifies this object to destroy its native peer.
+ */
+ public void removeNotify()
+ {
+ super.removeNotify();
+ }
+
+ /**
+ * Adds the specified <code>ActionListener</code> to the list of
+ * registered listeners for this object.
+ *
+ * @param listener The listener to add.
+ *
+ * @since 1.1
+ */
+ public synchronized void addActionListener(ActionListener listener)
+ {
+ action_listeners = AWTEventMulticaster.add(action_listeners, listener);
+ }
+
+ /**
+ * Removes the specified <code>ActionListener</code> from the list of
+ * registers listeners for this object.
+ *
+ * @param listener The listener to remove.
+ *
+ * @since 1.1
+ */
+ public synchronized void removeActionListener(ActionListener listener)
+ {
+ action_listeners = AWTEventMulticaster.remove(action_listeners, listener);
+ }
+
+ /**
+ * Adds the specified <code>ItemListener</code> to the list of
+ * registered listeners for this object.
+ *
+ * @param listener The listener to add.
+ *
+ * @since 1.1
+ */
+ public synchronized void addItemListener(ItemListener listener)
+ {
+ item_listeners = AWTEventMulticaster.add(item_listeners, listener);
+ }
+
+ /**
+ * Removes the specified <code>ItemListener</code> from the list of
+ * registers listeners for this object.
+ *
+ * @param listener The listener to remove.
+ *
+ * @since 1.1
+ */
+ public synchronized void removeItemListener(ItemListener listener)
+ {
+ item_listeners = AWTEventMulticaster.remove(item_listeners, listener);
+ }
+
+ /**
+ * Processes the specified event for this object. If the event is an
+ * instance of <code>ActionEvent</code> then the
+ * <code>processActionEvent()</code> method is called. Similarly, if the
+ * even is an instance of <code>ItemEvent</code> then the
+ * <code>processItemEvent()</code> method is called. Otherwise the
+ * superclass method is called to process this event.
+ *
+ * @param event The event to process.
+ *
+ * @since 1.1
+ */
+ protected void processEvent(AWTEvent event)
+ {
+ if (event instanceof ActionEvent)
+ processActionEvent((ActionEvent)event);
+ else if (event instanceof ItemEvent)
+ processItemEvent((ItemEvent)event);
+ else
+ super.processEvent(event);
+ }
+
+ /**
+ * This method processes the specified event by dispatching it to any
+ * registered listeners. Note that this method will only get called if
+ * action events are enabled. This will happen automatically if any
+ * listeners are added, or it can be done "manually" by calling
+ * the <code>enableEvents()</code> method.
+ *
+ * @param event The event to process.
+ *
+ * @since 1.1
+ */
+ protected void processActionEvent(ActionEvent event)
+ {
+ if (action_listeners != null)
+ action_listeners.actionPerformed(event);
+ }
+
+ /**
+ * This method processes the specified event by dispatching it to any
+ * registered listeners. Note that this method will only get called if
+ * item events are enabled. This will happen automatically if any
+ * listeners are added, or it can be done "manually" by calling
+ * the <code>enableEvents()</code> method.
+ *
+ * @param event The event to process.
+ *
+ * @since 1.1
+ */
+ protected void processItemEvent(ItemEvent event)
+ {
+ if (item_listeners != null)
+ item_listeners.itemStateChanged(event);
+ }
+
+ void dispatchEventImpl(AWTEvent e)
+ {
+ if (e.id <= ItemEvent.ITEM_LAST
+ && e.id >= ItemEvent.ITEM_FIRST
+ && (item_listeners != null
+ || (eventMask & AWTEvent.ITEM_EVENT_MASK) != 0))
+ processEvent(e);
+ else if (e.id <= ActionEvent.ACTION_LAST
+ && e.id >= ActionEvent.ACTION_FIRST
+ && (action_listeners != null
+ || (eventMask & AWTEvent.ACTION_EVENT_MASK) != 0))
+ processEvent(e);
+ else
+ super.dispatchEventImpl(e);
+ }
+
+ /**
+ * Returns a debugging string for this object.
+ *
+ * @return A debugging string for this object.
+ */
+ protected String paramString()
+ {
+ return "multiple=" + multipleMode + ",rows=" + rows + super.paramString();
+ }
+
+ /**
+ * Returns an array of all the objects currently registered as FooListeners
+ * upon this <code>List</code>. FooListeners are registered using the
+ * addFooListener method.
+ *
+ * @exception ClassCastException If listenerType doesn't specify a class or
+ * interface that implements java.util.EventListener.
+ *
+ * @since 1.3
+ */
+ public <T extends EventListener> T[] getListeners (Class<T> listenerType)
+ {
+ if (listenerType == ActionListener.class)
+ return AWTEventMulticaster.getListeners (action_listeners, listenerType);
+
+ if (listenerType == ItemListener.class)
+ return AWTEventMulticaster.getListeners (item_listeners, listenerType);
+
+ return super.getListeners (listenerType);
+ }
+
+ /**
+ * Returns all action listeners registered to this object.
+ *
+ * @since 1.4
+ */
+ public ActionListener[] getActionListeners ()
+ {
+ return (ActionListener[]) getListeners (ActionListener.class);
+ }
+
+ /**
+ * Returns all action listeners registered to this object.
+ *
+ * @since 1.4
+ */
+ public ItemListener[] getItemListeners ()
+ {
+ return (ItemListener[]) getListeners (ItemListener.class);
+ }
+
+ // Accessibility internal class
+ protected class AccessibleAWTList extends AccessibleAWTComponent
+ implements AccessibleSelection, ItemListener, ActionListener
+ {
+ private static final long serialVersionUID = 7924617370136012829L;
+
+ protected class AccessibleAWTListChild extends AccessibleAWTComponent
+ implements Accessible
+ {
+ private static final long serialVersionUID = 4412022926028300317L;
+
+ // Field names are fixed by serialization spec.
+ private List parent;
+ private int indexInParent;
+
+ public AccessibleAWTListChild(List parent, int indexInParent)
+ {
+ this.parent = parent;
+ this.indexInParent = indexInParent;
+ if (parent == null)
+ this.indexInParent = -1;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.Accessible#getAccessibleContext()
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ return this;
+ }
+
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.LIST_ITEM;
+ }
+
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ AccessibleStateSet states = super.getAccessibleStateSet();
+ if (parent.isIndexSelected(indexInParent))
+ states.add(AccessibleState.SELECTED);
+ return states;
+ }
+
+ public int getAccessibleIndexInParent()
+ {
+ return indexInParent;
+ }
+
+ }
+
+ public AccessibleAWTList()
+ {
+ addItemListener(this);
+ addActionListener(this);
+ }
+
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.LIST;
+ }
+
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ AccessibleStateSet states = super.getAccessibleStateSet();
+ states.add(AccessibleState.SELECTABLE);
+ if (isMultipleMode())
+ states.add(AccessibleState.MULTISELECTABLE);
+ return states;
+ }
+
+ public int getAccessibleChildrenCount()
+ {
+ return getItemCount();
+ }
+
+ public Accessible getAccessibleChild(int i)
+ {
+ if (i >= getItemCount())
+ return null;
+ return new AccessibleAWTListChild(List.this, i);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleSelection#getAccessibleSelectionCount()
+ */
+ public int getAccessibleSelectionCount()
+ {
+ return getSelectedIndexes().length;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleSelection#getAccessibleSelection()
+ */
+ public AccessibleSelection getAccessibleSelection()
+ {
+ return this;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleSelection#getAccessibleSelection(int)
+ */
+ public Accessible getAccessibleSelection(int i)
+ {
+ int[] items = getSelectedIndexes();
+ if (i >= items.length)
+ return null;
+ return new AccessibleAWTListChild(List.this, items[i]);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleSelection#isAccessibleChildSelected(int)
+ */
+ public boolean isAccessibleChildSelected(int i)
+ {
+ return isIndexSelected(i);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleSelection#addAccessibleSelection(int)
+ */
+ public void addAccessibleSelection(int i)
+ {
+ select(i);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleSelection#removeAccessibleSelection(int)
+ */
+ public void removeAccessibleSelection(int i)
+ {
+ deselect(i);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleSelection#clearAccessibleSelection()
+ */
+ public void clearAccessibleSelection()
+ {
+ for (int i = 0; i < getItemCount(); i++)
+ deselect(i);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleSelection#selectAllAccessibleSelection()
+ */
+ public void selectAllAccessibleSelection()
+ {
+ if (isMultipleMode())
+ for (int i = 0; i < getItemCount(); i++)
+ select(i);
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent)
+ */
+ public void itemStateChanged(ItemEvent event)
+ {
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ }
+
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>List</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTList();
+ return accessibleContext;
+ }
+
+ /**
+ * Generate a unique name for this <code>List</code>.
+ *
+ * @return A unique name for this <code>List</code>.
+ */
+ String generateName()
+ {
+ return "list" + getUniqueLong();
+ }
+
+ private static synchronized long getUniqueLong()
+ {
+ return next_list_number++;
+ }
+} // class List
diff --git a/libjava/classpath/java/awt/MediaTracker.java b/libjava/classpath/java/awt/MediaTracker.java
new file mode 100644
index 000000000..e69d23e8b
--- /dev/null
+++ b/libjava/classpath/java/awt/MediaTracker.java
@@ -0,0 +1,698 @@
+/* MediaTracker.java -- Class used for keeping track of images
+ Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.image.ImageObserver;
+import java.util.ArrayList;
+
+/**
+ * This class is used for keeping track of the status of various media
+ * objects.
+ *
+ * Media objects are tracked by assigning them an ID. It is possible
+ * to assign the same ID to mutliple objects, effectivly grouping them
+ * together. In this case the status flags ({@link #statusID}) and error flag
+ * (@link #isErrorID} and {@link #getErrorsID}) are ORed together. This
+ * means that you cannot say exactly which media object has which status,
+ * at most you can say that there <em>are</em> certain media objects with
+ * some certain status.
+ *
+ * At the moment only images are supported by this class.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Bryce McKinlay
+ */
+public class MediaTracker implements java.io.Serializable
+{
+ /** Indicates that the media is still loading. */
+ public static final int LOADING = 1 << 0;
+
+ /** Indicates that the loading operation has been aborted. */
+ public static final int ABORTED = 1 << 1;
+
+ /** Indicates that an error has occured during loading of the media. */
+ public static final int ERRORED = 1 << 2;
+
+ /** Indicates that the media has been successfully and completely loaded. */
+ public static final int COMPLETE = 1 << 3;
+
+ /** The component on which the media is eventually been drawn. */
+ Component target;
+
+ /** The head of the linked list of tracked media objects. */
+ MediaEntry head;
+
+ /** Our serialVersionUID for serialization. */
+ static final long serialVersionUID = -483174189758638095L;
+
+ /**
+ * This represents a media object that is tracked by a MediaTracker.
+ * It also implements a simple linked list.
+ */
+ // FIXME: The serialized form documentation says MediaEntry is a
+ // serializable field, but the serialized form of MediaEntry itself
+ // doesn't appear to be documented.
+ class MediaEntry implements ImageObserver
+ {
+ /** The ID of the media object. */
+ int id;
+
+ /** The media object. (only images are supported ATM). */
+ Image image;
+
+ /** The link to the next entry in the list. */
+ MediaEntry next;
+
+ /** The tracking status. */
+ int status;
+
+ /** The width of the image. */
+ int width;
+
+ /** The height of the image. */
+ int height;
+
+ /**
+ * Receives notification from an {@link java.awt.image.ImageProducer}
+ * that more data of the image is available.
+ *
+ * @param img the image that is updated
+ * @param flags flags from the ImageProducer that indicate the status
+ * of the loading process
+ * @param x the X coordinate of the upper left corner of the image
+ * @param y the Y coordinate of the upper left corner of the image
+ * @param width the width of the image
+ * @param height the height of the image
+ *
+ * @return <code>true</code> if more data is needed, <code>false</code>
+ * otherwise
+ *
+ * @see java.awt.image.ImageObserver
+ */
+ public boolean imageUpdate(Image img, int flags, int x, int y,
+ int width, int height)
+ {
+ if ((flags & ABORT) != 0)
+ status = ABORTED;
+ else if ((flags & ERROR) != 0)
+ status = ERRORED;
+ else if ((flags & ALLBITS) != 0)
+ status = COMPLETE;
+ else
+ status = 0;
+
+ synchronized (MediaTracker.this)
+ {
+ MediaTracker.this.notifyAll();
+ }
+
+ // If status is not COMPLETE then we need more updates.
+ return ((status & (COMPLETE | ERRORED | ABORTED)) == 0);
+ }
+ }
+
+ /**
+ * Constructs a new MediaTracker for the component <code>c</code>. The
+ * component should be the component that uses the media (i.e. draws it).
+ *
+ * @param c the Component that wants to use the media
+ */
+ public MediaTracker(Component c)
+ {
+ target = c;
+ }
+
+ /**
+ * Adds an image to the tracker with the specified <code>ID</code>.
+ *
+ * @param image the image to be added
+ * @param id the ID of the tracker list to which the image is added
+ */
+ public void addImage(Image image, int id)
+ {
+ MediaEntry e = new MediaEntry();
+ e.id = id;
+ e.image = image;
+ synchronized(this)
+ {
+ e.next = head;
+ head = e;
+ }
+ }
+
+ /**
+ * Adds an image to the tracker with the specified <code>ID</code>.
+ * The image is expected to be rendered with the specified width and
+ * height.
+ *
+ * @param image the image to be added
+ * @param id the ID of the tracker list to which the image is added
+ * @param width the width of the image
+ * @param height the height of the image
+ */
+ public void addImage(Image image, int id, int width, int height)
+ {
+ MediaEntry e = new MediaEntry();
+ e.id = id;
+ e.image = image;
+ e.width = width;
+ e.height = height;
+ synchronized(this)
+ {
+ e.next = head;
+ head = e;
+ }
+ }
+
+ /**
+ * Checks if all media objects have finished loading, i.e. are
+ * {@link #COMPLETE}, {@link #ABORTED} or {@link #ERRORED}.
+ *
+ * If the media objects are not already loading, a call to this
+ * method does <em>not</em> start loading. This is equivalent to
+ * a call to <code>checkAll(false)</code>.
+ *
+ * @return if all media objects have finished loading either by beeing
+ * complete, have been aborted or errored.
+ */
+ public boolean checkAll()
+ {
+ return checkAll(false);
+ }
+
+ /**
+ * Checks if all media objects have finished loading, i.e. are
+ * {@link #COMPLETE}, {@link #ABORTED} or {@link #ERRORED}.
+ *
+ * If the media objects are not already loading, and <code>load</code>
+ * is <code>true</code> then a call to this
+ * method starts loading the media objects.
+ *
+ * @param load if <code>true</code> this method starts loading objects
+ * that are not already loading
+ *
+ * @return if all media objects have finished loading either by beeing
+ * complete, have been aborted or errored.
+ */
+ public boolean checkAll(boolean load)
+ {
+ MediaEntry e = head;
+ boolean result = true;
+
+ while (e != null)
+ {
+ if ((e.status & (COMPLETE | ERRORED | ABORTED)) == 0)
+ {
+ if (load && ((e.status & LOADING) == 0))
+ {
+ if (target.prepareImage(e.image, e))
+ e.status = COMPLETE;
+ else
+ {
+ e.status = LOADING;
+ int flags = target.checkImage(e.image, e);
+ if ((flags & ImageObserver.ABORT) != 0)
+ e.status = ABORTED;
+ else if ((flags & ImageObserver.ERROR) != 0)
+ e.status = ERRORED;
+ else if ((flags & ImageObserver.ALLBITS) != 0)
+ e.status = COMPLETE;
+ }
+ boolean complete = (e.status
+ & (COMPLETE | ABORTED | ERRORED)) != 0;
+ if (!complete)
+ result = false;
+ }
+ else
+ result = false;
+ }
+ e = e.next;
+ }
+ return result;
+ }
+
+ /**
+ * Checks if any of the registered media objects has encountered an error
+ * during loading.
+ *
+ * @return <code>true</code> if at least one media object has encountered
+ * an error during loading, <code>false</code> otherwise
+ *
+ */
+ public boolean isErrorAny()
+ {
+ MediaEntry e = head;
+ while (e != null)
+ {
+ if ((e.status & ERRORED) != 0)
+ return true;
+ e = e.next;
+ }
+ return false;
+ }
+
+ /**
+ * Returns all media objects that have encountered errors during loading.
+ *
+ * @return an array of all media objects that have encountered errors
+ * or <code>null</code> if there were no errors at all
+ */
+ public Object[] getErrorsAny()
+ {
+ MediaEntry e = head;
+ ArrayList result = null;
+ while (e != null)
+ {
+ if ((e.status & ERRORED) != 0)
+ {
+ if (result == null)
+ result = new ArrayList();
+ result.add(e.image);
+ }
+ e = e.next;
+ }
+ if (result == null)
+ return null;
+ else
+ return result.toArray();
+ }
+
+ /**
+ * Waits for all media objects to finish loading, either by completing
+ * successfully or by aborting or encountering an error.
+ *
+ * @throws InterruptedException if another thread interrupted the
+ * current thread while waiting
+ */
+ public void waitForAll() throws InterruptedException
+ {
+ synchronized (this)
+ {
+ while (checkAll(true) == false)
+ wait();
+ }
+ }
+
+ /**
+ * Waits for all media objects to finish loading, either by completing
+ * successfully or by aborting or encountering an error.
+ *
+ * This method waits at most <code>ms</code> milliseconds. If the
+ * media objects have not completed loading within this timeframe, this
+ * method returns <code>false</code>, otherwise <code>true</code>.
+ *
+ * @param ms timeframe in milliseconds to wait for the media objects to
+ * finish
+ *
+ * @return <code>true</code> if all media objects have successfully loaded
+ * within the timeframe, <code>false</code> otherwise
+ *
+ * @throws InterruptedException if another thread interrupted the
+ * current thread while waiting
+ */
+ public boolean waitForAll(long ms) throws InterruptedException
+ {
+ long start = System.currentTimeMillis();
+ boolean result = checkAll(true);
+ synchronized (this)
+ {
+ while (result == false)
+ {
+ wait(ms);
+ result = checkAll(true);
+ if ((System.currentTimeMillis() - start) > ms)
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns the status flags of all registered media objects ORed together.
+ * If <code>load</code> is <code>true</code> then media objects that
+ * are not already loading will be started to load.
+ *
+ * @param load if set to <code>true</code> then media objects that are
+ * not already loading are started
+ *
+ * @return the status flags of all tracked media objects ORed together
+ */
+ public int statusAll(boolean load)
+ {
+ int result = 0;
+ MediaEntry e = head;
+ while (e != null)
+ {
+ if (load && e.status == 0)
+ {
+ if (target.prepareImage(e.image, e))
+ e.status = COMPLETE;
+ else
+ {
+ e.status = LOADING;
+ int flags = target.checkImage(e.image, e);
+ if ((flags & ImageObserver.ABORT) != 0)
+ e.status = ABORTED;
+ else if ((flags & ImageObserver.ERROR) != 0)
+ e.status = ERRORED;
+ else if ((flags & ImageObserver.ALLBITS) != 0)
+ e.status = COMPLETE;
+ }
+ }
+ result |= e.status;
+ e = e.next;
+ }
+ return result;
+ }
+
+ /**
+ * Checks if the media objects with <code>ID</code> have completed loading.
+ *
+ * @param id the ID of the media objects to check
+ *
+ * @return <code>true</code> if all media objects with <code>ID</code>
+ * have successfully finished
+ */
+ public boolean checkID(int id)
+ {
+ return checkID(id, false);
+ }
+
+ /**
+ * Checks if the media objects with <code>ID</code> have completed loading.
+ * If <code>load</code> is <code>true</code> then media objects that
+ * are not already loading will be started to load.
+ *
+ * @param id the ID of the media objects to check
+ * @param load if set to <code>true</code> then media objects that are
+ * not already loading are started
+ *
+ * @return <code>true</code> if all media objects with <code>ID</code>
+ * have successfully finished
+ */
+ public boolean checkID(int id, boolean load)
+ {
+ MediaEntry e = head;
+ boolean result = true;
+
+ while (e != null)
+ {
+ if (e.id == id && ((e.status & (COMPLETE | ABORTED | ERRORED)) == 0))
+ {
+ if (load && ((e.status & LOADING) == 0))
+ {
+ e.status = LOADING;
+ if (target.prepareImage(e.image, e))
+ e.status = COMPLETE;
+ else
+ {
+ int flags = target.checkImage(e.image, e);
+ if ((flags & ImageObserver.ABORT) != 0)
+ e.status = ABORTED;
+ else if ((flags & ImageObserver.ERROR) != 0)
+ e.status = ERRORED;
+ else if ((flags & ImageObserver.ALLBITS) != 0)
+ e.status = COMPLETE;
+ }
+ boolean complete = (e.status
+ & (COMPLETE | ABORTED | ERRORED)) != 0;
+ if (!complete)
+ result = false;
+ }
+ else
+ result = false;
+ }
+ e = e.next;
+ }
+ return result;
+ }
+
+ /**
+ * Returns <code>true</code> if any of the media objects with <code>ID</code>
+ * have encountered errors during loading, false otherwise.
+ *
+ * @param id the ID of the media objects to check
+ *
+ * @return <code>true</code> if any of the media objects with <code>ID</code>
+ * have encountered errors during loading, false otherwise
+ */
+ public boolean isErrorID(int id)
+ {
+ MediaEntry e = head;
+ while (e != null)
+ {
+ if (e.id == id && ((e.status & ERRORED) != 0))
+ return true;
+ e = e.next;
+ }
+ return false;
+ }
+
+ /**
+ * Returns all media objects with the specified ID that have encountered
+ * an error.
+ *
+ * @param id the ID of the media objects to check
+ *
+ * @return an array of all media objects with the specified ID that
+ * have encountered an error
+ */
+ public Object[] getErrorsID(int id)
+ {
+ MediaEntry e = head;
+ ArrayList result = null;
+ while (e != null)
+ {
+ if (e.id == id && ((e.status & ERRORED) != 0))
+ {
+ if (result == null)
+ result = new ArrayList();
+ result.add(e.image);
+ }
+ e = e.next;
+ }
+ if (result == null)
+ return null;
+ else
+ return result.toArray();
+ }
+
+ /**
+ * Waits for all media objects with the specified ID to finish loading,
+ * either by completing successfully or by aborting or encountering an error.
+ *
+ * @param id the ID of the media objects to wait for
+ *
+ * @throws InterruptedException if another thread interrupted the
+ * current thread while waiting
+ */
+ public void waitForID(int id) throws InterruptedException
+ {
+ MediaEntry e = head;
+ synchronized (this)
+ {
+ while (checkID (id, true) == false)
+ wait();
+ }
+ }
+
+ /**
+ * Waits for all media objects with the specified ID to finish loading,
+ * either by completing successfully or by aborting or encountering an error.
+ *
+ * This method waits at most <code>ms</code> milliseconds. If the
+ * media objects have not completed loading within this timeframe, this
+ * method returns <code>false</code>, otherwise <code>true</code>.
+ *
+ * @param id the ID of the media objects to wait for
+ * @param ms timeframe in milliseconds to wait for the media objects to
+ * finish
+ *
+ * @return <code>true</code> if all media objects have successfully loaded
+ * within the timeframe, <code>false</code> otherwise
+ *
+ * @throws InterruptedException if another thread interrupted the
+ * current thread while waiting
+ */
+ public boolean waitForID(int id, long ms) throws InterruptedException
+ {
+ MediaEntry e = head;
+ long start = System.currentTimeMillis();
+ boolean result = checkID(id, true);
+
+ synchronized (this)
+ {
+ while (result == false)
+ {
+ wait(ms);
+ result = checkID(id, true);
+ if ((System.currentTimeMillis() - start) > ms)
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns the status flags of the media objects with the specified ID
+ * ORed together.
+ *
+ * If <code>load</code> is <code>true</code> then media objects that
+ * are not already loading will be started to load.
+ *
+ * @param load if set to <code>true</code> then media objects that are
+ * not already loading are started
+ *
+ * @return the status flags of all tracked media objects ORed together
+ */
+ public int statusID(int id, boolean load)
+ {
+ int result = 0;
+ MediaEntry e = head;
+ while (e != null)
+ {
+ if (e.id == id)
+ {
+ if (load && e.status == 0)
+ {
+ if (target.prepareImage(e.image, e))
+ e.status = COMPLETE;
+ else
+ {
+ e.status = LOADING;
+ int flags = target.checkImage(e.image, e);
+ if ((flags & ImageObserver.ABORT) != 0)
+ e.status = ABORTED;
+ else if ((flags & ImageObserver.ERROR) != 0)
+ e.status = ERRORED;
+ else if ((flags & ImageObserver.ALLBITS) != 0)
+ e.status = COMPLETE;
+ }
+ }
+ result |= e.status;
+ }
+ e = e.next;
+ }
+ return result;
+ }
+
+ /**
+ * Removes an image from this MediaTracker.
+ *
+ * @param image the image to be removed
+ */
+ public void removeImage(Image image)
+ {
+ synchronized (this)
+ {
+ MediaEntry e = head;
+ MediaEntry prev = null;
+ while (e != null)
+ {
+ if (e.image == image)
+ {
+ if (prev == null)
+ head = e.next;
+ else
+ prev.next = e.next;
+ }
+ else
+ prev = e;
+ e = e.next;
+ }
+ }
+ }
+
+ /**
+ * Removes an image with the specified ID from this MediaTracker.
+ *
+ * @param image the image to be removed
+ */
+ public void removeImage(Image image, int id)
+ {
+ synchronized (this)
+ {
+ MediaEntry e = head;
+ MediaEntry prev = null;
+ while (e != null)
+ {
+ if (e.id == id && e.image == image)
+ {
+ if (prev == null)
+ head = e.next;
+ else
+ prev.next = e.next;
+ }
+ else
+ prev = e;
+ e = e.next;
+ }
+ }
+ }
+
+ /**
+ * Removes an image with the specified ID and scale from this MediaTracker.
+ *
+ * @param image the image to be removed
+ */
+ public void removeImage(Image image, int id, int width, int height)
+ {
+ synchronized (this)
+ {
+ MediaEntry e = head;
+ MediaEntry prev = null;
+ while (e != null)
+ {
+ if (e.id == id && e.image == image
+ && e.width == width && e.height == height)
+ {
+ if (prev == null)
+ head = e.next;
+ else
+ prev.next = e.next;
+ }
+ else
+ prev = e;
+ e = e.next;
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/java/awt/Menu.java b/libjava/classpath/java/awt/Menu.java
new file mode 100644
index 000000000..c640b5e85
--- /dev/null
+++ b/libjava/classpath/java/awt/Menu.java
@@ -0,0 +1,444 @@
+/* Menu.java -- A Java AWT Menu
+ Copyright (C) 1999, 2002, 2004, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.peer.MenuPeer;
+import java.io.Serializable;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+
+/**
+ * This class represents a pull down or tear off menu in Java's AWT.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class Menu extends MenuItem implements MenuContainer, Serializable
+{
+
+ /**
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_menu_number;
+
+ // Serialization Constant
+ private static final long serialVersionUID = -8809584163345499784L;
+
+ /**
+ * @serial The actual items in the menu
+ */
+ private Vector items = new Vector();
+
+ /**
+ * @serial Flag indicating whether or not this menu is a tear off
+ */
+ private boolean tearOff;
+
+ /**
+ * @serial Indicates whether or not this is a help menu.
+ */
+ private boolean isHelpMenu;
+
+ /*
+ * @serial Unused in this implementation, but present in Sun's
+ * serialization spec. Value obtained via reflection.
+ */
+ private int menuSerializedDataVersion = 1;
+
+ static final transient String separatorLabel = "-";
+
+ /**
+ * Initializes a new instance of <code>Menu</code> with no label and that
+ * is not a tearoff;
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public Menu()
+ {
+ }
+
+ /**
+ * Initializes a new instance of <code>Menu</code> that is not a tearoff and
+ * that has the specified label.
+ *
+ * @param label The menu label.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public Menu(String label)
+ {
+ this(label, false);
+ }
+
+ /**
+ * Initializes a new instance of <code>Menu</code> with the specified
+ * label and tearoff status.
+ *
+ * @param label The label for this menu
+ * @param isTearOff <code>true</code> if this menu is a tear off menu,
+ * <code>false</code> otherwise.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public Menu(String label, boolean isTearOff)
+ {
+ super(label);
+
+ tearOff = isTearOff;
+
+ if (label.equals("Help"))
+ isHelpMenu = true;
+
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException();
+ }
+
+ /**
+ * Tests whether or not this menu is a tearoff.
+ *
+ * @return <code>true</code> if this menu is a tearoff, <code>false</code>
+ * otherwise.
+ */
+ public boolean isTearOff()
+ {
+ return(tearOff);
+ }
+
+ /**
+ * Returns the number of items in this menu.
+ *
+ * @return The number of items in this menu.
+ */
+ public int getItemCount()
+ {
+ return countItems();
+ }
+
+ /**
+ * Returns the number of items in this menu.
+ *
+ * @return The number of items in this menu.
+ *
+ * @deprecated As of JDK 1.1, replaced by getItemCount().
+ */
+ public int countItems()
+ {
+ return items.size();
+ }
+
+ /**
+ * Returns the item at the specified index.
+ *
+ * @param index the item index.
+ *
+ * @return The item at the specified index.
+ *
+ * @exception ArrayIndexOutOfBoundsException If the index value is not valid.
+ */
+ public MenuItem getItem(int index)
+ {
+ return((MenuItem) items.elementAt(index));
+ }
+
+ /**
+ * Adds the specified item to this menu. If it was previously part of
+ * another menu, it is first removed from that menu.
+ *
+ * @param item The new item to add.
+ *
+ * @return The item that was added.
+ */
+ public MenuItem add(MenuItem item)
+ {
+ MenuContainer parent = item.getParent();
+ if (parent != null)
+ parent.remove(item);
+
+ items.addElement(item);
+ item.setParent(this);
+
+ if (peer != null)
+ {
+ item.addNotify();
+ MenuPeer mp = (MenuPeer) peer;
+ mp.addItem(item);
+ }
+
+ return item;
+ }
+
+ /**
+ * Add an item with the specified label to this menu.
+ *
+ * @param label The label of the menu item to add.
+ */
+ public void add(String label)
+ {
+ add(new MenuItem(label));
+ }
+
+ /**
+ * Inserts the specified menu item into this menu at the specified index. If
+ * the index is greater than or equal to the number of items already in the
+ * menu, the new item is added as the last item in the menu.
+ *
+ * @param item The menu item to add (<code>null</code> not permitted).
+ * @param index The index of the menu item (>= 0).
+ *
+ * @throws IllegalArgumentException if the index is less than zero.
+ * @throws NullPointerException if <code>item</code> is <code>null</code>.
+ */
+ public void insert(MenuItem item, int index)
+ {
+ if (index < 0)
+ throw new IllegalArgumentException("Index is less than zero");
+
+ int count = getItemCount();
+
+ if (index >= count)
+ add(item);
+ else
+ {
+ MenuContainer parent = item.getParent();
+ if (parent != null)
+ parent.remove(item);
+
+ items.insertElementAt(item, index);
+ item.setParent(this);
+
+ MenuPeer peer = (MenuPeer) getPeer();
+ if (peer == null)
+ return;
+
+ for (int i = count - 1; i >= index; i--)
+ peer.delItem(i);
+
+ item.addNotify();
+ peer.addItem(item);
+
+ // bear in mind that count is the number of items *before* the new
+ // item was added
+ for (int i = index + 1; i <= count; i++)
+ peer.addItem((MenuItem) items.elementAt(i));
+ }
+
+ }
+
+ /**
+ * Inserts an item with the specified label into this menu at the specified
+ * index. If the index is greater than or equal to the number of items
+ * already in the menu, the new item is added as the last item in the menu.
+ *
+ * @param label The label of the item to add.
+ * @param index The index of the menu item (>= 0).
+ *
+ * @throws IllegalArgumentException If the index is less than zero.
+ */
+ public void insert(String label, int index)
+ {
+ insert(new MenuItem(label), index);
+ }
+
+ /**
+ * Adds a separator bar at the current menu location.
+ */
+ public void addSeparator()
+ {
+ add(new MenuItem(separatorLabel));
+ }
+
+ /**
+ * Inserts a separator bar at the specified index value.
+ *
+ * @param index The index at which to insert a separator bar.
+ *
+ * @exception IllegalArgumentException If the index is less than zero.
+ * @exception ArrayIndexOutOfBoundsException If the index is otherwise invalid.
+ */
+ public void insertSeparator(int index)
+ {
+ insert(new MenuItem(separatorLabel), index);
+ }
+
+ /**
+ * Deletes the item at the specified index from this menu.
+ *
+ * @param index The index of the item to remove.
+ *
+ * @exception ArrayIndexOutOfBoundsException If the index is otherwise invalid.
+ */
+ public synchronized void remove(int index)
+ {
+ MenuItem item = (MenuItem) items.remove(index);
+
+ MenuPeer mp = (MenuPeer) getPeer();
+ if (mp != null)
+ {
+ mp.delItem(index);
+ item.removeNotify();
+ }
+ item.setParent(null);
+ }
+
+ /**
+ * Removes the specifed item from the menu. If the specified component
+ * does not exist, this method does nothing.
+ *
+ * @param item The component to remove.
+ */
+ public void remove(MenuComponent item)
+ {
+ int index = items.indexOf(item);
+ if (index == -1)
+ return;
+
+ remove(index);
+ }
+
+ /**
+ * Removes all the elements from this menu.
+ */
+ public synchronized void removeAll()
+ {
+ int count = getItemCount();
+ for(int i = 0; i < count; i++)
+ {
+ // We must always remove item 0.
+ remove(0);
+ }
+ }
+
+ /**
+ * Creates the native peer for this object.
+ */
+ public void addNotify()
+ {
+ MenuPeer peer = (MenuPeer) getPeer();
+ if (peer == null)
+ {
+ peer = getToolkit().createMenu(this);
+ setPeer(peer);
+ }
+
+ Enumeration e = items.elements();
+ while (e.hasMoreElements())
+ {
+ MenuItem mi = (MenuItem)e.nextElement();
+ mi.addNotify();
+ peer.addItem(mi);
+ }
+
+ super.addNotify();
+ }
+
+ /**
+ * Destroys the native peer for this object.
+ */
+ public void removeNotify()
+ {
+ Enumeration e = items.elements();
+ while (e.hasMoreElements())
+ {
+ MenuItem mi = (MenuItem) e.nextElement();
+ mi.removeNotify();
+ }
+ super.removeNotify();
+ }
+
+ /**
+ * Returns a debugging string for this menu.
+ *
+ * @return A debugging string for this menu.
+ */
+ public String paramString()
+ {
+ return (",tearOff=" + tearOff + ",isHelpMenu=" + isHelpMenu
+ + super.paramString());
+ }
+
+ /**
+ * Basic Accessibility class for Menu. Details get provided in derived
+ * classes.
+ */
+ protected class AccessibleAWTMenu extends AccessibleAWTMenuItem
+ {
+ private static final long serialVersionUID = 5228160894980069094L;
+
+ protected AccessibleAWTMenu()
+ {
+ }
+
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.MENU;
+ }
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>Menu</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTMenu();
+ return accessibleContext;
+ }
+
+ /**
+ * Generate a unique name for this <code>Menu</code>.
+ *
+ * @return A unique name for this <code>Menu</code>.
+ */
+ String generateName()
+ {
+ return "menu" + getUniqueLong();
+ }
+
+ private static synchronized long getUniqueLong()
+ {
+ return next_menu_number++;
+ }
+
+} // class Menu
diff --git a/libjava/classpath/java/awt/MenuBar.java b/libjava/classpath/java/awt/MenuBar.java
new file mode 100644
index 000000000..3fc5622ac
--- /dev/null
+++ b/libjava/classpath/java/awt/MenuBar.java
@@ -0,0 +1,390 @@
+/* MenuBar.java -- An AWT menu bar class
+ Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.peer.MenuBarPeer;
+
+import java.io.Serializable;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+
+/**
+ * This class implements a menu bar in the AWT system.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+public class MenuBar extends MenuComponent
+ implements MenuContainer, Serializable, Accessible
+{
+
+ // Serialization Constant
+ private static final long serialVersionUID = -4930327919388951260L;
+
+ /**
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_menubar_number;
+
+ /**
+ * @serial The menu used for providing help information
+ */
+ private Menu helpMenu;
+
+ /**
+ * @serial The menus contained in this menu bar.
+ */
+ private Vector menus = new Vector();
+
+ /**
+ * Initializes a new instance of <code>MenuBar</code>.
+ *
+ * @throws HeadlessException if GraphicsEnvironment.isHeadless() is true
+ */
+ public MenuBar()
+ {
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException();
+ }
+
+ /**
+ * Returns the help menu for this menu bar. This may be <code>null</code>.
+ *
+ * @return the help menu for this menu bar
+ */
+ public Menu getHelpMenu()
+ {
+ return helpMenu;
+ }
+
+ /**
+ * Sets the help menu for this menu bar.
+ *
+ * @param menu the new help menu for this menu bar
+ */
+ public synchronized void setHelpMenu(Menu menu)
+ {
+ MenuBarPeer myPeer = (MenuBarPeer) getPeer ();
+
+ if (helpMenu != null)
+ {
+ if (myPeer != null)
+ helpMenu.removeNotify();
+ helpMenu.setParent(null);
+ }
+ helpMenu = menu;
+
+ MenuContainer parent = menu.getParent();
+ if (parent != null)
+ parent.remove(menu);
+ menu.setParent(this);
+
+ if (myPeer != null)
+ {
+ menu.addNotify();
+ myPeer.addHelpMenu(menu);
+ }
+ }
+
+ /**
+ * Add a menu to this MenuBar. If the menu has already has a
+ * parent, it is first removed from its old parent before being
+ * added.
+ *
+ * @param menu the menu to add
+ *
+ * @return the menu that was added
+ */
+ public synchronized Menu add(Menu menu)
+ {
+ MenuBarPeer myPeer = (MenuBarPeer) getPeer ();
+
+ MenuContainer parent = menu.getParent();
+ if (parent != null)
+ parent.remove(menu);
+
+ menus.addElement(menu);
+ menu.setParent(this);
+
+ if (myPeer != null)
+ {
+ menu.addNotify();
+ myPeer.addMenu(menu);
+ }
+ return menu;
+ }
+
+ /**
+ * Removes the menu at the specified index.
+ *
+ * @param index the index of the menu to remove from the menu bar
+ */
+ public synchronized void remove(int index)
+ {
+ Menu m = (Menu) menus.remove(index);
+ MenuBarPeer mp = (MenuBarPeer) getPeer();
+
+ if (mp != null)
+ m.removeNotify();
+
+ m.setParent(null);
+
+ if (mp != null)
+ mp.delMenu(index);
+ }
+
+ /**
+ * Removes the specified menu from the menu bar.
+ *
+ * @param menu the menu to remove from the menu bar
+ */
+ public void remove(MenuComponent menu)
+ {
+ int index = menus.indexOf(menu);
+ if (index == -1)
+ return;
+
+ remove(index);
+ }
+
+ /**
+ * Returns the number of elements in this menu bar.
+ *
+ * @return the number of elements in the menu bar
+ */
+ public int getMenuCount()
+ {
+ return countMenus();
+ }
+
+ /**
+ * Returns the number of elements in this menu bar.
+ *
+ * @return the number of elements in the menu bar
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getMenuCount()</code>.
+ */
+ public int countMenus()
+ {
+ return menus.size() + (getHelpMenu() == null ? 0 : 1);
+ }
+
+ /**
+ * Returns the menu at the specified index.
+ *
+ * @param index the index of the menu
+ *
+ * @return the requested menu
+ *
+ * @throws ArrayIndexOutOfBoundsException if the index is not valid
+ */
+ public Menu getMenu(int index)
+ {
+ return (Menu) menus.elementAt(index);
+ }
+
+ /**
+ * Creates this object's native peer.
+ */
+ public void addNotify()
+ {
+ MenuBarPeer peer = (MenuBarPeer) getPeer();
+ if (peer == null)
+ {
+ peer = getToolkit().createMenuBar(this);
+ setPeer(peer);
+ }
+
+ Enumeration e = menus.elements();
+ while (e.hasMoreElements())
+ {
+ Menu mi = (Menu)e.nextElement();
+ mi.addNotify();
+ peer.addMenu(mi);
+ }
+
+ if (helpMenu != null)
+ {
+ helpMenu.addNotify();
+ peer.addHelpMenu(helpMenu);
+ }
+ }
+
+ /**
+ * Destroys this object's native peer.
+ */
+ public void removeNotify()
+ {
+ Enumeration e = menus.elements();
+ while (e.hasMoreElements())
+ {
+ Menu mi = (Menu) e.nextElement();
+ mi.removeNotify();
+ }
+ super.removeNotify();
+ }
+
+ /**
+ * Returns a list of all shortcuts for the menus in this menu bar.
+ *
+ * @return a list of all shortcuts for the menus in this menu bar
+ */
+ public synchronized Enumeration<MenuShortcut> shortcuts()
+ {
+ Vector shortcuts = new Vector();
+ Enumeration e = menus.elements();
+
+ while (e.hasMoreElements())
+ {
+ Menu menu = (Menu)e.nextElement();
+ if (menu.getShortcut() != null)
+ shortcuts.addElement(menu.getShortcut());
+ }
+
+ return shortcuts.elements();
+ }
+
+ /**
+ * Returns the menu item for the specified shortcut, or <code>null</code>
+ * if no such item exists.
+ *
+ * @param shortcut the shortcut to return the menu item for
+ *
+ * @return the menu item for the specified shortcut
+ */
+ public MenuItem getShortcutMenuItem(MenuShortcut shortcut)
+ {
+ Enumeration e = menus.elements();
+
+ while (e.hasMoreElements())
+ {
+ Menu menu = (Menu) e.nextElement();
+ MenuShortcut s = menu.getShortcut();
+ if ((s != null) && s.equals(shortcut))
+ return menu;
+ }
+
+ return null;
+ }
+
+ /**
+ * Deletes the specified menu shortcut.
+ *
+ * @param shortcut the shortcut to delete
+ */
+ public void deleteShortcut(MenuShortcut shortcut)
+ {
+ MenuItem it;
+ // This is a slow implementation, but it probably doesn't matter.
+ while ((it = getShortcutMenuItem (shortcut)) != null)
+ it.deleteShortcut();
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>MenuBar</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ // Create the context if this is the first request.
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTMenuBar();
+ return accessibleContext;
+ }
+
+ /**
+ * Generate a unique name for this <code>MenuBar</code>.
+ *
+ * @return A unique name for this <code>MenuBar</code>.
+ */
+ String generateName()
+ {
+ return "menubar" + getUniqueLong();
+ }
+
+ private static synchronized long getUniqueLong()
+ {
+ return next_menubar_number++;
+ }
+
+ /**
+ * This class provides accessibility support for AWT menu bars.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+ protected class AccessibleAWTMenuBar
+ extends AccessibleAWTMenuComponent
+ {
+
+ /**
+ * Compatible with JDK 1.4.2 revision 5
+ */
+ private static final long serialVersionUID = -8577604491830083815L;
+
+ /**
+ * This is the default constructor, which simply calls the default
+ * constructor of the superclass.
+ */
+ protected AccessibleAWTMenuBar()
+ {
+ super();
+ }
+
+ /**
+ * Returns the accessible role relating to the menu bar.
+ *
+ * @return <code>AccessibleRole.MENU_BAR</code>
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.MENU_BAR;
+ }
+
+ }
+
+}
diff --git a/libjava/classpath/java/awt/MenuComponent.java b/libjava/classpath/java/awt/MenuComponent.java
new file mode 100644
index 000000000..fb0f14eb0
--- /dev/null
+++ b/libjava/classpath/java/awt/MenuComponent.java
@@ -0,0 +1,1302 @@
+/* MenuComponent.java -- Superclass of all AWT menu components
+ Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.peer.MenuComponentPeer;
+import java.io.Serializable;
+import java.util.Locale;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleComponent;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleSelection;
+import javax.accessibility.AccessibleStateSet;
+
+/**
+ * This is the superclass of all menu AWT widgets.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+public abstract class MenuComponent implements Serializable
+{
+
+//Serialization Constant
+ private static final long serialVersionUID = -4536902356223894379L;
+
+ /**
+ * The font for this component.
+ *
+ * @see #getFont()
+ * @see #setFont(java.awt.Font)
+ * @serial the component's font.
+ */
+ private Font font;
+
+ /**
+ * The name of the component.
+ *
+ * @see #getName()
+ * @see #setName(String)
+ * @serial the component's name.
+ */
+ private String name;
+
+ /**
+ * The parent of this component.
+ *
+ * @see #getParent()
+ * @see #setParent(java.awt.MenuContainer)
+ * @serial ignored.
+ */
+ transient MenuContainer parent;
+
+ /**
+ * The native peer for this component.
+ *
+ * @see #getPeer()
+ * @see #setPeer(java.awt.peer.MenuComponentPeer)
+ * @serial ignored.
+ */
+ transient MenuComponentPeer peer;
+
+ /**
+ * The synchronization locking object for this component.
+ *
+ * @serial ignored.
+ */
+ private transient Object tree_lock = this;
+
+ /**
+ * The toolkit for this object.
+ *
+ * @see #getToolkit()
+ * @serial ignored.
+ */
+ private static transient Toolkit toolkit = Toolkit.getDefaultToolkit();
+
+ /**
+ * The accessible context for this component.
+ *
+ * @see #getAccessibleContext()
+ * @serial the accessibility information for this component.
+ */
+ AccessibleContext accessibleContext;
+
+ /**
+ * Was the name of the component set? This value defaults
+ * to false and becomes true after a call to <code>setName()</code>.
+ * Please note that this does not guarantee that name will then
+ * be non-null, as this may be the value passed to <code>setName()</code>.
+ *
+ * @see #setName(String)
+ * @serial true if the name value has been explicitly set by calling
+ * <code>setName()</code>.
+ */
+ private boolean nameExplicitlySet;
+
+ /**
+ * Does this component handle new events? Events will be handled
+ * by this component if this is true. Otherwise, they will be forwarded
+ * up the component hierarchy. This implementation does not use this
+ * variable; it is merely provided for serialization compatability.
+ *
+ * @see #dispatchEvent(AWTEvent)
+ * @serial true if events are to be processed locally. Unused.
+ */
+ private boolean newEventsOnly;
+
+ /**
+ * The focus listener chain handler which deals with focus events for
+ * the accessible context of this component.
+ *
+ * @see AccessibleAWTMenuComponent#addFocusListener(java.awt.event.FocusListener)
+ * @serial ignored.
+ * This is package-private to avoid an accessor method.
+ */
+ transient FocusListener focusListener;
+
+ /**
+ * Default constructor for subclasses.
+ *
+ * @throws HeadlessException ff GraphicsEnvironment.isHeadless() is true
+ */
+ public MenuComponent()
+ {
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException();
+ }
+
+/**
+ * Returns the font in use for this component.
+ *
+ * @return the font for this component
+ */
+ public Font getFont()
+ {
+ if (font != null)
+ return font;
+
+ if (parent != null)
+ return parent.getFont();
+
+ return null;
+ }
+
+ /**
+ * Sets the font for this component to the specified font.
+ *
+ * @param font the new font for this component
+ */
+ public void setFont(Font font)
+ {
+ this.font = font;
+ }
+
+ /**
+ * Returns the name of this component.
+ *
+ * @return the name of this component
+ */
+ public String getName()
+ {
+ if (name == null && ! nameExplicitlySet)
+ name = generateName();
+ return name;
+ }
+
+ /**
+ * Subclasses should override this to return unique component names like
+ * "menuitem0".
+ *
+ * @return the generated name for this menu component
+ */
+ String generateName()
+ {
+ // MenuComponent is abstract.
+ return null;
+ }
+
+ /**
+ * Sets the name of this component to the specified name.
+ *
+ * @param name the new name of this component
+ */
+ public void setName(String name)
+ {
+ this.name = name;
+ nameExplicitlySet = true;
+ }
+
+ /**
+ * Returns the parent of this component.
+ *
+ * @return the parent of this component
+ */
+ public MenuContainer getParent()
+ {
+ return parent;
+ }
+
+ /**
+ * Sets the parent of this component.
+ *
+ * @param parent the parent to set
+ */
+ final void setParent(MenuContainer parent)
+ {
+ this.parent = parent;
+ }
+
+ /**
+ * Returns the native windowing system peer for this component.
+ *
+ * @return the peer for this component
+ *
+ * @deprecated
+ */
+ public MenuComponentPeer getPeer()
+ {
+ return peer;
+ }
+
+ /**
+ * Sets the peer for this component.
+ *
+ * @param peer the peer to set
+ */
+ final void setPeer(MenuComponentPeer peer)
+ {
+ this.peer = peer;
+ }
+
+ /**
+ * Destroys this component's native peer
+ */
+ public void removeNotify()
+ {
+ if (peer != null)
+ peer.dispose();
+ peer = null;
+ }
+
+ /**
+ * Returns the toolkit in use for this component.
+ *
+ * @return the toolkit for this component
+ */
+ final Toolkit getToolkit()
+ {
+ return toolkit;
+ }
+
+ /**
+ * Returns the object used for synchronization locks on this component
+ * when performing tree and layout functions.
+ *
+ * @return the synchronization lock for this component
+ */
+ protected final Object getTreeLock()
+ {
+ return tree_lock;
+ }
+
+ /**
+ * Sets the sync lock object for this component.
+ *
+ * @param treeLock the sync lock to set
+ */
+ final void setTreeLock(Object treeLock)
+ {
+ this.tree_lock = treeLock;
+ }
+
+ /**
+ * AWT 1.0 event dispatcher.
+ *
+ * @return true if the event was dispatched, false otherwise
+ *
+ * @deprecated Deprecated in favor of <code>dispatchEvent()</code>.
+ */
+ public boolean
+ postEvent(Event event)
+ {
+ boolean retVal = false;
+ MenuContainer parent = getParent();
+ if (parent != null)
+ retVal = parent.postEvent(event);
+
+ return retVal;
+ }
+
+ /**
+ * Sends this event to this component or a subcomponent for processing.
+ *
+ * @param event The event to dispatch
+ */
+ public final void dispatchEvent(AWTEvent event)
+ {
+ // Convert AWT 1.1 event to AWT 1.0 event.
+ Event oldStyleEvent = Component.translateEvent(event);
+ if (oldStyleEvent != null)
+ {
+ postEvent(oldStyleEvent);
+ }
+
+ // See comment in Component.dispatchEvent().
+ dispatchEventImpl(event);
+ }
+
+ /**
+ * Implementation of dispatchEvent. Allows trusted package classes
+ * to dispatch additional events first. This implementation first
+ * translates <code>event</code> to an AWT 1.0 event and sends the
+ * result to {@link #postEvent}. The event is then
+ * passed on to {@link #processEvent} for local processing.
+ *
+ * @param event the event to dispatch
+ */
+ void dispatchEventImpl(AWTEvent event)
+ {
+ // Do local processing.
+ processEvent(event);
+ }
+
+ /**
+ * Processes the specified event. In this class, this method simply
+ * calls one of the more specific event handlers.
+ *
+ * @param event the event to process
+ */
+ protected void processEvent(AWTEvent event)
+ {
+ // Pass a focus event to the focus listener for
+ // the accessibility context.
+ if (event instanceof FocusEvent)
+ {
+ if (focusListener != null)
+ {
+ switch (event.id)
+ {
+ case FocusEvent.FOCUS_GAINED:
+ focusListener.focusGained((FocusEvent) event);
+ break;
+ case FocusEvent.FOCUS_LOST:
+ focusListener.focusLost((FocusEvent) event);
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns a string representation of this component.
+ *
+ * @return a string representation of this component
+ */
+ public String toString()
+ {
+ return getClass().getName() + "[" + paramString() + "]";
+ }
+
+ /**
+ * Returns a debugging string for this component
+ */
+ protected String paramString()
+ {
+ return "name=" + getName();
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>MenuComponent</code>.
+ * As an abstract class, we return null. Concrete subclasses should return
+ * their implementation of the accessibility context.
+ *
+ * @return null
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ return null;
+ }
+
+ /**
+ * This class provides a base for the accessibility support of menu
+ * components.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+ protected abstract class AccessibleAWTMenuComponent
+ extends AccessibleContext
+ implements Serializable, AccessibleComponent, AccessibleSelection
+ {
+
+ /**
+ * Compatible with JDK 1.4.2 revision 5
+ */
+ private static final long serialVersionUID = -4269533416223798698L;
+
+ /**
+ * This is the default constructor. It should be called by
+ * concrete subclasses to ensure necessary groundwork is completed.
+ */
+ protected AccessibleAWTMenuComponent()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Replaces or supplements the component's selection with the
+ * <code>Accessible</code> child at the supplied index. If
+ * the component supports multiple selection, the child is
+ * added to the current selection. Otherwise, the current
+ * selection becomes the specified child. If the child is
+ * already selected, nothing happens.
+ * <br />
+ * <br />
+ * As the existence of children can not be determined from
+ * this abstract class, the implementation of this method
+ * is left to subclasses.
+ *
+ * @param index the index of the specified child within a
+ * zero-based list of the component's children
+ */
+ public void addAccessibleSelection(int index)
+ {
+ // Subclasses with children should implement this.
+ }
+
+ /**
+ * Registers the specified focus listener to receive
+ * focus events from this component.
+ *
+ * @param listener the new focus listener
+ */
+ public void addFocusListener(FocusListener listener)
+ {
+ // Chain the new focus listener to the existing chain
+ // of focus listeners. Each new focus listener is
+ // coupled via multicasting to the existing chain.
+ focusListener = AWTEventMulticaster.add(focusListener, listener);
+ }
+
+ /**
+ * Clears the component's current selection. Following
+ * the calling of this method, no children of the component
+ * will be selected.
+ * <br />
+ * <br />
+ * As the existence of children can not be determined from
+ * this abstract class, the implementation of this method
+ * is left to subclasses.
+ */
+ public void clearAccessibleSelection()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns true if the specified point lies within the
+ * component. The supplied co-ordinates are assumed to
+ * be relative to the co-ordinate system of the component
+ * itself. Thus, the point (0,0) is the upper left corner
+ * of this component.
+ * <br />
+ * <br />
+ * Please note that this method depends on a correctly implemented
+ * version of the <code>getBounds()</code> method. Subclasses
+ * must provide the bounding rectangle via <code>getBounds()</code>
+ * in order for this method to work.
+ *
+ * @param point the point to check against this component
+ * @return true if the point is within this component
+ * @see #getBounds()
+ */
+ public boolean contains(Point point)
+ {
+ // We can simply return the result of a
+ // test for containment in the bounding rectangle.
+ return getBounds().contains(point);
+ }
+
+ /**
+ * Returns the <code>Accessible</code> child of this component present
+ * at the specified point. The supplied co-ordinates are
+ * assumed to be relative to the co-ordinate system of this
+ * component (the parent of any returned accessible). Thus,
+ * the point (0,0) is the upper left corner of this menu
+ * component.
+ * <br />
+ * <br />
+ * As the existence of children can not be determined from
+ * this abstract class, the implementation of this method
+ * is left to subclasses.
+ *
+ * @param point the point at which the returned accessible
+ * is located
+ * @return null
+ */
+ public Accessible getAccessibleAt(Point point)
+ {
+ return null;
+ }
+
+ /**
+ * Returns the <code>Accessible</code> child at the supplied
+ * index within the list of children of this component.
+ * <br />
+ * <br />
+ * As the existence of children can not be determined from
+ * this abstract class, the implementation of this method
+ * is left to subclasses.
+ *
+ * @param index the index of the <code>Accessible</code> child
+ * to retrieve
+ *
+ * @return null
+ */
+ public Accessible getAccessibleChild(int index)
+ {
+ return null;
+ }
+
+ /**
+ * Returns the number of children of this component which
+ * implement the <code>Accessible</code> interface. If
+ * all children of this component are accessible, then
+ * the returned value will be the same as the number of
+ * children.
+ * <br />
+ * <br />
+ *
+ * @return 0
+ */
+ public int getAccessibleChildrenCount()
+ {
+ return 0;
+ }
+
+ /**
+ * Retrieves the <code>AccessibleComponent</code> associated
+ * with this accessible context and its component. As the
+ * context itself implements <code>AccessibleComponent</code>,
+ * this is the return value.
+ *
+ * @return the context itself
+ */
+ public AccessibleComponent getAccessibleComponent()
+ {
+ return this;
+ }
+
+ /**
+ * Returns the accessible name for this menu component. This
+ * is the name given to the component, which may be null if
+ * not set using <code>setName()</code>.
+ * <br />
+ * <br />
+ * The name is not the most appropriate description of this
+ * object. Subclasses should preferably provide a more
+ * accurate description. For example, a File menu could
+ * have the description `Lists commands related to the
+ * file system'.
+ *
+ * @return a description of the component. Currently,
+ * this is just the contents of the name property
+ *
+ * @see MenuComponent#setName(String)
+ */
+ public String getAccessibleDescription()
+ {
+ return MenuComponent.this.getName();
+ }
+
+ /**
+ * Retrieves the index of this component within its parent.
+ * If no parent exists, -1 is returned.
+ *
+ * @return -1 as the parent, a <code>MenuContainer</code>
+ * is not <code>Accessible</code>
+ */
+ public int getAccessibleIndexInParent()
+ {
+ return -1;
+ }
+
+ /**
+ * Returns the accessible name of this component. This
+ * is the name given to the component, which may be null if
+ * not set using <code>setName()</code>.
+ * <br />
+ * <br />
+ * The name property is not the most suitable string to return
+ * for this method. The string should be localized, and
+ * relevant to the operation of the component. For example,
+ * it could be the text of a menu item. However, this can
+ * not be used at this level of abstraction, so it is the
+ * responsibility of subclasses to provide a more appropriate
+ * name.
+ *
+ * @return a localized name for this component. Currently, this
+ * is just the contents of the name property
+ *
+ * @see MenuComponent#setName(String)
+ */
+ public String getAccessibleName()
+ {
+ return MenuComponent.this.getName();
+ }
+
+ /**
+ * Returns the <code>Accessible</code> parent of this component.
+ * As the parent of a <code>MenuComponent</code> is a
+ * <code>MenuContainer</code>, which doesn't implement
+ * <code>Accessible</code>, this method returns null.
+ *
+ * @return null
+ */
+ public Accessible getAccessibleParent()
+ {
+ return null;
+ }
+
+ /**
+ * Returns the accessible role of this component.
+ * <br />
+ * <br />
+ * The abstract implementation of this method returns
+ * <code>AccessibleRole.AWT_COMPONENT</code>,
+ * as the abstract component has no specific role. This
+ * method should be overridden by concrete subclasses, so
+ * as to return an appropriate role for the component.
+ *
+ * @return <code>AccessibleRole.AWT_COMPONENT</code>
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.AWT_COMPONENT;
+ }
+
+ /**
+ * Retrieves the <code>AccessibleSelection</code> associated
+ * with this accessible context and its component. As the
+ * context itself implements <code>AccessibleSelection</code>,
+ * this is the return value.
+ *
+ * @return the context itself
+ */
+ public AccessibleSelection getAccessibleSelection()
+ {
+ return this;
+ }
+
+ /**
+ * Retrieves the <code>Accessible</code> selected child
+ * at the specified index. If there are no selected children
+ * or the index is outside the range of selected children,
+ * null is returned. Please note that the index refers
+ * to the index of the child in the list of <strong>selected
+ * children</strong>, and not the index of the child in
+ * the list of all <code>Accessible</code> children.
+ * <br />
+ * <br />
+ * As the existence of children can not be determined from
+ * this abstract class, the implementation of this method
+ * is left to subclasses.
+ *
+ * @param index the index of the selected <code>Accessible</code>
+ * child
+ */
+ public Accessible getAccessibleSelection(int index)
+ {
+ return null;
+ }
+
+ /**
+ * Returns a count of the number of <code>Accessible</code>
+ * children of this component which are currently selected.
+ * If there are no children currently selected, 0 is returned.
+ * <br />
+ * <br />
+ * As the existence of children can not be determined from
+ * this abstract class, the implementation of this method
+ * is left to subclasses.
+ *
+ * @return 0
+ */
+ public int getAccessibleSelectionCount()
+ {
+ return 0;
+ }
+
+ /**
+ * Retrieves the current state of this component
+ * in an accessible form. For example, a given component
+ * may be visible, selected, disabled, etc.
+ * <br />
+ * <br />
+ * As this class tells us virtually nothing about the component,
+ * except for its name and font, no state information can be
+ * provided. This implementation thus returns an empty
+ * state set, and it is left to concrete subclasses to provide
+ * a more acceptable and relevant state set. Changes to these
+ * properties also need to be handled using
+ * <code>PropertyChangeListener</code>s.
+ *
+ * @return an empty <code>AccessibleStateSet</code>
+ */
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ return new AccessibleStateSet();
+ }
+
+ /**
+ * Returns the background color of the component, or null
+ * if this property is unsupported.
+ * <br />
+ * <br />
+ * This abstract class knows nothing about how the component
+ * is drawn on screen, so this method simply returns the
+ * default system background color used for rendering menus.
+ * Concrete subclasses which handle the drawing of an onscreen
+ * menu component should override this method and provide
+ * the appropriate information.
+ *
+ * @return the default system background color for menus
+ *
+ * @see #setBackground(java.awt.Color)
+ */
+ public Color getBackground()
+ {
+ return SystemColor.menu;
+ }
+
+ /**
+ * Returns a <code>Rectangle</code> which represents the
+ * bounds of this component. The returned rectangle has the
+ * height and width of the component's bounds, and is positioned
+ * at a location relative to this component's parent, the
+ * <code>MenuContainer</code>. null is returned if bounds
+ * are not supported by the component.
+ * <br />
+ * <br />
+ * This abstract class knows nothing about how the component
+ * is drawn on screen, so this method simply returns null.
+ * Concrete subclasses which handle the drawing of an onscreen
+ * menu component should override this method and provide
+ * the appropriate information.
+ *
+ * @return null
+ *
+ * @see #setBounds(java.awt.Rectangle)
+ */
+ public Rectangle getBounds()
+ {
+ return null;
+ }
+
+ /**
+ * Returns the <code>Cursor</code> displayed when the pointer
+ * is positioned over this component. Alternatively, null
+ * is returned if the component doesn't support the cursor
+ * property.
+ * <br />
+ * <br />
+ * This abstract class knows nothing about how the component
+ * is drawn on screen, so this method simply returns the default
+ * system cursor. Concrete subclasses which handle the drawing
+ * of an onscreen menu component may override this method and provide
+ * the appropriate information.
+ *
+ * @return the default system cursor
+ *
+ * @see #setCursor(java.awt.Cursor)
+ */
+ public Cursor getCursor()
+ {
+ return Cursor.getDefaultCursor();
+ }
+
+ /**
+ * Returns the <code>Font</code> used for text created by this component.
+ *
+ * @return the current font
+ *
+ * @see #setFont(java.awt.Font)
+ */
+ public Font getFont()
+ {
+ return MenuComponent.this.getFont();
+ }
+
+ /**
+ * Retrieves information on the rendering and metrics of the supplied
+ * font. If font metrics are not supported by this component, null
+ * is returned.
+ * <br />
+ * <br />
+ * The abstract implementation of this method simply uses the toolkit
+ * to obtain the <code>FontMetrics</code>. Concrete subclasses may
+ * find it more efficient to invoke their peer class directly, if one
+ * is available.
+ *
+ * @param font the font about which to retrieve rendering and metric
+ * information
+ *
+ * @return the metrics of the given font, as provided by the system
+ * toolkit
+ *
+ * @throws NullPointerException if the supplied font was null
+ */
+ public FontMetrics getFontMetrics(Font font)
+ {
+ return MenuComponent.this.getToolkit().getFontMetrics(font);
+ }
+
+ /**
+ * Returns the foreground color of the component, or null
+ * if this property is unsupported.
+ * <br />
+ * <br />
+ * This abstract class knows nothing about how the component
+ * is drawn on screen, so this method simply returns the
+ * default system text color used for rendering menus.
+ * Concrete subclasses which handle the drawing of an onscreen
+ * menu component should override this method and provide
+ * the appropriate information.
+ *
+ * @return the default system text color for menus
+ *
+ * @see #setForeground(java.awt.Color)
+ */
+ public Color getForeground()
+ {
+ return SystemColor.menuText;
+ }
+
+ /**
+ * Returns the locale currently in use by this component.
+ * <br />
+ * <br />
+ * This abstract class has no property relating to the
+ * locale used by the component, so this method simply
+ * returns the default locale for the current instance
+ * of the Java Virtual Machine (JVM). Concrete subclasses
+ * which maintain such a property should override this method
+ * and provide the locale information more accurately.
+ *
+ * @return the default locale for this JVM instance
+ */
+ public Locale getLocale()
+ {
+ return Locale.getDefault();
+ }
+
+ /**
+ * Returns the location of the component, with co-ordinates
+ * relative to the parent component and using the co-ordinate
+ * space of the screen. Thus, the point (0,0) is the upper
+ * left corner of the parent component.
+ * <br />
+ * <br />
+ * Please note that this method depends on a correctly implemented
+ * version of the <code>getBounds()</code> method. Subclasses
+ * must provide the bounding rectangle via <code>getBounds()</code>
+ * in order for this method to work.
+ *
+ * @return the location of the component, relative to its parent
+ *
+ * @see #setLocation(java.awt.Point)
+ */
+ public Point getLocation()
+ {
+ // Simply return the location of the bounding rectangle.
+ return getBounds().getLocation();
+ }
+
+ /**
+ * Returns the location of the component, with co-ordinates
+ * relative to the screen. Thus, the point (0,0) is the upper
+ * left corner of the screen. null is returned if the component
+ * is either not on screen or if this property is unsupported.
+ * <br />
+ * <br />
+ * This abstract class knows nothing about how the component
+ * is drawn on screen, so this method simply returns null.
+ * Concrete subclasses which handle the drawing of an onscreen
+ * menu component should override this method and provide
+ * the appropriate information.
+ *
+ * @return the location of the component, relative to the screen
+ */
+ public Point getLocationOnScreen()
+ {
+ return null;
+ }
+
+ /**
+ * Returns the size of the component.
+ * <br />
+ * <br />
+ * Please note that this method depends on a correctly implemented
+ * version of the <code>getBounds()</code> method. Subclasses
+ * must provide the bounding rectangle via <code>getBounds()</code>
+ * in order for this method to work.
+ *
+ * @return the size of the component
+ *
+ * @see #setSize(java.awt.Dimension)
+ */
+ public Dimension getSize()
+ {
+ // Simply return the size of the bounding rectangle.
+ return getBounds().getSize();
+ }
+
+ /**
+ * Returns true if the accessible child specified by the supplied index
+ * is currently selected.
+ * <br />
+ * <br />
+ * As the existence of children can not be determined from
+ * this abstract class, the implementation of this method
+ * is left to subclasses.
+ *
+ * @param index the index of the accessible child to check for selection
+ *
+ * @return false
+ */
+ public boolean isAccessibleChildSelected(int index)
+ {
+ return false;
+ }
+
+ /**
+ * Returns true if this component is currently enabled.
+ * <br />
+ * <br />
+ * As this abstract component has no properties related to
+ * its enabled or disabled state, the implementation of this
+ * method is left to subclasses.
+ *
+ * @return false
+ *
+ * @see #setEnabled(boolean)
+ */
+ public boolean isEnabled()
+ {
+ return false;
+ }
+
+ /**
+ * Returns true if this component is included in the traversal
+ * of the current focus from one component to the other.
+ * <br />
+ * <br />
+ * As this abstract component has no properties related to
+ * its ability to accept the focus, the implementation of this
+ * method is left to subclasses.
+ *
+ * @return false
+ */
+ public boolean isFocusTraversable()
+ {
+ return false;
+ }
+
+ /**
+ * Returns true if the component is being shown on screen.
+ * A component is determined to be shown if it is visible,
+ * and each parent component is also visible. Please note
+ * that, even when a component is showing, it may still be
+ * obscured by other components in front. This method only
+ * determines if the component is being drawn on the screen.
+ * <br />
+ * <br />
+ * As this abstract component and its parent have no properties
+ * relating to visibility, the implementation of this method is
+ * left to subclasses.
+ *
+ * @return false
+ *
+ * @see #isVisible()
+ */
+ public boolean isShowing()
+ {
+ return false;
+ }
+
+ /**
+ * Returns true if the component is visible. A component may
+ * be visible but not drawn on the screen if one of its parent
+ * components is not visible. To determine if the component is
+ * actually drawn on screen, <code>isShowing()</code> should be
+ * used.
+ * <br />
+ * <br />
+ * As this abstract component has no properties relating to its
+ * visibility, the implementation of this method is left to subclasses.
+ *
+ * @return false
+ *
+ * @see #isShowing()
+ * @see #setVisible(boolean)
+ */
+ public boolean isVisible()
+ {
+ return false;
+ }
+
+ /**
+ * Removes the accessible child specified by the supplied index from
+ * the list of currently selected children. If the child specified
+ * is not selected, nothing happens.
+ * <br />
+ * <br />
+ * As the existence of children can not be determined from
+ * this abstract class, the implementation of this method
+ * is left to subclasses.
+ *
+ * @param index the index of the <code>Accessible</code> child
+ */
+ public void removeAccessibleSelection(int index)
+ {
+ // Subclasses with children should implement this.
+ }
+
+ /**
+ * Removes the specified focus listener from the list of registered
+ * focus listeners for this component.
+ *
+ * @param listener the listener to remove
+ */
+ public void removeFocusListener(FocusListener listener)
+ {
+ // Remove the focus listener from the chain.
+ focusListener = AWTEventMulticaster.remove(focusListener, listener);
+ }
+
+ /**
+ * Requests that this component gains focus. This depends on the
+ * component being focus traversable.
+ * <br />
+ * <br />
+ * As this abstract component has no properties relating to its
+ * focus traversability, or access to a peer with request focusing
+ * abilities, the implementation of this method is left to subclasses.
+ */
+ public void requestFocus()
+ {
+ // Ignored.
+ }
+
+ /**
+ * Selects all <code>Accessible</code> children of this component which
+ * it is possible to select. The component needs to support multiple
+ * selections.
+ * <br />
+ * <br />
+ * This abstract component provides a simplistic implementation of this
+ * method, which ignores the ability of the component to support multiple
+ * selections and simply uses <code>addAccessibleSelection</code> to
+ * add each <code>Accessible</code> child to the selection. The last
+ * <code>Accessible</code> component is thus selected for components
+ * which don't support multiple selections. Concrete implementations should
+ * override this with a more appopriate and efficient implementation, which
+ * properly takes into account the ability of the component to support multiple
+ * selections.
+ */
+ public void selectAllAccessibleSelection()
+ {
+ // Simply call addAccessibleSelection() on all accessible children.
+ for (int a = 0; a < getAccessibleChildrenCount(); ++a)
+ {
+ addAccessibleSelection(a);
+ }
+ }
+
+ /**
+ * Sets the background color of the component to that specified.
+ * Unspecified behaviour occurs when null is given as the new
+ * background color.
+ * <br />
+ * <br />
+ * This abstract class knows nothing about how the component
+ * is drawn on screen, so this method simply ignores the supplied
+ * color and continues to use the default system color.
+ * Concrete subclasses which handle the drawing of an onscreen
+ * menu component should override this method and provide
+ * the appropriate information.
+ *
+ * @param color the new color to use for the background
+ *
+ * @see #getBackground()
+ */
+ public void setBackground(Color color)
+ {
+ // Ignored.
+ }
+
+ /**
+ * Sets the height and width of the component, and its position
+ * relative to this component's parent, to the values specified
+ * by the supplied rectangle. Unspecified behaviour occurs when
+ * null is given as the new bounds.
+ * <br />
+ * <br />
+ * This abstract class knows nothing about how the component
+ * is drawn on screen, so this method simply ignores the new
+ * rectangle and continues to return null from <code>getBounds()</code>.
+ * Concrete subclasses which handle the drawing of an onscreen
+ * menu component should override this method and provide
+ * the appropriate information.
+ *
+ * @param rectangle a rectangle which specifies the new bounds of
+ * the component
+ *
+ * @see #getBounds()
+ */
+ public void setBounds(Rectangle rectangle)
+ {
+ // Ignored.
+ }
+
+ /**
+ * Sets the <code>Cursor</code> used when the pointer is positioned over the
+ * component. Unspecified behaviour occurs when null is given as the new
+ * cursor.
+ * <br />
+ * <br />
+ * This abstract class knows nothing about how the component
+ * is drawn on screen, so this method simply ignores the new cursor
+ * and continues to return the default system cursor. Concrete
+ * subclasses which handle the drawing of an onscreen menu component
+ * may override this method and provide the appropriate information.
+ *
+ * @param cursor the new cursor to use
+ *
+ * @see #getCursor()
+ */
+ public void setCursor(Cursor cursor)
+ {
+ // Ignored.
+ }
+
+ /**
+ * Sets the enabled/disabled state of this component.
+ * <br />
+ * <br />
+ * As this abstract component has no properties related to
+ * its enabled or disabled state, the implementation of this
+ * method is left to subclasses.
+ *
+ * @param enabled true if the component should be enabled,
+ * false otherwise
+ *
+ * @see #isEnabled()
+ */
+ public void setEnabled(boolean enabled)
+ {
+ // Ignored.
+ }
+
+ /**
+ * Sets the <code>Font</code> used for text created by this component.
+ * Unspecified behaviour occurs when null is given as the new
+ * font.
+ *
+ * @param font the new font to use for text.
+ * @see #getFont()
+ */
+ public void setFont(Font font)
+ {
+ // Call the method of the enclosing component.
+ MenuComponent.this.setFont(font);
+ }
+
+ /**
+ * Sets the foreground color of the component to that specified.
+ * Unspecified behaviour occurs when null is given as the new
+ * background color.
+ * <br />
+ * <br />
+ * This abstract class knows nothing about how the component
+ * is drawn on screen, so this method simply ignores the supplied
+ * color and continues to return the default system text color used
+ * for rendering menus.
+ * Concrete subclasses which handle the drawing of an onscreen
+ * menu component should override this method and provide
+ * the appropriate information.
+ *
+ * @param color the new foreground color
+ *
+ * @see #getForeground()
+ */
+ public void setForeground(Color color)
+ {
+ // Ignored.
+ }
+
+ /**
+ * Sets the location of the component, with co-ordinates
+ * relative to the parent component and using the co-ordinate
+ * space of the screen. Thus, the point (0,0) is the upper
+ * left corner of the parent component.
+ * <br />
+ * <br />
+ * Please note that this method depends on a correctly implemented
+ * version of the <code>getBounds()</code> method. Subclasses
+ * must provide the bounding rectangle via <code>getBounds()</code>
+ * in order for this method to work.
+ *
+ * @param point the location of the component, relative to its parent
+ *
+ * @see #getLocation()
+ */
+ public void setLocation(Point point)
+ {
+ getBounds().setLocation(point);
+ }
+
+ /**
+ * Sets the size of the component.
+ * <br />
+ * <br />
+ * Please note that this method depends on a correctly implemented
+ * version of the <code>getBounds()</code> method. Subclasses
+ * must provide the bounding rectangle via <code>getBounds()</code>
+ * in order for this method to work.
+ *
+ * @param size the new size of the component
+ *
+ * @see #getSize()
+ */
+ public void setSize(Dimension size)
+ {
+ getBounds().setSize(size);
+ }
+
+ /**
+ * Sets the visibility state of the component. A component may
+ * be visible but not drawn on the screen if one of its parent
+ * components is not visible. To determine if the component is
+ * actually drawn on screen, <code>isShowing()</code> should be
+ * used.
+ * <br />
+ * <br />
+ * As this abstract component has no properties relating to its
+ * visibility, the implementation of this method is left to subclasses.
+ *
+ * @param visibility the new visibility of the component -- true if
+ * the component is visible, false if not
+ *
+ * @see #isShowing()
+ * @see #isVisible()
+ */
+ public void setVisible(boolean visibility)
+ {
+ // Ignored.
+ }
+
+ }
+
+}
diff --git a/libjava/classpath/java/awt/MenuContainer.java b/libjava/classpath/java/awt/MenuContainer.java
new file mode 100644
index 000000000..c76ec96c2
--- /dev/null
+++ b/libjava/classpath/java/awt/MenuContainer.java
@@ -0,0 +1,71 @@
+/* MenuContainer.java -- container for menu items
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This interface is a container for menu components.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public interface MenuContainer
+{
+ /**
+ * Returns the font in use by this container.
+ *
+ * @return the menu font
+ */
+ Font getFont();
+
+ /**
+ * Removes the specified menu component from the menu.
+ *
+ * @param component the menu component to remove
+ */
+ void remove(MenuComponent component);
+
+ /**
+ * Posts an event to the listeners.
+ *
+ * @param event the event to dispatch
+ * @deprecated use {@link MenuComponent#dispatchEvent(AWTEvent)} instead
+ */
+ boolean postEvent(Event event);
+} // interface MenuContainer
diff --git a/libjava/classpath/java/awt/MenuItem.java b/libjava/classpath/java/awt/MenuItem.java
new file mode 100644
index 000000000..52d0b4ddf
--- /dev/null
+++ b/libjava/classpath/java/awt/MenuItem.java
@@ -0,0 +1,623 @@
+/* MenuItem.java -- An item in a menu
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.peer.MenuItemPeer;
+import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.util.EventListener;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleAction;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleValue;
+
+/**
+ * This class represents an item in a menu.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class MenuItem extends MenuComponent
+ implements Serializable, Accessible
+{
+
+/*
+ * Static Variables
+ */
+
+
+ /**
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_menuitem_number;
+
+ // Serialization Constant
+ private static final long serialVersionUID = - 21757335363267194L;
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * @serial The name of the action command generated by this item.
+ * This is package-private to avoid an accessor method.
+ */
+String actionCommand;
+
+/**
+ * @serial Indicates whether or not this menu item is enabled.
+ * This is package-private to avoid an accessor method.
+ */
+boolean enabled = true;
+
+/**
+ * @serial The mask of events that are enabled for this menu item.
+ */
+long eventMask;
+
+/**
+ * @serial This menu item's label
+ * This is package-private to avoid an accessor method.
+ */
+String label = "";
+
+/**
+ * @serial The shortcut for this menu item, if any
+ */
+private MenuShortcut shortcut;
+
+// The list of action listeners for this menu item.
+private transient ActionListener action_listeners;
+
+ protected class AccessibleAWTMenuItem
+ extends MenuComponent.AccessibleAWTMenuComponent
+ implements AccessibleAction, AccessibleValue
+ {
+ private static final long serialVersionUID = -217847831945965825L;
+
+ /** Constructor */
+ protected AccessibleAWTMenuItem()
+ {
+ super();
+ }
+
+
+
+ public String getAccessibleName()
+ {
+ return label;
+ }
+
+ public AccessibleAction getAccessibleAction()
+ {
+ return this;
+ }
+
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.MENU_ITEM;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleAction#getAccessibleActionCount()
+ */
+ public int getAccessibleActionCount()
+ {
+ return 1;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleAction#getAccessibleActionDescription(int)
+ */
+ public String getAccessibleActionDescription(int i)
+ {
+ if (i == 0)
+ return label;
+ else
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleAction#doAccessibleAction(int)
+ */
+ public boolean doAccessibleAction(int i)
+ {
+ if (i != 0)
+ return false;
+ processActionEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, actionCommand));
+ return true;
+ }
+
+ public AccessibleValue getAccessibleValue()
+ {
+ return this;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleValue#getCurrentAccessibleValue()
+ */
+ public Number getCurrentAccessibleValue()
+ {
+ return (enabled) ? new Integer(1) : new Integer(0);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleValue#setCurrentAccessibleValue(java.lang.Number)
+ */
+ public boolean setCurrentAccessibleValue(Number number)
+ {
+ boolean result = (number.intValue() != 0);
+ // this. is required by javac 1.3, otherwise it is confused with
+ // MenuItem.this.setEnabled.
+ this.setEnabled(result);
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleValue#getMinimumAccessibleValue()
+ */
+ public Number getMinimumAccessibleValue()
+ {
+ return new Integer(0);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleValue#getMaximumAccessibleValue()
+ */
+ public Number getMaximumAccessibleValue()
+ {
+ return new Integer(0);
+ }
+
+ }
+
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * Initializes a new instance of <code>MenuItem</code> with no label
+ * and no shortcut.
+ */
+public
+MenuItem()
+{
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>MenuItem</code> with the specified
+ * label and no shortcut.
+ *
+ * @param label The label for this menu item.
+ */
+public
+MenuItem(String label)
+{
+ this.label = label;
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>MenuItem</code> with the specified
+ * label and shortcut.
+ *
+ * @param label The label for this menu item.
+ * @param shortcut The shortcut for this menu item.
+ */
+public
+MenuItem(String label, MenuShortcut shortcut)
+{
+ this.label = label;
+ this.shortcut = shortcut;
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Methods
+ */
+
+/**
+ * Returns the label for this menu item, which may be <code>null</code>.
+ *
+ * @return The label for this menu item.
+ */
+public String
+getLabel()
+{
+ return(label);
+}
+
+/*************************************************************************/
+
+/**
+ * This method sets the label for this menu to the specified value.
+ *
+ * @param label The new label for this menu item.
+ */
+public synchronized void
+setLabel(String label)
+{
+ this.label = label;
+ if (peer != null)
+ {
+ MenuItemPeer mp = (MenuItemPeer) peer;
+ mp.setLabel (label);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Tests whether or not this menu item is enabled.
+ *
+ * @return <code>true</code> if this menu item is enabled, <code>false</code>
+ * otherwise.
+ */
+public boolean
+isEnabled()
+{
+ return(enabled);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the enabled status of this menu item.
+ *
+ * @param enabled <code>true</code> to enable this menu item,
+ * <code>false</code> otherwise.
+ */
+public synchronized void
+setEnabled(boolean enabled)
+{
+ enable (enabled);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the enabled status of this menu item.
+ *
+ * @param enabled <code>true</code> to enable this menu item,
+ * <code>false</code> otherwise.
+ *
+ * @deprecated This method is deprecated in favor of <code>setEnabled()</code>.
+ */
+public void
+enable(boolean enabled)
+{
+ if (enabled)
+ enable ();
+ else
+ disable ();
+}
+
+/*************************************************************************/
+
+/**
+ * Enables this menu item.
+ *
+ * @deprecated This method is deprecated in favor of <code>setEnabled()</code>.
+ */
+public void
+enable()
+{
+ if (enabled)
+ return;
+
+ this.enabled = true;
+ if (peer != null)
+ ((MenuItemPeer) peer).setEnabled (true);
+}
+
+/*************************************************************************/
+
+/**
+ * Disables this menu item.
+ *
+ * @deprecated This method is deprecated in favor of <code>setEnabled()</code>.
+ */
+public void
+disable()
+{
+ if (!enabled)
+ return;
+
+ this.enabled = false;
+ if (peer != null)
+ ((MenuItemPeer) peer).setEnabled (false);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the shortcut for this menu item, which may be <code>null</code>.
+ *
+ * @return The shortcut for this menu item.
+ */
+public MenuShortcut
+getShortcut()
+{
+ return(shortcut);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the shortcut for this menu item to the specified value. This
+ * must be done before the native peer is created.
+ *
+ * @param shortcut The new shortcut for this menu item.
+ */
+public void
+setShortcut(MenuShortcut shortcut)
+{
+ this.shortcut = shortcut;
+}
+
+/*************************************************************************/
+
+/**
+ * Deletes the shortcut for this menu item if one exists. This must be
+ * done before the native peer is created.
+ */
+public void
+deleteShortcut()
+{
+ shortcut = null;
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the name of the action command in the action events
+ * generated by this menu item.
+ *
+ * @return The action command name
+ */
+public String
+getActionCommand()
+{
+ if (actionCommand == null)
+ return label;
+ else
+ return actionCommand;
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the name of the action command in the action events generated by
+ * this menu item.
+ *
+ * @param actionCommand The new action command name.
+ */
+public void
+setActionCommand(String actionCommand)
+{
+ this.actionCommand = actionCommand;
+}
+
+/*************************************************************************/
+
+/**
+ * Enables the specified events. This is done automatically when a
+ * listener is added and does not normally need to be done by
+ * application code.
+ *
+ * @param events The events to enable, which should be the bit masks
+ * from <code>AWTEvent</code>.
+ */
+protected final void
+enableEvents(long events)
+{
+ eventMask |= events;
+ // TODO: see comment in Component.enableEvents().
+}
+
+/*************************************************************************/
+
+/**
+ * Disables the specified events.
+ *
+ * @param events The events to enable, which should be the bit masks
+ * from <code>AWTEvent</code>.
+ */
+protected final void
+disableEvents(long events)
+{
+ eventMask &= ~events;
+}
+
+/*************************************************************************/
+
+/**
+ * Creates the native peer for this object.
+ */
+public void
+addNotify()
+{
+ if (peer == null)
+ peer = getToolkit ().createMenuItem (this);
+}
+
+/*************************************************************************/
+
+/**
+ * Adds the specified listener to the list of registered action listeners
+ * for this component.
+ *
+ * @param listener The listener to add.
+ */
+public synchronized void
+addActionListener(ActionListener listener)
+{
+ action_listeners = AWTEventMulticaster.add(action_listeners, listener);
+
+ enableEvents(AWTEvent.ACTION_EVENT_MASK);
+}
+
+public synchronized void
+removeActionListener(ActionListener l)
+{
+ action_listeners = AWTEventMulticaster.remove(action_listeners, l);
+}
+
+ public synchronized ActionListener[] getActionListeners()
+ {
+ return (ActionListener[])
+ AWTEventMulticaster.getListeners(action_listeners,
+ ActionListener.class);
+ }
+
+/** Returns all registered EventListers of the given listenerType.
+ * listenerType must be a subclass of EventListener, or a
+ * ClassClassException is thrown.
+ * @since 1.3
+ */
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
+ {
+ if (listenerType == ActionListener.class)
+ return (T[]) getActionListeners();
+ return (T[]) Array.newInstance(listenerType, 0);
+ }
+
+/*************************************************************************/
+
+void
+dispatchEventImpl(AWTEvent e)
+{
+ if (e.id <= ActionEvent.ACTION_LAST
+ && e.id >= ActionEvent.ACTION_FIRST
+ && (action_listeners != null
+ || (eventMask & AWTEvent.ACTION_EVENT_MASK) != 0))
+ processEvent(e);
+
+ // Send the event to the parent menu if it has not yet been
+ // consumed.
+ if (!e.isConsumed ())
+ ((Menu) getParent ()).processEvent (e);
+}
+
+/**
+ * Processes the specified event by calling <code>processActionEvent()</code>
+ * if it is an instance of <code>ActionEvent</code>.
+ *
+ * @param event The event to process.
+ */
+protected void
+processEvent(AWTEvent event)
+{
+ if (event instanceof ActionEvent)
+ processActionEvent((ActionEvent)event);
+}
+
+/*************************************************************************/
+
+/**
+ * Processes the specified event by dispatching it to any registered listeners.
+ *
+ * @param event The event to process.
+ */
+protected void
+processActionEvent(ActionEvent event)
+{
+ if (action_listeners != null)
+ {
+ event.setSource(this);
+ action_listeners.actionPerformed(event);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a debugging string for this object.
+ *
+ * @return A debugging string for this object.
+ */
+public String
+paramString()
+{
+ return ("label=" + label + ",enabled=" + enabled +
+ ",actionCommand=" + actionCommand + "," + super.paramString());
+}
+
+/**
+ * Gets the AccessibleContext associated with this <code>MenuItem</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+public AccessibleContext getAccessibleContext()
+{
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTMenuItem();
+ return accessibleContext;
+}
+
+/**
+ * Generate a unique name for this <code>MenuItem</code>.
+ *
+ * @return A unique name for this <code>MenuItem</code>.
+ */
+String generateName()
+{
+ return "menuitem" + getUniqueLong();
+}
+
+private static synchronized long getUniqueLong()
+{
+ return next_menuitem_number++;
+}
+
+} // class MenuItem
diff --git a/libjava/classpath/java/awt/MenuShortcut.java b/libjava/classpath/java/awt/MenuShortcut.java
new file mode 100644
index 000000000..4939438f1
--- /dev/null
+++ b/libjava/classpath/java/awt/MenuShortcut.java
@@ -0,0 +1,434 @@
+/* MenuShortcut.java -- A class for menu accelerators
+ Copyright (C) 1999, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This class implements a keyboard accelerator for a menu item.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class MenuShortcut implements java.io.Serializable
+{
+
+/*
+ * Static Variables
+ */
+
+// Serialization Constant
+private static final long serialVersionUID = 143448358473180225L;
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * @serial The virtual keycode for the shortcut.
+ */
+private int key;
+
+/**
+ * @serial <code>true</code> if the shift key was used with this shortcut,
+ * or <code>false</code> otherwise.
+ */
+private boolean usesShift;
+
+private String keyName;
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>MenuShortcut</code> with the
+ * specified virtual key value.
+ *
+ * @param key The virtual keycode for the shortcut.
+ */
+public
+MenuShortcut(int key)
+{
+ this(key, false);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>MenuShortcut</code> with the
+ * specified virtual key value and shift setting.
+ *
+ * @param key The virtual keycode for the shortcut.
+ * @param usesShift <code>true</code> if the shift key was pressed,
+ * <code>false</code> otherwise.
+ */
+public
+MenuShortcut(int key, boolean usesShift)
+{
+ this.key = key;
+ this.usesShift = usesShift;
+ setKeyName(key);
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Methods
+ */
+
+/**
+ * Returns the virtual keycode for this shortcut.
+ *
+ * @return The virtual keycode for this shortcut.
+ */
+public int
+getKey()
+{
+ return(key);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the shift setting for this shortcut.
+ *
+ * @return <code>true</code> if the shift key was pressed, <code>false</code>
+ * otherwise.
+ */
+public boolean
+usesShiftModifier()
+{
+ return(usesShift);
+}
+
+/*************************************************************************/
+
+/**
+ * Tests this object for equality against the specified object. The two
+ * objects will be considered equal if and only if the specified object
+ * is an instance of <code>MenuShortcut</code> and has the same key value
+ * and shift setting as this object.
+ *
+ * @param obj The object to test for equality against.
+ *
+ * @return <code>true</code> if the two objects are equal, <code>false</code>
+ * otherwise.
+ */
+public boolean
+equals(MenuShortcut obj)
+{
+ if (obj == null)
+ return(false);
+
+ if (obj.key != this.key)
+ return(false);
+
+ if (obj.usesShift != this.usesShift)
+ return(false);
+
+ return(true);
+}
+
+public boolean
+equals(Object obj)
+{
+ if (obj instanceof MenuShortcut)
+ {
+ MenuShortcut ms = (MenuShortcut) obj;
+ return (ms.key == key && ms.usesShift == usesShift);
+ }
+ return false;
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a string representation of this shortcut.
+ *
+ * @return A string representation of this shortcut.
+ */
+public String
+toString()
+{
+ String temp = "Ctrl+";
+ if (usesShift)
+ temp = temp + "Shift+";
+ temp = temp + keyName;
+ return temp;
+}
+
+public int
+hashCode()
+{
+ // Arbitrary.
+ return key + (usesShift ? 23 : 57);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a debugging string for this object.
+ *
+ * @return A debugging string for this object.
+ */
+protected String
+paramString()
+{
+ return "key=" + key + ",usesShift=" + usesShift;
+}
+
+private void
+setKeyName(int key)
+{
+ if (key == '\n')
+ keyName = "Enter";
+ else if (key == '\b')
+ keyName = "Backspace";
+ else if (key == '\t')
+ keyName = "Tab";
+ else if (key == ' ')
+ keyName = "Space";
+ else if (key == ',')
+ keyName = "Comma";
+ else if (key == '.')
+ keyName = "Period";
+ else if (key == '/')
+ keyName = "Slash";
+ else if (key == '\\')
+ keyName = "Back Slash";
+ else if (key == ';')
+ keyName = "Semicolon";
+ else if (key == '=')
+ keyName = "Equals";
+ else if (key == '[')
+ keyName = "Open Bracket";
+ else if (key == ']')
+ keyName = "Close Bracket";
+ else if (key == '0')
+ keyName = "0";
+ else if (key == '1')
+ keyName = "1";
+ else if (key == '2')
+ keyName = "2";
+ else if (key == '3')
+ keyName = "3";
+ else if (key == '4')
+ keyName = "4";
+ else if (key == '5')
+ keyName = "5";
+ else if (key == '6')
+ keyName = "6";
+ else if (key == '7')
+ keyName = "7";
+ else if (key == '8')
+ keyName = "8";
+ else if (key == '9')
+ keyName = "9";
+ else if (key == 'A')
+ keyName = "A";
+ else if (key == 'B')
+ keyName = "B";
+ else if (key == 'C')
+ keyName = "C";
+ else if (key == 'D')
+ keyName = "D";
+ else if (key == 'E')
+ keyName = "E";
+ else if (key == 'F')
+ keyName = "F";
+ else if (key == 'G')
+ keyName = "G";
+ else if (key == 'H')
+ keyName = "H";
+ else if (key == 'I')
+ keyName = "I";
+ else if (key == 'J')
+ keyName = "J";
+ else if (key == 'K')
+ keyName = "K";
+ else if (key == 'L')
+ keyName = "L";
+ else if (key == 'M')
+ keyName = "M";
+ else if (key == 'N')
+ keyName = "N";
+ else if (key == 'O')
+ keyName = "O";
+ else if (key == 'P')
+ keyName = "P";
+ else if (key == 'Q')
+ keyName = "Q";
+ else if (key == 'R')
+ keyName = "R";
+ else if (key == 'S')
+ keyName = "S";
+ else if (key == 'T')
+ keyName = "T";
+ else if (key == 'U')
+ keyName = "U";
+ else if (key == 'V')
+ keyName = "V";
+ else if (key == 'W')
+ keyName = "W";
+ else if (key == 'X')
+ keyName = "X";
+ else if (key == 'Y')
+ keyName = "Y";
+ else if (key == 'Z')
+ keyName = "Z";
+ else if (key == 3)
+ keyName = "Cancel";
+ else if (key == 12)
+ keyName = "Clear";
+ else if (key == 16)
+ keyName = "Shift";
+ else if (key == 17)
+ keyName = "Ctrl";
+ else if (key == 18)
+ keyName = "Alt";
+ else if (key == 19)
+ keyName = "Pause";
+ else if (key == 20)
+ keyName = "Caps Lock";
+ else if (key == 21)
+ keyName = "Kana";
+ else if (key == 24)
+ keyName = "Final";
+ else if (key == 25)
+ keyName = "Kanji";
+ else if (key == 27)
+ keyName = "Escape";
+ else if (key == 28)
+ keyName = "Convert";
+ else if (key == 29)
+ keyName = "No Convert";
+ else if (key == 30)
+ keyName = "Accept";
+ else if (key == 31)
+ keyName = "Mode Change";
+ else if (key == 33)
+ keyName = "Page Up";
+ else if (key == 34)
+ keyName = "Page Down";
+ else if (key == 35)
+ keyName = "End";
+ else if (key == 36)
+ keyName = "Home";
+ else if (key == 37)
+ keyName = "Left";
+ else if (key == 38)
+ keyName = "Up";
+ else if (key == 39)
+ keyName = "Right";
+ else if (key == 40)
+ keyName = "Down";
+ else if (key == 96)
+ keyName = "NumPad-0";
+ else if (key == 97)
+ keyName = "NumPad-1";
+ else if (key == 98)
+ keyName = "NumPad-2";
+ else if (key == 99)
+ keyName = "NumPad-3";
+ else if (key == 100)
+ keyName = "NumPad-4";
+ else if (key == 101)
+ keyName = "NumPad-5";
+ else if (key == 102)
+ keyName = "NumPad-6";
+ else if (key == 103)
+ keyName = "NumPad-7";
+ else if (key == 104)
+ keyName = "NumPad-8";
+ else if (key == 105)
+ keyName = "NumPad-9";
+ else if (key == 106)
+ keyName = "NumPad *";
+ else if (key == 107)
+ keyName = "NumPad +";
+ else if (key == 108)
+ keyName = "NumPad ,";
+ else if (key == 109)
+ keyName = "NumPad -";
+ else if (key == 110)
+ keyName = "NumPad .";
+ else if (key == 111)
+ keyName = "NumPad /";
+ else if (key == 112)
+ keyName = "F1";
+ else if (key == 113)
+ keyName = "F2";
+ else if (key == 114)
+ keyName = "F3";
+ else if (key == 115)
+ keyName = "F4";
+ else if (key == 116)
+ keyName = "F5";
+ else if (key == 117)
+ keyName = "F6";
+ else if (key == 118)
+ keyName = "F7";
+ else if (key == 119)
+ keyName = "F8";
+ else if (key == 120)
+ keyName = "F9";
+ else if (key == 121)
+ keyName = "F10";
+ else if (key == 122)
+ keyName = "F11";
+ else if (key == 123)
+ keyName = "F12";
+ else if (key == 127)
+ keyName = "Delete";
+ else if (key == 144)
+ keyName = "Num Lock";
+ else if (key == 145)
+ keyName = "Scroll Lock";
+ else if (key == 154)
+ keyName = "Print Screen";
+ else if (key == 155)
+ keyName = "Insert";
+ else if (key == 156)
+ keyName = "Help";
+ else if (key == 157)
+ keyName = "Meta";
+ else if (key == 192)
+ keyName = "Back Quote";
+ else if (key == 222)
+ keyName = "Quote";
+}
+} // class MenuShortcut
diff --git a/libjava/classpath/java/awt/MouseInfo.java b/libjava/classpath/java/awt/MouseInfo.java
new file mode 100644
index 000000000..62d7d3068
--- /dev/null
+++ b/libjava/classpath/java/awt/MouseInfo.java
@@ -0,0 +1,102 @@
+/* MouseInfo.java -- utility methods for mice.
+ Copyright (C) 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt;
+
+import gnu.java.awt.ClasspathToolkit;
+import java.awt.peer.MouseInfoPeer;
+
+/**
+ * MouseInfo is a class containing utility functions for mouse information.
+ *
+ * @author Sven de Marothy
+ * @since 1.5
+ */
+public class MouseInfo
+{
+ private static MouseInfoPeer peer;
+
+ /**
+ * Private constructor to prevent instance creation.
+ */
+ private MouseInfo()
+ {
+ }
+
+ /**
+ * Returns a PointerInfo object containing information about the current
+ * location of the mouse pointer
+ *
+ * @throws HeadlessException if the current GraphicsEnvironment is headless.
+ * @return a PointerInfo object.
+ */
+ public static PointerInfo getPointerInfo() throws HeadlessException
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission( new AWTPermission("watchMousePointer") );
+
+ if( GraphicsEnvironment.isHeadless() )
+ throw new HeadlessException();
+
+ if( peer == null )
+ peer = Toolkit.getDefaultToolkit().getMouseInfoPeer();
+
+ Point p = new Point();
+ int screen = peer.fillPointWithCoords( p );
+
+ GraphicsDevice[] gds = GraphicsEnvironment.getLocalGraphicsEnvironment().
+ getScreenDevices();
+
+ return new PointerInfo( gds[ screen ], p );
+ }
+
+ /**
+ * Returns the number of mouse buttons, or -1 if no mouse is connected.
+ * (mentioned in the 1.5 release notes)
+ *
+ * @throws HeadlessException if the current GraphicsEnvironment is headless.
+ * @return an integer number of buttons.
+ */
+ public static int getNumberOfButtons() throws HeadlessException
+ {
+ if( GraphicsEnvironment.isHeadless() )
+ throw new HeadlessException();
+ return ((ClasspathToolkit)Toolkit.getDefaultToolkit()).
+ getMouseNumberOfButtons();
+ }
+}
diff --git a/libjava/classpath/java/awt/PageAttributes.java b/libjava/classpath/java/awt/PageAttributes.java
new file mode 100644
index 000000000..825d0feb3
--- /dev/null
+++ b/libjava/classpath/java/awt/PageAttributes.java
@@ -0,0 +1,482 @@
+/* PageAttributes.java --
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.util.Locale;
+
+/**
+ * Missing Documentation
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.3
+ * @status updated to 1.4, but missing documentation
+ */
+public final class PageAttributes implements Cloneable
+{
+ public static final class ColorType extends AttributeValue
+ {
+ private static final String[] NAMES = { "color", "monochrome" };
+ public static final ColorType COLOR = new ColorType(0);
+ public static final ColorType MONOCHROME = new ColorType(1);
+ private ColorType(int value)
+ {
+ super(value, NAMES);
+ }
+ } // class ColorType
+ public static final class MediaType extends AttributeValue
+ {
+ private static final String[] NAMES
+ = { "iso-4a0", "iso-2a0", "iso-a0", "iso-a1", "iso-a2", "iso-a3",
+ "iso-a4", "iso-a5", "iso-a6", "iso-a7", "iso-a8", "iso-a9",
+ "iso-a10", "iso-b0", "iso-b1", "iso-b2", "iso-b3", "iso-b4",
+ "iso-b5", "iso-b6", "iso-b7", "iso-b8", "iso-b9", "iso-b10",
+ "jis-b0", "jis-b1", "jis-b2", "jis-b3", "jis-b4", "jis-b5",
+ "jis-b6", "jis-b7", "jis-b8", "jis-b9", "jis-b10", "iso-c0",
+ "iso-c1", "iso-c2", "iso-c3", "iso-c4", "iso-c5", "iso-c6",
+ "iso-c7", "iso-c8", "iso-c9", "iso-c10", "iso-designated-long",
+ "executive", "folio", "invoice", "ledger", "na-letter", "na-legal",
+ "quarto", "a", "b", "c", "d", "e", "na-10x15-envelope",
+ "na-10x14-envelope", "na-10x13-envelope", "na-9x12-envelope",
+ "na-9x11-envelope", "na-7x9-envelope", "na-6x9-envelope",
+ "na-number-9-envelope", "na-number-10-envelope",
+ "na-number-11-envelope", "na-number-12-envelope",
+ "na-number-14-envelope", "invite-envelope", "italy-envelope",
+ "monarch-envelope", "personal-envelope" };
+ public static final MediaType ISO_4A0 = new MediaType(0);
+ public static final MediaType ISO_2A0 = new MediaType(1);
+ public static final MediaType ISO_A0 = new MediaType(2);
+ public static final MediaType ISO_A1 = new MediaType(3);
+ public static final MediaType ISO_A2 = new MediaType(4);
+ public static final MediaType ISO_A3 = new MediaType(5);
+ public static final MediaType ISO_A4 = new MediaType(6);
+ public static final MediaType ISO_A5 = new MediaType(7);
+ public static final MediaType ISO_A6 = new MediaType(8);
+ public static final MediaType ISO_A7 = new MediaType(9);
+ public static final MediaType ISO_A8 = new MediaType(10);
+ public static final MediaType ISO_A9 = new MediaType(11);
+ public static final MediaType ISO_A10 = new MediaType(12);
+ public static final MediaType ISO_B0 = new MediaType(13);
+ public static final MediaType ISO_B1 = new MediaType(14);
+ public static final MediaType ISO_B2 = new MediaType(15);
+ public static final MediaType ISO_B3 = new MediaType(16);
+ public static final MediaType ISO_B4 = new MediaType(17);
+ public static final MediaType ISO_B5 = new MediaType(18);
+ public static final MediaType ISO_B6 = new MediaType(19);
+ public static final MediaType ISO_B7 = new MediaType(20);
+ public static final MediaType ISO_B8 = new MediaType(21);
+ public static final MediaType ISO_B9 = new MediaType(22);
+ public static final MediaType ISO_B10 = new MediaType(23);
+ public static final MediaType JIS_B0 = new MediaType(24);
+ public static final MediaType JIS_B1 = new MediaType(25);
+ public static final MediaType JIS_B2 = new MediaType(26);
+ public static final MediaType JIS_B3 = new MediaType(27);
+ public static final MediaType JIS_B4 = new MediaType(28);
+ public static final MediaType JIS_B5 = new MediaType(29);
+ public static final MediaType JIS_B6 = new MediaType(30);
+ public static final MediaType JIS_B7 = new MediaType(31);
+ public static final MediaType JIS_B8 = new MediaType(32);
+ public static final MediaType JIS_B9 = new MediaType(33);
+ public static final MediaType JIS_B10 = new MediaType(34);
+ public static final MediaType ISO_C0 = new MediaType(35);
+ public static final MediaType ISO_C1 = new MediaType(36);
+ public static final MediaType ISO_C2 = new MediaType(37);
+ public static final MediaType ISO_C3 = new MediaType(38);
+ public static final MediaType ISO_C4 = new MediaType(39);
+ public static final MediaType ISO_C5 = new MediaType(40);
+ public static final MediaType ISO_C6 = new MediaType(41);
+ public static final MediaType ISO_C7 = new MediaType(42);
+ public static final MediaType ISO_C8 = new MediaType(43);
+ public static final MediaType ISO_C9 = new MediaType(44);
+ public static final MediaType ISO_C10 = new MediaType(45);
+ public static final MediaType ISO_DESIGNATED_LONG = new MediaType(46);
+ public static final MediaType EXECUTIVE = new MediaType(47);
+ public static final MediaType FOLIO = new MediaType(48);
+ public static final MediaType INVOICE = new MediaType(49);
+ public static final MediaType LEDGER = new MediaType(50);
+ public static final MediaType NA_LETTER = new MediaType(51);
+ public static final MediaType NA_LEGAL = new MediaType(52);
+ public static final MediaType QUARTO = new MediaType(53);
+ public static final MediaType A = new MediaType(54);
+ public static final MediaType B = new MediaType(55);
+ public static final MediaType C = new MediaType(56);
+ public static final MediaType D = new MediaType(57);
+ public static final MediaType E = new MediaType(58);
+ public static final MediaType NA_10X15_ENVELOPE = new MediaType(59);
+ public static final MediaType NA_10X14_ENVELOPE = new MediaType(60);
+ public static final MediaType NA_10X13_ENVELOPE = new MediaType(61);
+ public static final MediaType NA_9X12_ENVELOPE = new MediaType(62);
+ public static final MediaType NA_9X11_ENVELOPE = new MediaType(63);
+ public static final MediaType NA_7X9_ENVELOPE = new MediaType(64);
+ public static final MediaType NA_6X9_ENVELOPE = new MediaType(65);
+ public static final MediaType NA_NUMBER_9_ENVELOPE = new MediaType(66);
+ public static final MediaType NA_NUMBER_10_ENVELOPE = new MediaType(67);
+ public static final MediaType NA_NUMBER_11_ENVELOPE = new MediaType(68);
+ public static final MediaType NA_NUMBER_12_ENVELOPE = new MediaType(69);
+ public static final MediaType NA_NUMBER_14_ENVELOPE = new MediaType(70);
+ public static final MediaType INVITE_ENVELOPE = new MediaType(71);
+ public static final MediaType ITALY_ENVELOPE = new MediaType(72);
+ public static final MediaType MONARCH_ENVELOPE = new MediaType(73);
+ public static final MediaType PERSONAL_ENVELOPE = new MediaType(74);
+ public static final MediaType A0 = ISO_A0;
+ public static final MediaType A1 = ISO_A1;
+ public static final MediaType A2 = ISO_A2;
+ public static final MediaType A3 = ISO_A3;
+ public static final MediaType A4 = ISO_A4;
+ public static final MediaType A5 = ISO_A5;
+ public static final MediaType A6 = ISO_A6;
+ public static final MediaType A7 = ISO_A7;
+ public static final MediaType A8 = ISO_A8;
+ public static final MediaType A9 = ISO_A9;
+ public static final MediaType A10 = ISO_A10;
+ public static final MediaType B0 = ISO_B0;
+ public static final MediaType B1 = ISO_B1;
+ public static final MediaType B2 = ISO_B2;
+ public static final MediaType B3 = ISO_B3;
+ public static final MediaType B4 = ISO_B4;
+ public static final MediaType ISO_B4_ENVELOPE = ISO_B4;
+ public static final MediaType B5 = ISO_B5;
+ public static final MediaType ISO_B5_ENVELOPE = ISO_B4;
+ public static final MediaType B6 = ISO_B6;
+ public static final MediaType B7 = ISO_B7;
+ public static final MediaType B8 = ISO_B8;
+ public static final MediaType B9 = ISO_B9;
+ public static final MediaType B10 = ISO_B10;
+ public static final MediaType C0 = ISO_B0;
+ public static final MediaType ISO_C0_ENVELOPE = ISO_C0;
+ public static final MediaType C1 = ISO_C1;
+ public static final MediaType ISO_C1_ENVELOPE = ISO_C1;
+ public static final MediaType C2 = ISO_C2;
+ public static final MediaType ISO_C2_ENVELOPE = ISO_C2;
+ public static final MediaType C3 = ISO_C3;
+ public static final MediaType ISO_C3_ENVELOPE = ISO_C3;
+ public static final MediaType C4 = ISO_C4;
+ public static final MediaType ISO_C4_ENVELOPE = ISO_C4;
+ public static final MediaType C5 = ISO_C5;
+ public static final MediaType ISO_C5_ENVELOPE = ISO_C5;
+ public static final MediaType C6 = ISO_C6;
+ public static final MediaType ISO_C6_ENVELOPE = ISO_C6;
+ public static final MediaType C7 = ISO_C7;
+ public static final MediaType ISO_C7_ENVELOPE = ISO_C7;
+ public static final MediaType C8 = ISO_C8;
+ public static final MediaType ISO_C8_ENVELOPE = ISO_C8;
+ public static final MediaType C9 = ISO_C9;
+ public static final MediaType ISO_C9_ENVELOPE = ISO_C9;
+ public static final MediaType C10 = ISO_C10;
+ public static final MediaType ISO_C10_ENVELOPE = ISO_C10;
+ public static final MediaType ISO_DESIGNATED_LONG_ENVELOPE
+ = ISO_DESIGNATED_LONG;
+ public static final MediaType STATEMENT = INVOICE;
+ public static final MediaType TABLOID = LEDGER;
+ public static final MediaType LETTER = NA_LETTER;
+ public static final MediaType NOTE = NA_LETTER;
+ public static final MediaType LEGAL = NA_LEGAL;
+ public static final MediaType ENV_10X15 = NA_10X15_ENVELOPE;
+ public static final MediaType ENV_10X14 = NA_10X14_ENVELOPE;
+ public static final MediaType ENV_10X13 = NA_10X13_ENVELOPE;
+ public static final MediaType ENV_9X12 = NA_9X12_ENVELOPE;
+ public static final MediaType ENV_9X11 = NA_9X11_ENVELOPE;
+ public static final MediaType ENV_7X9 = NA_7X9_ENVELOPE;
+ public static final MediaType ENV_6X9 = NA_6X9_ENVELOPE;
+ public static final MediaType ENV_9 = NA_NUMBER_9_ENVELOPE;
+ public static final MediaType ENV_10 = NA_NUMBER_10_ENVELOPE;
+ public static final MediaType ENV_11 = NA_NUMBER_11_ENVELOPE;
+ public static final MediaType ENV_12 = NA_NUMBER_12_ENVELOPE;
+ public static final MediaType ENV_14 = NA_NUMBER_14_ENVELOPE;
+ public static final MediaType ENV_INVITE = INVITE_ENVELOPE;
+ public static final MediaType ENV_ITALY = ITALY_ENVELOPE;
+ public static final MediaType ENV_MONARCH = MONARCH_ENVELOPE;
+ public static final MediaType ENV_PERSONAL = PERSONAL_ENVELOPE;
+ public static final MediaType INVITE = INVITE_ENVELOPE;
+ public static final MediaType ITALY = ITALY_ENVELOPE;
+ public static final MediaType MONARCH = MONARCH_ENVELOPE;
+ public static final MediaType PERSONAL = PERSONAL_ENVELOPE;
+ private MediaType(int value)
+ {
+ super(value, NAMES);
+ }
+ } // class MediaType
+ public static final class OrientationRequestedType extends AttributeValue
+ {
+ private static final String[] NAMES = { "portrait", "landscape" };
+ public static final OrientationRequestedType PORTRAIT
+ = new OrientationRequestedType(0);
+ public static final OrientationRequestedType LANDSCAPE
+ = new OrientationRequestedType(1);
+ private OrientationRequestedType(int value)
+ {
+ super(value, NAMES);
+ }
+ } // class OrientationRequestedType
+ public static final class OriginType extends AttributeValue
+ {
+ private static final String[] NAMES = { "physical", "printable" };
+ public static final OriginType PHYSICAL = new OriginType(0);
+ public static final OriginType PRINTABLE = new OriginType(1);
+ private OriginType(int value)
+ {
+ super(value, NAMES);
+ }
+ } // class OriginType
+ public static final class PrintQualityType extends AttributeValue
+ {
+ private static final String[] NAMES = { "high", "normal", "draft" };
+ public static final PrintQualityType HIGH = new PrintQualityType(0);
+ public static final PrintQualityType NORMAL = new PrintQualityType(1);
+ public static final PrintQualityType DRAFT = new PrintQualityType(2);
+ private PrintQualityType(int value)
+ {
+ super(value, NAMES);
+ }
+ } // class PrintQualityType
+
+
+ private ColorType color;
+ private MediaType media;
+ private OrientationRequestedType orientation;
+ private OriginType origin;
+ private PrintQualityType quality;
+ private int resolutionX;
+ private int resolutionY;
+ private int resolutionScale;
+ public PageAttributes()
+ {
+ color = ColorType.MONOCHROME;
+ setMediaToDefault();
+ orientation = OrientationRequestedType.PORTRAIT;
+ origin = OriginType.PHYSICAL;
+ quality = PrintQualityType.NORMAL;
+ setPrinterResolutionToDefault();
+ }
+
+ public PageAttributes(PageAttributes attr)
+ {
+ set(attr);
+ }
+
+ public PageAttributes(ColorType color, MediaType media,
+ OrientationRequestedType orientation,
+ OriginType origin, PrintQualityType quality,
+ int[] resolution)
+ {
+ if (color == null || media == null || orientation == null
+ || origin == null || quality == null)
+ throw new IllegalArgumentException();
+ setPrinterResolution(resolution);
+ this.color = color;
+ this.media = media;
+ this.orientation = orientation;
+ this.origin = origin;
+ this.quality = quality;
+ }
+
+ public Object clone()
+ {
+ return new PageAttributes(this);
+ }
+
+ public void set(PageAttributes attr)
+ {
+ color = attr.color;
+ media = attr.media;
+ orientation = attr.orientation;
+ origin = attr.origin;
+ quality = attr.quality;
+ resolutionX = attr.resolutionX;
+ resolutionY = attr.resolutionY;
+ resolutionScale = attr.resolutionScale;
+ }
+
+ public ColorType getColor()
+ {
+ return color;
+ }
+
+ public void setColor(ColorType color)
+ {
+ if (color == null)
+ throw new IllegalArgumentException();
+ this.color = color;
+ }
+
+ public MediaType getMedia()
+ {
+ return media;
+ }
+
+ public void setMedia(MediaType media)
+ {
+ if (media == null)
+ throw new IllegalArgumentException();
+ this.media = media;
+ }
+
+ public void setMediaToDefault()
+ {
+ String country = Locale.getDefault().getCountry();
+ media = ("US".equals(country) || "CA".equals(country)) ? MediaType.LETTER
+ : MediaType.A4;
+ }
+
+ public OrientationRequestedType getOrientationRequested()
+ {
+ return orientation;
+ }
+
+ public void setOrientationRequested(OrientationRequestedType orientation)
+ {
+ if (orientation == null)
+ throw new IllegalArgumentException();
+ this.orientation = orientation;
+ }
+
+ public void setOrientationRequested(int orientation)
+ {
+ if (orientation == 3)
+ this.orientation = OrientationRequestedType.PORTRAIT;
+ else if (orientation == 4)
+ this.orientation = OrientationRequestedType.LANDSCAPE;
+ else
+ throw new IllegalArgumentException();
+ }
+
+ public void setOrientationRequestedToDefault()
+ {
+ orientation = OrientationRequestedType.PORTRAIT;
+ }
+
+ public OriginType getOrigin()
+ {
+ return origin;
+ }
+
+ public void setOrigin(OriginType origin)
+ {
+ if (origin == null)
+ throw new IllegalArgumentException();
+ this.origin = origin;
+ }
+
+ public PrintQualityType getPrintQuality()
+ {
+ return quality;
+ }
+
+ public void setPrintQuality(PrintQualityType quality)
+ {
+ if (quality == null)
+ throw new IllegalArgumentException();
+ this.quality = quality;
+ }
+
+ public void setPrintQuality(int quality)
+ {
+ if (quality == 3)
+ this.quality = PrintQualityType.DRAFT;
+ else if (quality == 4)
+ this.quality = PrintQualityType.NORMAL;
+ else if (quality == 5)
+ this.quality = PrintQualityType.HIGH;
+ else
+ throw new IllegalArgumentException();
+ }
+
+ public void setPrintQualityToDefault()
+ {
+ quality = PrintQualityType.NORMAL;
+ }
+
+ public int[] getPrinterResolution()
+ {
+ return new int[] { resolutionX, resolutionY, resolutionScale };
+ }
+
+ public void setPrinterResolution(int[] resolution)
+ {
+ if (resolution == null || resolution.length != 3 || resolution[0] <= 0
+ || resolution[1] <= 0 || resolution[2] < 3 || resolution[2] > 4)
+ throw new IllegalArgumentException();
+ resolutionX = resolution[0];
+ resolutionY = resolution[1];
+ resolutionScale = resolution[2];
+ }
+
+ public void setPrinterResolution(int resolution)
+ {
+ if (resolution <= 0)
+ throw new IllegalArgumentException();
+ resolutionX = resolution;
+ resolutionY = resolution;
+ resolutionScale = 3;
+ }
+
+ public void setPrinterResolutionToDefault()
+ {
+ resolutionX = 72;
+ resolutionY = 72;
+ resolutionScale = 3;
+ }
+
+ public boolean equals(Object o)
+ {
+ if (this == o)
+ return true;
+ if (! (o instanceof PageAttributes))
+ return false;
+ PageAttributes pa = (PageAttributes) o;
+ return color == pa.color && media == pa.media
+ && orientation == pa.orientation && origin == pa.origin
+ && quality == pa.quality && resolutionX == pa.resolutionX
+ && resolutionY == pa.resolutionY
+ && resolutionScale == pa.resolutionScale;
+ }
+ public int hashCode()
+ {
+ return (color.value << 31) ^ (media.value << 24)
+ ^ (orientation.value << 23) ^ (origin.value << 22)
+ ^ (quality.value << 20) ^ (resolutionScale << 19)
+ ^ (resolutionY << 10) ^ resolutionX;
+ }
+ public String toString()
+ {
+ return "color=" + color + ",media=" + media + ",orientation-requested="
+ + orientation + ",origin=" + origin + ",print-quality=" + quality
+ + ",printer-resolution=[" + resolutionX + ',' + resolutionY + ','
+ + resolutionScale + ']';
+ }
+} // class PageAttributes
diff --git a/libjava/classpath/java/awt/Paint.java b/libjava/classpath/java/awt/Paint.java
new file mode 100644
index 000000000..0f099cc0b
--- /dev/null
+++ b/libjava/classpath/java/awt/Paint.java
@@ -0,0 +1,79 @@
+/* Paint.java -- generate colors for Graphics2D operations
+ Copyright (C) 2000, 2002 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.ColorModel;
+
+/**
+ * Defines how color patterns are generated for Graphics2D operations. This
+ * is used to perform the <code>draw</code> and <code>fill</code> methods
+ * of the graphics object. Instances must be immutable, because the graphics
+ * object does not clone them.
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @see PaintContext
+ * @see Color
+ * @see GradientPaint
+ * @see TexturePaint
+ * @see Graphics2D#setPaint(Paint)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface Paint extends Transparency
+{
+ /**
+ * Create the context necessary for performing the color pattern generation.
+ * The color model is a hint, and may be null for Classpath implementations;
+ * however some legacy code may throw a NullPointerException when passed a
+ * null. Leaving the color model null provides the most efficiency and leeway
+ * in the generation of the color pattern.
+ *
+ * @param cm the color model, used as a hint
+ * @param deviceBounds the device space bounding box of the painted area
+ * @param userBounds the user space bounding box of the painted area
+ * @param xform the transformation from user space to device space
+ * @param hints any hints for choosing between rendering alternatives
+ * @return the context for performing the paint
+ */
+ PaintContext createContext(ColorModel cm, Rectangle deviceBounds,
+ Rectangle2D userBounds, AffineTransform xform,
+ RenderingHints hints);
+} // interface Paint
diff --git a/libjava/classpath/java/awt/PaintContext.java b/libjava/classpath/java/awt/PaintContext.java
new file mode 100644
index 000000000..3d5fdcdf0
--- /dev/null
+++ b/libjava/classpath/java/awt/PaintContext.java
@@ -0,0 +1,76 @@
+/* PaintContext.java -- the environment for performing a paint operation
+ Copyright (C) 2000, 2002 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.image.ColorModel;
+import java.awt.image.Raster;
+
+/**
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @see Paint
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface PaintContext
+{
+ /**
+ * Release the resources allocated for the paint.
+ */
+ void dispose();
+
+ /**
+ * Return the color model of this context. It may be different from the
+ * hint specified during createContext, as not all contexts can generate
+ * color patterns in an arbitrary model.
+ *
+ * @return the context color model
+ */
+ ColorModel getColorModel();
+
+ /**
+ * Return a raster containing the colors for the graphics operation.
+ *
+ * @param x the x-coordinate, in device space
+ * @param y the y-coordinate, in device space
+ * @param w the width, in device space
+ * @param h the height, in device space
+ * @return a raster for the given area and color
+ */
+ Raster getRaster(int x, int y, int w, int h);
+} // interface PaintContext
diff --git a/libjava/classpath/java/awt/Panel.java b/libjava/classpath/java/awt/Panel.java
new file mode 100644
index 000000000..cc17eef22
--- /dev/null
+++ b/libjava/classpath/java/awt/Panel.java
@@ -0,0 +1,173 @@
+/* Panel.java -- Simple container object
+ Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+
+/**
+ * A panel is a simple container class. It's default layout is the
+ * <code>FlowLayout</code> manager.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see FlowLayout
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public class Panel extends Container implements Accessible
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -2728009084054400034L;
+
+ /** The cached accessible context. */
+ private transient AccessibleContext context;
+
+ /** Flag set when the first system-requested paint event is
+ dispatched. */
+ private transient boolean initialSystemUpdateDone;
+
+ /** Flag set when the first application-requested paint event is
+ consumed. */
+ private transient boolean initialUpdateConsumed;
+
+ /*
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_panel_number;
+
+ /**
+ * Initializes a new instance of <code>Panel</code> that has a default
+ * layout manager of <code>FlowLayout</code>.
+ */
+ public Panel()
+ {
+ this(new FlowLayout());
+ }
+
+ /**
+ * Initializes a new instance of <code>Panel</code> with the specified
+ * layout manager.
+ *
+ * @param layoutManager the layout manager for this object
+ * @since 1.1
+ */
+ public Panel(LayoutManager layoutManager)
+ {
+ setLayout(layoutManager);
+ }
+
+ /**
+ * Notifies this object to create its native peer.
+ *
+ * @see #isDisplayable()
+ * @see #removeNotify()
+ */
+ public void addNotify()
+ {
+ if (peer == null)
+ peer = getToolkit().createPanel(this);
+ super.addNotify();
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this panel, creating one if
+ * necessary. This always returns an instance of {@link AccessibleAWTPanel}.
+ *
+ * @return the accessibility context of this panel
+ * @since 1.3
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ if (context == null)
+ context = new AccessibleAWTPanel();
+ return context;
+ }
+
+ /**
+ * This class provides accessibility support for Panels, and is the
+ * runtime type returned by {@link #getAccessibleContext()}.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.3
+ */
+ protected class AccessibleAWTPanel extends AccessibleAWTContainer
+ {
+ /**
+ * Compatible with JDK 1.4+.
+ */
+ private static final long serialVersionUID = -6409552226660031050L;
+
+ /**
+ * The default constructor.
+ */
+ protected AccessibleAWTPanel()
+ {
+ }
+
+ /**
+ * Get the role of this accessible object, a panel.
+ *
+ * @return the role of the object
+ * @see AccessibleRole#PANEL
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.PANEL;
+ }
+ }
+
+ /**
+ * Generate a unique name for this panel.
+ *
+ * @return A unique name for this panel.
+ */
+ String generateName ()
+ {
+ return "panel" + getUniqueLong ();
+ }
+
+ private static synchronized long getUniqueLong ()
+ {
+ return next_panel_number++;
+ }
+}
diff --git a/libjava/classpath/java/awt/Point.java b/libjava/classpath/java/awt/Point.java
new file mode 100644
index 000000000..871202491
--- /dev/null
+++ b/libjava/classpath/java/awt/Point.java
@@ -0,0 +1,250 @@
+/* Point.java -- represents a point in 2-D space
+ Copyright (C) 1999, 2002, 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.geom.Point2D;
+import java.io.Serializable;
+
+/**
+ * This class represents a point on the screen using cartesian coordinates.
+ * Remember that in screen coordinates, increasing x values go from left to
+ * right, and increasing y values go from top to bottom.
+ *
+ * <p>There are some public fields; if you mess with them in an inconsistent
+ * manner, it is your own fault when you get invalid results. Also, this
+ * class is not threadsafe.
+ *
+ * @author Per Bothner (bothner@cygnus.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public class Point extends Point2D implements Serializable
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -5276940640259749850L;
+
+ /**
+ * The x coordinate.
+ *
+ * @see #getLocation()
+ * @see #move(int, int)
+ * @serial the X coordinate of the point
+ */
+ public int x;
+
+ /**
+ * The y coordinate.
+ *
+ * @see #getLocation()
+ * @see #move(int, int)
+ * @serial The Y coordinate of the point
+ */
+ public int y;
+
+ /**
+ * Initializes a new instance of <code>Point</code> representing the
+ * coordinates (0, 0).
+ *
+ * @since 1.1
+ */
+ public Point()
+ {
+ }
+
+ /**
+ * Initializes a new instance of <code>Point</code> with coordinates
+ * identical to the coordinates of the specified point.
+ *
+ * @param p the point to copy the coordinates from
+ * @throws NullPointerException if p is null
+ */
+ public Point(Point p)
+ {
+ x = p.x;
+ y = p.y;
+ }
+
+ /**
+ * Initializes a new instance of <code>Point</code> with the specified
+ * coordinates.
+ *
+ * @param x the X coordinate
+ * @param y the Y coordinate
+ */
+ public Point(int x, int y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ * Get the x coordinate.
+ *
+ * @return the value of x, as a double
+ */
+ public double getX()
+ {
+ return x;
+ }
+
+ /**
+ * Get the y coordinate.
+ *
+ * @return the value of y, as a double
+ */
+ public double getY()
+ {
+ return y;
+ }
+
+ /**
+ * Returns the location of this point. A pretty useless method, as this
+ * is already a point.
+ *
+ * @return a copy of this point
+ * @see #setLocation(Point)
+ * @since 1.1
+ */
+ public Point getLocation()
+ {
+ return new Point(x, y);
+ }
+
+ /**
+ * Sets this object's coordinates to match those of the specified point.
+ *
+ * @param p the point to copy the coordinates from
+ * @throws NullPointerException if p is null
+ * @since 1.1
+ */
+ public void setLocation(Point p)
+ {
+ x = p.x;
+ y = p.y;
+ }
+
+ /**
+ * Sets this object's coordinates to the specified values. This method
+ * is identical to the <code>move()</code> method.
+ *
+ * @param x the new X coordinate
+ * @param y the new Y coordinate
+ */
+ public void setLocation(int x, int y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ * Sets this object's coordinates to the specified values. This method
+ * rounds to the nearest integer coordinates by adding 0.5 and calling
+ * {@link Math#floor(double)}.
+ *
+ * @param x the new X coordinate
+ * @param y the new Y coordinate
+ */
+ public void setLocation(double x, double y)
+ {
+ this.x = (int) Math.floor(x + 0.5);
+ this.y = (int) Math.floor(y + 0.5);
+ }
+
+ /**
+ * Sets this object's coordinates to the specified values. This method
+ * is identical to the <code>setLocation(int, int)</code> method.
+ *
+ * @param x the new X coordinate
+ * @param y the new Y coordinate
+ */
+ public void move(int x, int y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ * Changes the coordinates of this point such that the specified
+ * <code>dx</code> parameter is added to the existing X coordinate and
+ * <code>dy</code> is added to the existing Y coordinate.
+ *
+ * @param dx the amount to add to the X coordinate
+ * @param dy the amount to add to the Y coordinate
+ */
+ public void translate(int dx, int dy)
+ {
+ x += dx;
+ y += dy;
+ }
+
+ /**
+ * Tests whether or not this object is equal to the specified object.
+ * This will be true if and only if the specified object is an instance
+ * of Point2D and has the same X and Y coordinates.
+ *
+ * @param obj the object to test against for equality
+ * @return true if the specified object is equal
+ */
+ public boolean equals(Object obj)
+ {
+ // NOTE: No special hashCode() method is required for this class,
+ // as this equals() implementation is functionally equivalent to
+ // super.equals(), which does define a proper hashCode().
+
+ if (! (obj instanceof Point2D))
+ return false;
+ Point2D p = (Point2D) obj;
+ return x == p.getX() && y == p.getY();
+ }
+
+ /**
+ * Returns a string representation of this object. The format is:
+ * <code>getClass().getName() + "[x=" + x + ",y=" + y + ']'</code>.
+ *
+ * @return a string representation of this object
+ */
+ public String toString()
+ {
+ return getClass().getName() + "[x=" + x + ",y=" + y + ']';
+ }
+} // class Point
diff --git a/libjava/classpath/java/awt/PointerInfo.java b/libjava/classpath/java/awt/PointerInfo.java
new file mode 100644
index 000000000..2bbd97677
--- /dev/null
+++ b/libjava/classpath/java/awt/PointerInfo.java
@@ -0,0 +1,84 @@
+/* PointerInfo.java -- mouse pointer data
+ Copyright (C) 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt;
+
+/**
+ * PointerInfo represents information about the mouse pointer,
+ * i.e. its GraphicsDevice and location.
+ *
+ * PointerInfo objects cannot be instantiated directly, but are
+ * retrieved from MouseInfo.getPointerInfo(). PointerInfo objects
+ * are immutable and will not be updated for future mouse motions.
+ *
+ * @since 1.5
+ * @author Sven de Marothy
+ */
+public class PointerInfo
+{
+ private GraphicsDevice gd;
+ private Point p;
+
+ /**
+ * Package-private constructor used by MouseInfo.
+ */
+ PointerInfo( GraphicsDevice gd, Point p )
+ {
+ this.gd = gd;
+ this.p = p;
+ }
+
+ /**
+ * Returns the GraphicsDevice on which the mouse pointer was located
+ *
+ * @return a GraphicsDevice object.
+ */
+ public GraphicsDevice getDevice()
+ {
+ return gd;
+ }
+
+ /**
+ * Returns the coordinates of the mouse pointer.
+ *
+ * @return a Point object containing the pointer coordinates.
+ */
+ public Point getLocation()
+ {
+ return p;
+ }
+}
diff --git a/libjava/classpath/java/awt/Polygon.java b/libjava/classpath/java/awt/Polygon.java
new file mode 100644
index 000000000..03e91f8bd
--- /dev/null
+++ b/libjava/classpath/java/awt/Polygon.java
@@ -0,0 +1,611 @@
+/* Polygon.java -- class representing a polygon
+ Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Line2D;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.io.Serializable;
+
+/**
+ * This class represents a polygon, a closed, two-dimensional region in a
+ * coordinate space. The region is bounded by an arbitrary number of line
+ * segments, between (x,y) coordinate vertices. The polygon has even-odd
+ * winding, meaning that a point is inside the shape if it crosses the
+ * boundary an odd number of times on the way to infinity.
+ *
+ * <p>There are some public fields; if you mess with them in an inconsistent
+ * manner, it is your own fault when you get NullPointerException,
+ * ArrayIndexOutOfBoundsException, or invalid results. Also, this class is
+ * not threadsafe.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public class Polygon implements Shape, Serializable
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -6460061437900069969L;
+
+ /**
+ * This total number of endpoints.
+ *
+ * @serial the number of endpoints, possibly less than the array sizes
+ */
+ public int npoints;
+
+ /**
+ * The array of X coordinates of endpoints. This should not be null.
+ *
+ * @see #addPoint(int, int)
+ * @serial the x coordinates
+ */
+ public int[] xpoints;
+
+ /**
+ * The array of Y coordinates of endpoints. This should not be null.
+ *
+ * @see #addPoint(int, int)
+ * @serial the y coordinates
+ */
+ public int[] ypoints;
+
+ /**
+ * The bounding box of this polygon. This is lazily created and cached, so
+ * it must be invalidated after changing points.
+ *
+ * @see #getBounds()
+ * @serial the bounding box, or null
+ */
+ protected Rectangle bounds;
+
+ /** A big number, but not so big it can't survive a few float operations */
+ private static final double BIG_VALUE = java.lang.Double.MAX_VALUE / 10.0;
+
+ /**
+ * Initializes an empty polygon.
+ */
+ public Polygon()
+ {
+ // Leave room for growth.
+ xpoints = new int[4];
+ ypoints = new int[4];
+ }
+
+ /**
+ * Create a new polygon with the specified endpoints. The arrays are copied,
+ * so that future modifications to the parameters do not affect the polygon.
+ *
+ * @param xpoints the array of X coordinates for this polygon
+ * @param ypoints the array of Y coordinates for this polygon
+ * @param npoints the total number of endpoints in this polygon
+ * @throws NegativeArraySizeException if npoints is negative
+ * @throws IndexOutOfBoundsException if npoints exceeds either array
+ * @throws NullPointerException if xpoints or ypoints is null
+ */
+ public Polygon(int[] xpoints, int[] ypoints, int npoints)
+ {
+ this.xpoints = new int[npoints];
+ this.ypoints = new int[npoints];
+ System.arraycopy(xpoints, 0, this.xpoints, 0, npoints);
+ System.arraycopy(ypoints, 0, this.ypoints, 0, npoints);
+ this.npoints = npoints;
+ }
+
+ /**
+ * Reset the polygon to be empty. The arrays are left alone, to avoid object
+ * allocation, but the number of points is set to 0, and all cached data
+ * is discarded. If you are discarding a huge number of points, it may be
+ * more efficient to just create a new Polygon.
+ *
+ * @see #invalidate()
+ * @since 1.4
+ */
+ public void reset()
+ {
+ npoints = 0;
+ invalidate();
+ }
+
+ /**
+ * Invalidate or flush all cached data. After direct manipulation of the
+ * public member fields, this is necessary to avoid inconsistent results
+ * in methods like <code>contains</code>.
+ *
+ * @see #getBounds()
+ * @since 1.4
+ */
+ public void invalidate()
+ {
+ bounds = null;
+ }
+
+ /**
+ * Translates the polygon by adding the specified values to all X and Y
+ * coordinates. This updates the bounding box, if it has been calculated.
+ *
+ * @param dx the amount to add to all X coordinates
+ * @param dy the amount to add to all Y coordinates
+ * @since 1.1
+ */
+ public void translate(int dx, int dy)
+ {
+ int i = npoints;
+ while (--i >= 0)
+ {
+ xpoints[i] += dx;
+ ypoints[i] += dy;
+ }
+ if (bounds != null)
+ {
+ bounds.x += dx;
+ bounds.y += dy;
+ }
+ }
+
+ /**
+ * Adds the specified endpoint to the polygon. This updates the bounding
+ * box, if it has been created.
+ *
+ * @param x the X coordinate of the point to add
+ * @param y the Y coordiante of the point to add
+ */
+ public void addPoint(int x, int y)
+ {
+ if (npoints + 1 > xpoints.length)
+ {
+ int[] newx = new int[npoints + 1];
+ System.arraycopy(xpoints, 0, newx, 0, npoints);
+ xpoints = newx;
+ }
+ if (npoints + 1 > ypoints.length)
+ {
+ int[] newy = new int[npoints + 1];
+ System.arraycopy(ypoints, 0, newy, 0, npoints);
+ ypoints = newy;
+ }
+ xpoints[npoints] = x;
+ ypoints[npoints] = y;
+ npoints++;
+ if (bounds != null)
+ {
+ if (npoints == 1)
+ {
+ bounds.x = x;
+ bounds.y = y;
+ }
+ else
+ {
+ if (x < bounds.x)
+ {
+ bounds.width += bounds.x - x;
+ bounds.x = x;
+ }
+ else if (x > bounds.x + bounds.width)
+ bounds.width = x - bounds.x;
+ if (y < bounds.y)
+ {
+ bounds.height += bounds.y - y;
+ bounds.y = y;
+ }
+ else if (y > bounds.y + bounds.height)
+ bounds.height = y - bounds.y;
+ }
+ }
+ }
+
+ /**
+ * Returns the bounding box of this polygon. This is the smallest
+ * rectangle with sides parallel to the X axis that will contain this
+ * polygon.
+ *
+ * @return the bounding box for this polygon
+ * @see #getBounds2D()
+ * @since 1.1
+ */
+ public Rectangle getBounds()
+ {
+ return getBoundingBox();
+ }
+
+ /**
+ * Returns the bounding box of this polygon. This is the smallest
+ * rectangle with sides parallel to the X axis that will contain this
+ * polygon.
+ *
+ * @return the bounding box for this polygon
+ * @see #getBounds2D()
+ * @deprecated use {@link #getBounds()} instead
+ */
+ public Rectangle getBoundingBox()
+ {
+ if (bounds == null)
+ {
+ if (npoints == 0)
+ return bounds = new Rectangle();
+ int i = npoints - 1;
+ int minx = xpoints[i];
+ int maxx = minx;
+ int miny = ypoints[i];
+ int maxy = miny;
+ while (--i >= 0)
+ {
+ int x = xpoints[i];
+ int y = ypoints[i];
+ if (x < minx)
+ minx = x;
+ else if (x > maxx)
+ maxx = x;
+ if (y < miny)
+ miny = y;
+ else if (y > maxy)
+ maxy = y;
+ }
+ bounds = new Rectangle(minx, miny, maxx - minx, maxy - miny);
+ }
+ return bounds;
+ }
+
+ /**
+ * Tests whether or not the specified point is inside this polygon.
+ *
+ * @param p the point to test
+ * @return true if the point is inside this polygon
+ * @throws NullPointerException if p is null
+ * @see #contains(double, double)
+ */
+ public boolean contains(Point p)
+ {
+ return contains(p.getX(), p.getY());
+ }
+
+ /**
+ * Tests whether or not the specified point is inside this polygon.
+ *
+ * @param x the X coordinate of the point to test
+ * @param y the Y coordinate of the point to test
+ * @return true if the point is inside this polygon
+ * @see #contains(double, double)
+ * @since 1.1
+ */
+ public boolean contains(int x, int y)
+ {
+ return contains((double) x, (double) y);
+ }
+
+ /**
+ * Tests whether or not the specified point is inside this polygon.
+ *
+ * @param x the X coordinate of the point to test
+ * @param y the Y coordinate of the point to test
+ * @return true if the point is inside this polygon
+ * @see #contains(double, double)
+ * @deprecated use {@link #contains(int, int)} instead
+ */
+ public boolean inside(int x, int y)
+ {
+ return contains((double) x, (double) y);
+ }
+
+ /**
+ * Returns a high-precision bounding box of this polygon. This is the
+ * smallest rectangle with sides parallel to the X axis that will contain
+ * this polygon.
+ *
+ * @return the bounding box for this polygon
+ * @see #getBounds()
+ * @since 1.2
+ */
+ public Rectangle2D getBounds2D()
+ {
+ // For polygons, the integer version is exact!
+ return getBounds();
+ }
+
+ /**
+ * Tests whether or not the specified point is inside this polygon.
+ *
+ * @param x the X coordinate of the point to test
+ * @param y the Y coordinate of the point to test
+ * @return true if the point is inside this polygon
+ * @since 1.2
+ */
+ public boolean contains(double x, double y)
+ {
+ return ((evaluateCrossings(x, y, false, BIG_VALUE) & 1) != 0);
+ }
+
+ /**
+ * Tests whether or not the specified point is inside this polygon.
+ *
+ * @param p the point to test
+ * @return true if the point is inside this polygon
+ * @throws NullPointerException if p is null
+ * @see #contains(double, double)
+ * @since 1.2
+ */
+ public boolean contains(Point2D p)
+ {
+ return contains(p.getX(), p.getY());
+ }
+
+ /**
+ * Test if a high-precision rectangle intersects the shape. This is true
+ * if any point in the rectangle is in the shape. This implementation is
+ * precise.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle, treated as point if negative
+ * @param h the height of the rectangle, treated as point if negative
+ * @return true if the rectangle intersects this shape
+ * @since 1.2
+ */
+ public boolean intersects(double x, double y, double w, double h)
+ {
+ /* Does any edge intersect? */
+ if (evaluateCrossings(x, y, false, w) != 0 /* top */
+ || evaluateCrossings(x, y + h, false, w) != 0 /* bottom */
+ || evaluateCrossings(x + w, y, true, h) != 0 /* right */
+ || evaluateCrossings(x, y, true, h) != 0) /* left */
+ return true;
+
+ /* No intersections, is any point inside? */
+ if ((evaluateCrossings(x, y, false, BIG_VALUE) & 1) != 0)
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Test if a high-precision rectangle intersects the shape. This is true
+ * if any point in the rectangle is in the shape. This implementation is
+ * precise.
+ *
+ * @param r the rectangle
+ * @return true if the rectangle intersects this shape
+ * @throws NullPointerException if r is null
+ * @see #intersects(double, double, double, double)
+ * @since 1.2
+ */
+ public boolean intersects(Rectangle2D r)
+ {
+ return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Test if a high-precision rectangle lies completely in the shape. This is
+ * true if all points in the rectangle are in the shape. This implementation
+ * is precise.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle, treated as point if negative
+ * @param h the height of the rectangle, treated as point if negative
+ * @return true if the rectangle is contained in this shape
+ * @since 1.2
+ */
+ public boolean contains(double x, double y, double w, double h)
+ {
+ if (! getBounds2D().intersects(x, y, w, h))
+ return false;
+
+ /* Does any edge intersect? */
+ if (evaluateCrossings(x, y, false, w) != 0 /* top */
+ || evaluateCrossings(x, y + h, false, w) != 0 /* bottom */
+ || evaluateCrossings(x + w, y, true, h) != 0 /* right */
+ || evaluateCrossings(x, y, true, h) != 0) /* left */
+ return false;
+
+ /* No intersections, is any point inside? */
+ if ((evaluateCrossings(x, y, false, BIG_VALUE) & 1) != 0)
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Test if a high-precision rectangle lies completely in the shape. This is
+ * true if all points in the rectangle are in the shape. This implementation
+ * is precise.
+ *
+ * @param r the rectangle
+ * @return true if the rectangle is contained in this shape
+ * @throws NullPointerException if r is null
+ * @see #contains(double, double, double, double)
+ * @since 1.2
+ */
+ public boolean contains(Rectangle2D r)
+ {
+ return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Return an iterator along the shape boundary. If the optional transform
+ * is provided, the iterator is transformed accordingly. Each call returns
+ * a new object, independent from others in use. This class is not
+ * threadsafe to begin with, so the path iterator is not either.
+ *
+ * @param transform an optional transform to apply to the iterator
+ * @return a new iterator over the boundary
+ * @since 1.2
+ */
+ public PathIterator getPathIterator(final AffineTransform transform)
+ {
+ return new PathIterator()
+ {
+ /** The current vertex of iteration. */
+ private int vertex;
+
+ public int getWindingRule()
+ {
+ return WIND_EVEN_ODD;
+ }
+
+ public boolean isDone()
+ {
+ return vertex > npoints;
+ }
+
+ public void next()
+ {
+ vertex++;
+ }
+
+ public int currentSegment(float[] coords)
+ {
+ if (vertex >= npoints)
+ return SEG_CLOSE;
+ coords[0] = xpoints[vertex];
+ coords[1] = ypoints[vertex];
+ if (transform != null)
+ transform.transform(coords, 0, coords, 0, 1);
+ return vertex == 0 ? SEG_MOVETO : SEG_LINETO;
+ }
+
+ public int currentSegment(double[] coords)
+ {
+ if (vertex >= npoints)
+ return SEG_CLOSE;
+ coords[0] = xpoints[vertex];
+ coords[1] = ypoints[vertex];
+ if (transform != null)
+ transform.transform(coords, 0, coords, 0, 1);
+ return vertex == 0 ? SEG_MOVETO : SEG_LINETO;
+ }
+ };
+ }
+
+ /**
+ * Return an iterator along the flattened version of the shape boundary.
+ * Since polygons are already flat, the flatness parameter is ignored, and
+ * the resulting iterator only has SEG_MOVETO, SEG_LINETO and SEG_CLOSE
+ * points. If the optional transform is provided, the iterator is
+ * transformed accordingly. Each call returns a new object, independent
+ * from others in use. This class is not threadsafe to begin with, so the
+ * path iterator is not either.
+ *
+ * @param transform an optional transform to apply to the iterator
+ * @param flatness the maximum distance for deviation from the real boundary
+ * @return a new iterator over the boundary
+ * @since 1.2
+ */
+ public PathIterator getPathIterator(AffineTransform transform,
+ double flatness)
+ {
+ return getPathIterator(transform);
+ }
+
+ /**
+ * Helper for contains, intersects, calculates the number of intersections
+ * between the polygon and a line extending from the point (x, y) along
+ * the positive X, or Y axis, within a given interval.
+ *
+ * @return the winding number.
+ * @see #contains(double, double)
+ */
+ private int evaluateCrossings(double x, double y, boolean useYaxis,
+ double distance)
+ {
+ double x0;
+ double x1;
+ double y0;
+ double y1;
+ double epsilon = 0.0;
+ int crossings = 0;
+ int[] xp;
+ int[] yp;
+
+ if (useYaxis)
+ {
+ xp = ypoints;
+ yp = xpoints;
+ double swap;
+ swap = y;
+ y = x;
+ x = swap;
+ }
+ else
+ {
+ xp = xpoints;
+ yp = ypoints;
+ }
+
+ /* Get a value which is small but not insignificant relative the path. */
+ epsilon = 1E-7;
+
+ x0 = xp[0] - x;
+ y0 = yp[0] - y;
+ for (int i = 1; i < npoints; i++)
+ {
+ x1 = xp[i] - x;
+ y1 = yp[i] - y;
+
+ if (y0 == 0.0)
+ y0 -= epsilon;
+ if (y1 == 0.0)
+ y1 -= epsilon;
+ if (y0 * y1 < 0)
+ if (Line2D.linesIntersect(x0, y0, x1, y1, epsilon, 0.0, distance, 0.0))
+ ++crossings;
+
+ x0 = xp[i] - x;
+ y0 = yp[i] - y;
+ }
+
+ // end segment
+ x1 = xp[0] - x;
+ y1 = yp[0] - y;
+ if (y0 == 0.0)
+ y0 -= epsilon;
+ if (y1 == 0.0)
+ y1 -= epsilon;
+ if (y0 * y1 < 0)
+ if (Line2D.linesIntersect(x0, y0, x1, y1, epsilon, 0.0, distance, 0.0))
+ ++crossings;
+
+ return crossings;
+ }
+} // class Polygon
diff --git a/libjava/classpath/java/awt/PopupMenu.java b/libjava/classpath/java/awt/PopupMenu.java
new file mode 100644
index 000000000..8595300f1
--- /dev/null
+++ b/libjava/classpath/java/awt/PopupMenu.java
@@ -0,0 +1,190 @@
+/* PopupMenu.java -- An AWT popup menu
+ Copyright (C) 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.peer.PopupMenuPeer;
+
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+
+/**
+ * This class implement an AWT popup menu widget
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class PopupMenu extends Menu
+{
+
+/*
+ * Static Variables
+ */
+
+ /**
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_popup_number;
+
+ // Serialization Constant
+ private static final long serialVersionUID = - 4620452533522760060L;
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * Initializes a new instance of <code>PopupMenu</code>.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true.
+ */
+public
+PopupMenu()
+{
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>PopupMenu</code> with the specified
+ * label.
+ *
+ * @param label The label for this popup menu.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true.
+ */
+public
+PopupMenu(String label)
+{
+ super(label);
+
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException ();
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Methods
+ */
+
+/**
+ * Creates this object's native peer.
+ */
+public void
+addNotify()
+{
+ if (peer == null)
+ peer = getToolkit ().createPopupMenu (this);
+ super.addNotify ();
+}
+
+/*************************************************************************/
+
+/**
+ * Displays this popup menu at the specified coordinates relative to
+ * the specified component.
+ *
+ * @param component The component to which the display coordinates are relative.
+ * @param x The X coordinate of the menu.
+ * @param y The Y coordinate of the menu.
+ */
+public void
+show(Component component, int x, int y)
+{
+ if (getPeer() == null)
+ this.addNotify();
+ PopupMenuPeer pmp = (PopupMenuPeer)getPeer();
+ if (pmp != null)
+ {
+ /* XXX
+ Event e = new Event (component, Event.ACTION_EVENT, component);
+ e.x = x;
+ e.y = y;*/
+ pmp.show (component, x, y);
+ }
+}
+
+ protected class AccessibleAWTPopupMenu extends AccessibleAWTMenu
+ {
+ private static final long serialVersionUID = -4282044795947239955L;
+
+ protected AccessibleAWTPopupMenu()
+ {
+ }
+
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.POPUP_MENU;
+ }
+
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>PopupMenu</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTPopupMenu();
+ return accessibleContext;
+ }
+
+ /**
+ * Generate a unique name for this <code>PopupMenu</code>.
+ *
+ * @return A unique name for this <code>PopupMenu</code>.
+ */
+ String generateName()
+ {
+ return "popup" + getUniqueLong();
+ }
+
+ private static synchronized long getUniqueLong()
+ {
+ return next_popup_number++;
+ }
+
+} // class PopupMenu
diff --git a/libjava/classpath/java/awt/PrintGraphics.java b/libjava/classpath/java/awt/PrintGraphics.java
new file mode 100644
index 000000000..e7f857797
--- /dev/null
+++ b/libjava/classpath/java/awt/PrintGraphics.java
@@ -0,0 +1,57 @@
+/* PrintGraphics.java -- a print graphics context
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This interface allows the originating print job to be obtained.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public interface PrintGraphics
+{
+ /**
+ * Returns the <code>PrintJob</code> that this object is being
+ * managed by.
+ *
+ * @return the print job for this object
+ */
+ PrintJob getPrintJob();
+} // interface PrintGraphics
diff --git a/libjava/classpath/java/awt/PrintJob.java b/libjava/classpath/java/awt/PrintJob.java
new file mode 100644
index 000000000..62aa8b195
--- /dev/null
+++ b/libjava/classpath/java/awt/PrintJob.java
@@ -0,0 +1,104 @@
+/* PrintJob.java -- A print job class
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.util.Properties;
+
+/**
+ * This abstract class represents a print job.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see Toolkit#getPrintJob(Frame, String, Properties)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public abstract class PrintJob
+{
+ /**
+ * Create a new PrintJob.
+ */
+ public PrintJob()
+ {
+ }
+
+ /**
+ * Returns a graphics context suitable for rendering the next page. The
+ * return must also implement {@link PrintGraphics}.
+ *
+ * @return a graphics context for printing the next page
+ */
+ public abstract Graphics getGraphics();
+
+ /**
+ * Returns the dimension of the page in pixels. The resolution will be
+ * chosen to be similar to the on screen image.
+ *
+ * @return the page dimensions
+ */
+ public abstract Dimension getPageDimension();
+
+ /**
+ * Returns the resolution of the page in pixels per inch. Note that this is
+ * not necessarily the printer's resolution.
+ *
+ * @return the resolution of the page in pixels per inch
+ */
+ public abstract int getPageResolution();
+
+ /**
+ * Tests whether or not the last page will be printed first.
+ *
+ * @return true if the last page prints first
+ */
+ public abstract boolean lastPageFirst();
+
+ /**
+ * Informs the print job that printing is complete or should be aborted.
+ */
+ public abstract void end();
+
+ /**
+ * This method explicitly ends the print job in the event the job
+ * becomes un-referenced without the application having done so.
+ */
+ public void finalize()
+ {
+ end();
+ }
+} // class PrintJob
diff --git a/libjava/classpath/java/awt/Rectangle.java b/libjava/classpath/java/awt/Rectangle.java
new file mode 100644
index 000000000..1d5a8da07
--- /dev/null
+++ b/libjava/classpath/java/awt/Rectangle.java
@@ -0,0 +1,753 @@
+/* Rectangle.java -- represents a graphics rectangle
+ Copyright (C) 1999, 2000, 2001, 2002, 2006, Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.geom.Rectangle2D;
+import java.io.Serializable;
+
+/**
+ * This class represents a rectangle and all the interesting things you
+ * might want to do with it. Note that the coordinate system uses
+ * the origin (0,0) as the top left of the screen, with the x and y
+ * values increasing as they move to the right and down respectively.
+ *
+ * <p>It is valid for a rectangle to have negative width or height; but it
+ * is considered to have no area or internal points. Therefore, the behavior
+ * in methods like <code>contains</code> or <code>intersects</code> is
+ * undefined unless the rectangle has positive width and height.
+ *
+ * <p>There are some public fields; if you mess with them in an inconsistent
+ * manner, it is your own fault when you get NullPointerException,
+ * ArrayIndexOutOfBoundsException, or invalid results. Also, this class is
+ * not threadsafe.
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public class Rectangle extends Rectangle2D implements Shape, Serializable
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -4345857070255674764L;
+
+ /**
+ * The X coordinate of the top-left corner of the rectangle.
+ *
+ * @see #setLocation(int, int)
+ * @see #getLocation()
+ * @serial the x coordinate
+ */
+ public int x;
+
+ /**
+ * The Y coordinate of the top-left corner of the rectangle.
+ *
+ * @see #setLocation(int, int)
+ * @see #getLocation()
+ * @serial the y coordinate
+ */
+ public int y;
+
+ /**
+ * The width of the rectangle.
+ *
+ * @see #setSize(int, int)
+ * @see #getSize()
+ * @serial
+ */
+ public int width;
+
+ /**
+ * The height of the rectangle.
+ *
+ * @see #setSize(int, int)
+ * @see #getSize()
+ * @serial
+ */
+ public int height;
+
+ /**
+ * Initializes a new instance of <code>Rectangle</code> with a top
+ * left corner at (0,0) and a width and height of 0.
+ */
+ public Rectangle()
+ {
+ }
+
+ /**
+ * Initializes a new instance of <code>Rectangle</code> from the
+ * coordinates of the specified rectangle.
+ *
+ * @param r the rectangle to copy from
+ * @since 1.1
+ */
+ public Rectangle(Rectangle r)
+ {
+ x = r.x;
+ y = r.y;
+ width = r.width;
+ height = r.height;
+ }
+
+ /**
+ * Initializes a new instance of <code>Rectangle</code> from the specified
+ * inputs.
+ *
+ * @param x the X coordinate of the top left corner
+ * @param y the Y coordinate of the top left corner
+ * @param width the width of the rectangle
+ * @param height the height of the rectangle
+ */
+ public Rectangle(int x, int y, int width, int height)
+ {
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ }
+
+ /**
+ * Initializes a new instance of <code>Rectangle</code> with the specified
+ * width and height. The upper left corner of the rectangle will be at
+ * the origin (0,0).
+ *
+ * @param width the width of the rectangle
+ * @param height the height of the rectange
+ */
+ public Rectangle(int width, int height)
+ {
+ this.width = width;
+ this.height = height;
+ }
+
+ /**
+ * Initializes a new instance of <code>Rectangle</code> with a top-left
+ * corner represented by the specified point and the width and height
+ * represented by the specified dimension.
+ *
+ * @param p the upper left corner of the rectangle
+ * @param d the width and height of the rectangle
+ */
+ public Rectangle(Point p, Dimension d)
+ {
+ x = p.x;
+ y = p.y;
+ width = d.width;
+ height = d.height;
+ }
+
+ /**
+ * Initializes a new instance of <code>Rectangle</code> with a top left
+ * corner at the specified point and a width and height of zero.
+ *
+ * @param p the upper left corner of the rectangle
+ */
+ public Rectangle(Point p)
+ {
+ x = p.x;
+ y = p.y;
+ }
+
+ /**
+ * Initializes a new instance of <code>Rectangle</code> with an
+ * upper left corner at the origin (0,0) and a width and height represented
+ * by the specified dimension.
+ *
+ * @param d the width and height of the rectangle
+ */
+ public Rectangle(Dimension d)
+ {
+ width = d.width;
+ height = d.height;
+ }
+
+ /**
+ * Get the X coordinate of the upper-left corner.
+ *
+ * @return the value of x, as a double
+ */
+ public double getX()
+ {
+ return x;
+ }
+
+ /**
+ * Get the Y coordinate of the upper-left corner.
+ *
+ * @return the value of y, as a double
+ */
+ public double getY()
+ {
+ return y;
+ }
+
+ /**
+ * Get the width of the rectangle.
+ *
+ * @return the value of width, as a double
+ */
+ public double getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Get the height of the rectangle.
+ *
+ * @return the value of height, as a double
+ */
+ public double getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * Returns the bounds of this rectangle. A pretty useless method, as this
+ * is already a rectangle; it is included to mimic the
+ * <code>getBounds</code> method in Component.
+ *
+ * @return a copy of this rectangle
+ * @see #setBounds(Rectangle)
+ * @since 1.1
+ */
+ public Rectangle getBounds()
+ {
+ return new Rectangle(this);
+ }
+
+ /**
+ * Returns the high-precision bounds of this rectangle. A pretty useless
+ * method, as this is already a rectangle.
+ *
+ * @return a copy of this rectangle
+ * @see #setBounds(Rectangle)
+ * @since 1.2
+ */
+ public Rectangle2D getBounds2D()
+ {
+ return new Rectangle(x, y, width, height);
+ }
+
+ /**
+ * Updates this rectangle to match the dimensions of the specified
+ * rectangle.
+ *
+ * @param r the rectangle to update from
+ * @throws NullPointerException if r is null
+ * @see #setBounds(int, int, int, int)
+ * @since 1.1
+ */
+ public void setBounds(Rectangle r)
+ {
+ setBounds (r.x, r.y, r.width, r.height);
+ }
+
+ /**
+ * Updates this rectangle to have the specified dimensions.
+ *
+ * @param x the new X coordinate of the upper left hand corner
+ * @param y the new Y coordinate of the upper left hand corner
+ * @param width the new width of this rectangle
+ * @param height the new height of this rectangle
+ * @since 1.1
+ */
+ public void setBounds(int x, int y, int width, int height)
+ {
+ reshape (x, y, width, height);
+ }
+
+ /**
+ * Updates this rectangle to have the specified dimensions, rounded to the
+ * integer precision used by this class (the values are rounded "outwards" so
+ * that the stored rectangle completely encloses the specified double
+ * precision rectangle).
+ *
+ * @param x the new X coordinate of the upper left hand corner
+ * @param y the new Y coordinate of the upper left hand corner
+ * @param width the new width of this rectangle
+ * @param height the new height of this rectangle
+ * @since 1.2
+ */
+ public void setRect(double x, double y, double width, double height)
+ {
+ this.x = (int) Math.floor(x);
+ this.y = (int) Math.floor(y);
+ this.width = (int) Math.ceil(x + width) - this.x;
+ this.height = (int) Math.ceil(y + height) - this.y;
+ }
+
+ /**
+ * Updates this rectangle to have the specified dimensions.
+ *
+ * @param x the new X coordinate of the upper left hand corner
+ * @param y the new Y coordinate of the upper left hand corner
+ * @param width the new width of this rectangle
+ * @param height the new height of this rectangle
+ * @deprecated use {@link #setBounds(int, int, int, int)} instead
+ */
+ public void reshape(int x, int y, int width, int height)
+ {
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ }
+
+ /**
+ * Returns the location of this rectangle, which is the coordinates of
+ * its upper left corner.
+ *
+ * @return the point where this rectangle is located
+ * @see #setLocation(Point)
+ * @since 1.1
+ */
+ public Point getLocation()
+ {
+ return new Point(x,y);
+ }
+
+ /**
+ * Moves the location of this rectangle by setting its upper left
+ * corner to the specified point.
+ *
+ * @param p the point to move the rectangle to
+ * @throws NullPointerException if p is null
+ * @see #getLocation()
+ * @since 1.1
+ */
+ public void setLocation(Point p)
+ {
+ setLocation (p.x, p.y);
+ }
+
+ /**
+ * Moves the location of this rectangle by setting its upper left
+ * corner to the specified coordinates.
+ *
+ * @param x the new X coordinate for this rectangle
+ * @param y the new Y coordinate for this rectangle
+ * @since 1.1
+ */
+ public void setLocation(int x, int y)
+ {
+ move (x, y);
+ }
+
+ /**
+ * Moves the location of this rectangle by setting its upper left
+ * corner to the specified coordinates.
+ *
+ * @param x the new X coordinate for this rectangle
+ * @param y the new Y coordinate for this rectangle
+ * @deprecated use {@link #setLocation(int, int)} instead
+ */
+ public void move(int x, int y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ * Translate the location of this rectangle by the given amounts.
+ *
+ * @param dx the x distance to move by
+ * @param dy the y distance to move by
+ * @see #setLocation(int, int)
+ */
+ public void translate(int dx, int dy)
+ {
+ x += dx;
+ y += dy;
+ }
+
+ /**
+ * Returns the size of this rectangle.
+ *
+ * @return the size of this rectangle
+ * @see #setSize(Dimension)
+ * @since 1.1
+ */
+ public Dimension getSize()
+ {
+ return new Dimension(width, height);
+ }
+
+ /**
+ * Sets the size of this rectangle based on the specified dimensions.
+ *
+ * @param d the new dimensions of the rectangle
+ * @throws NullPointerException if d is null
+ * @see #getSize()
+ * @since 1.1
+ */
+ public void setSize(Dimension d)
+ {
+ setSize (d.width, d.height);
+ }
+
+ /**
+ * Sets the size of this rectangle based on the specified dimensions.
+ *
+ * @param width the new width of the rectangle
+ * @param height the new height of the rectangle
+ * @since 1.1
+ */
+ public void setSize(int width, int height)
+ {
+ resize (width, height);
+ }
+
+ /**
+ * Sets the size of this rectangle based on the specified dimensions.
+ *
+ * @param width the new width of the rectangle
+ * @param height the new height of the rectangle
+ * @deprecated use {@link #setSize(int, int)} instead
+ */
+ public void resize(int width, int height)
+ {
+ this.width = width;
+ this.height = height;
+ }
+
+ /**
+ * Tests whether or not the specified point is inside this rectangle.
+ * According to the contract of Shape, a point on the border is in only if
+ * it has an adjacent point inside the rectangle in either the increasing
+ * x or y direction.
+ *
+ * @param p the point to test
+ * @return true if the point is inside the rectangle
+ * @throws NullPointerException if p is null
+ * @see #contains(int, int)
+ * @since 1.1
+ */
+ public boolean contains(Point p)
+ {
+ return contains (p.x, p.y);
+ }
+
+ /**
+ * Tests whether or not the specified point is inside this rectangle.
+ * According to the contract of Shape, a point on the border is in only if
+ * it has an adjacent point inside the rectangle in either the increasing
+ * x or y direction.
+ *
+ * @param x the X coordinate of the point to test
+ * @param y the Y coordinate of the point to test
+ * @return true if the point is inside the rectangle
+ * @since 1.1
+ */
+ public boolean contains(int x, int y)
+ {
+ return inside (x, y);
+ }
+
+ /**
+ * Checks whether all points in the given rectangle are contained in this
+ * rectangle.
+ *
+ * @param r the rectangle to check
+ * @return true if r is contained in this rectangle
+ * @throws NullPointerException if r is null
+ * @see #contains(int, int, int, int)
+ * @since 1.1
+ */
+ public boolean contains(Rectangle r)
+ {
+ return contains (r.x, r.y, r.width, r.height);
+ }
+
+ /**
+ * Checks whether all points in the given rectangle are contained in this
+ * rectangle.
+ *
+ * @param x the x coordinate of the rectangle to check
+ * @param y the y coordinate of the rectangle to check
+ * @param w the width of the rectangle to check
+ * @param h the height of the rectangle to check
+ * @return true if the parameters are contained in this rectangle
+ * @since 1.1
+ */
+ public boolean contains(int x, int y, int w, int h)
+ {
+ return width > 0 && height > 0 && w > 0 && h > 0
+ && x >= this.x && x + w <= this.x + this.width
+ && y >= this.y && y + h <= this.y + this.height;
+ }
+
+ /**
+ * Tests whether or not the specified point is inside this rectangle.
+ *
+ * @param x the X coordinate of the point to test
+ * @param y the Y coordinate of the point to test
+ * @return true if the point is inside the rectangle
+ * @deprecated use {@link #contains(int, int)} instead
+ */
+ public boolean inside(int x, int y)
+ {
+ return width > 0 && height > 0
+ && x >= this.x && x < this.x + width
+ && y >= this.y && y < this.y + height;
+ }
+
+ /**
+ * Tests whether or not the specified rectangle intersects this rectangle.
+ * This means the two rectangles share at least one internal point.
+ *
+ * @param r the rectangle to test against
+ * @return true if the specified rectangle intersects this one
+ * @throws NullPointerException if r is null
+ * @since 1.2
+ */
+ public boolean intersects(Rectangle r)
+ {
+ return r.width > 0 && r.height > 0 && width > 0 && height > 0
+ && r.x < x + width && r.x + r.width > x
+ && r.y < y + height && r.y + r.height > y;
+ }
+
+ /**
+ * Determines the rectangle which is formed by the intersection of this
+ * rectangle with the specified rectangle. If the two do not intersect,
+ * an empty rectangle will be returned (meaning the width and/or height
+ * will be non-positive).
+ *
+ * @param r the rectange to calculate the intersection with
+ * @return a new rectangle bounding the intersection
+ * @throws NullPointerException if r is null
+ */
+ public Rectangle intersection(Rectangle r)
+ {
+ Rectangle res = new Rectangle();
+ intersect(this, r, res);
+ return res;
+ }
+
+ /**
+ * Returns the smallest rectangle that contains both this rectangle
+ * and the specified rectangle.
+ *
+ * @param r the rectangle to compute the union with
+ * @return the smallest rectangle containing both rectangles
+ * @throws NullPointerException if r is null
+ */
+ public Rectangle union(Rectangle r)
+ {
+ Rectangle res = new Rectangle();
+ union(this, r, res);
+ return res;
+ }
+
+ /**
+ * Modifies this rectangle so that it represents the smallest rectangle
+ * that contains both the existing rectangle and the specified point.
+ * However, if the point falls on one of the two borders which are not
+ * inside the rectangle, a subsequent call to <code>contains</code> may
+ * return false.
+ *
+ * @param x the X coordinate of the point to add to this rectangle
+ * @param y the Y coordinate of the point to add to this rectangle
+ */
+ public void add(int x, int y)
+ {
+ add((double) x, (double) y);
+ }
+
+ /**
+ * Modifies this rectangle so that it represents the smallest rectangle
+ * that contains both the existing rectangle and the specified point.
+ * However, if the point falls on one of the two borders which are not
+ * inside the rectangle, a subsequent call to <code>contains</code> may
+ * return false.
+ *
+ * @param p the point to add to this rectangle
+ * @throws NullPointerException if p is null
+ */
+ public void add(Point p)
+ {
+ add((double) p.x, (double) p.y);
+ }
+
+ /**
+ * Modifies this rectangle so that it represents the smallest rectangle
+ * that contains both the existing rectangle and the specified rectangle.
+ *
+ * @param r the rectangle to add to this rectangle
+ * @throws NullPointerException if r is null
+ * @see #union(Rectangle)
+ */
+ public void add(Rectangle r)
+ {
+ union(this, r, this);
+ }
+
+ /**
+ * Expands the rectangle by the specified amount. The horizontal
+ * and vertical expansion values are applied both to the X,Y coordinate
+ * of this rectangle, and its width and height. Thus the width and
+ * height will increase by 2h and 2v accordingly.
+ *
+ * @param h the horizontal expansion value
+ * @param v the vertical expansion value
+ */
+ public void grow(int h, int v)
+ {
+ x -= h;
+ y -= v;
+ width += h + h;
+ height += v + v;
+ }
+
+ /**
+ * Tests whether or not this rectangle is empty. An empty rectangle
+ * has a non-positive width or height.
+ *
+ * @return true if the rectangle is empty
+ */
+ public boolean isEmpty()
+ {
+ return width <= 0 || height <= 0;
+ }
+
+ /**
+ * Determine where the point lies with respect to this rectangle. The
+ * result will be the binary OR of the appropriate bit masks.
+ *
+ * @param x the x coordinate to check
+ * @param y the y coordinate to check
+ * @return the binary OR of the result
+ * @see #OUT_LEFT
+ * @see #OUT_TOP
+ * @see #OUT_RIGHT
+ * @see #OUT_BOTTOM
+ * @since 1.2
+ */
+ public int outcode(double x, double y)
+ {
+ int result = 0;
+ if (width <= 0)
+ result |= OUT_LEFT | OUT_RIGHT;
+ else if (x < this.x)
+ result |= OUT_LEFT;
+ else if (x > this.x + width)
+ result |= OUT_RIGHT;
+ if (height <= 0)
+ result |= OUT_BOTTOM | OUT_TOP;
+ else if (y < this.y) // Remember that +y heads top-to-bottom.
+ result |= OUT_TOP;
+ else if (y > this.y + height)
+ result |= OUT_BOTTOM;
+ return result;
+ }
+
+ /**
+ * Determines the rectangle which is formed by the intersection of this
+ * rectangle with the specified rectangle. If the two do not intersect,
+ * an empty rectangle will be returned (meaning the width and/or height
+ * will be non-positive).
+ *
+ * @param r the rectange to calculate the intersection with
+ * @return a new rectangle bounding the intersection
+ * @throws NullPointerException if r is null
+ * @since 1.2
+ */
+ public Rectangle2D createIntersection(Rectangle2D r)
+ {
+ // Favor runtime type of other rectangle.
+ Rectangle2D res = r.getBounds2D();
+ intersect(this, r, res);
+ return res;
+ }
+
+ /**
+ * Returns the smallest rectangle that contains both this rectangle
+ * and the specified rectangle.
+ *
+ * @param r the rectangle to compute the union with
+ * @return the smallest rectangle containing both rectangles
+ * @throws NullPointerException if r is null
+ * @since 1.2
+ */
+ public Rectangle2D createUnion(Rectangle2D r)
+ {
+ // Favor runtime type of other rectangle.
+ Rectangle2D res = r.getBounds2D();
+ union(this, r, res);
+ return res;
+ }
+
+ /**
+ * Tests this rectangle for equality against the specified object. This
+ * will be true if an only if the specified object is an instance of
+ * Rectangle2D with the same coordinates and dimensions.
+ *
+ * @param obj the object to test against for equality
+ * @return true if the specified object is equal to this one
+ */
+ public boolean equals(Object obj)
+ {
+ // NOTE: No special hashCode() method is required for this class,
+ // as this equals() implementation is functionally equivalent to
+ // super.equals(), which does define a proper hashCode().
+
+ if (! (obj instanceof Rectangle2D))
+ return false;
+ Rectangle2D r = (Rectangle2D) obj;
+ return r.getX() == x && r.getY() == y
+ && r.getWidth() == width && r.getHeight() == height;
+ }
+
+ /**
+ * Returns a string representation of this rectangle. This is in the form
+ * <code>getClass().getName() + "[x=" + x + ",y=" + y + ",width=" + width
+ * + ",height=" + height + ']'</code>.
+ *
+ * @return a string representation of this rectangle
+ */
+ public String toString()
+ {
+ return getClass().getName() + "[x=" + x + ",y=" + y + ",width=" + width
+ + ",height=" + height + ']';
+ }
+} // class Rectangle
diff --git a/libjava/classpath/java/awt/RenderingHints.java b/libjava/classpath/java/awt/RenderingHints.java
new file mode 100644
index 000000000..5de6a608f
--- /dev/null
+++ b/libjava/classpath/java/awt/RenderingHints.java
@@ -0,0 +1,804 @@
+/* RenderingHints.java --
+ Copyright (C) 2000, 2001, 2002, 2004, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A collection of (key, value) items that provide 'hints' for the
+ * {@link java.awt.Graphics2D} rendering pipeline. Because these
+ * items are hints only, they may be ignored by a particular
+ * {@link java.awt.Graphics2D} implementation.
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+public class RenderingHints
+ implements Map<Object,Object>, Cloneable
+{
+ /**
+ * The base class used to represent keys.
+ */
+ public abstract static class Key
+ {
+ private final int key;
+
+ /**
+ * Creates a new key.
+ *
+ * @param privateKey the private key.
+ */
+ protected Key(int privateKey)
+ {
+ key = privateKey;
+ }
+
+ /**
+ * Returns <code>true</code> if the specified value is compatible with
+ * this key, and <code>false</code> otherwise.
+ *
+ * @param value the value (<code>null</code> permitted).
+ *
+ * @return A boolean.
+ */
+ public abstract boolean isCompatibleValue(Object value);
+
+ /**
+ * Returns the private key for this instance.
+ *
+ * @return The private key.
+ */
+ protected final int intKey()
+ {
+ return key;
+ }
+
+ /**
+ * Returns a hash code for the key.
+ *
+ * @return A hash code.
+ */
+ public final int hashCode()
+ {
+ return System.identityHashCode(this);
+ }
+
+ /**
+ * Checks this key for equality with an arbitrary object.
+ *
+ * @param other the object (<code>null</code> permitted)
+ *
+ * @return A boolean.
+ */
+ public final boolean equals(Object other)
+ {
+ return this == other;
+ }
+ } // class Key
+
+ private static final class KeyImpl extends Key
+ {
+ final String description;
+ final Object v1;
+ final Object v2;
+ final Object v3;
+
+ KeyImpl(int privateKey, String description,
+ Object v1, Object v2, Object v3)
+ {
+ super(privateKey);
+ this.description = description;
+ this.v1 = v1;
+ this.v2 = v2;
+ this.v3 = v3;
+ }
+
+ /**
+ * Returns <code>true</code> if the specified value is compatible with
+ * this key, and <code>false</code> otherwise.
+ *
+ * @param value the value (<code>null</code> permitted).
+ *
+ * @return A boolean.
+ */
+ public boolean isCompatibleValue(Object value)
+ {
+ return value == v1 || value == v2 || value == v3;
+ }
+
+ /**
+ * Returns a string representation of the key.
+ *
+ * @return A string.
+ */
+ public String toString()
+ {
+ return description;
+ }
+ } // class KeyImpl
+
+ private HashMap<Object,Object> hintMap = new HashMap<Object,Object>();
+
+ /**
+ * A key for the 'antialiasing' hint. Permitted values are:
+ * <p>
+ * <table>
+ * <tr>
+ * <td>{@link #VALUE_ANTIALIAS_OFF}</td>
+ * <td>Render without antialiasing (better speed).</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_ANTIALIAS_ON}</td>
+ * <td>Render with antialiasing (better quality).</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_ANTIALIAS_DEFAULT}</td>
+ * <td>Use the default value for antialiasing.</td>
+ * </tr>
+ * </table>
+ */
+ public static final Key KEY_ANTIALIASING;
+
+ /**
+ * This value is for use with the {@link #KEY_ANTIALIASING} key.
+ */
+ public static final Object VALUE_ANTIALIAS_ON
+ = "Antialiased rendering mode";
+
+ /**
+ * This value is for use with the {@link #KEY_ANTIALIASING} key.
+ */
+ public static final Object VALUE_ANTIALIAS_OFF
+ = "Nonantialiased rendering mode";
+
+ /**
+ * This value is for use with the {@link #KEY_ANTIALIASING} key.
+ */
+ public static final Object VALUE_ANTIALIAS_DEFAULT
+ = "Default antialiasing rendering mode";
+
+ /**
+ * A key for the 'rendering' hint. Permitted values are:
+ * <p>
+ * <table>
+ * <tr>
+ * <td>{@link #VALUE_RENDER_SPEED}</td>
+ * <td>Prefer speed over quality when rendering.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_RENDER_QUALITY}</td>
+ * <td>Prefer quality over speed when rendering.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_RENDER_DEFAULT}</td>
+ * <td>Use the default value for quality vs. speed when rendering.</td>
+ * </tr>
+ * </table>
+ */
+ public static final Key KEY_RENDERING;
+
+ /**
+ * This value is for use with the {@link #KEY_RENDERING} key.
+ */
+ public static final Object VALUE_RENDER_SPEED
+ = "Fastest rendering methods";
+
+ /**
+ * This value is for use with the {@link #KEY_RENDERING} key.
+ */
+ public static final Object VALUE_RENDER_QUALITY
+ = "Highest quality rendering methods";
+
+ /**
+ * This value is for use with the {@link #KEY_RENDERING} key.
+ */
+ public static final Object VALUE_RENDER_DEFAULT
+ = "Default rendering methods";
+
+ /**
+ * A key for the 'dithering' hint. Permitted values are:
+ * <p>
+ * <table>
+ * <tr>
+ * <td>{@link #VALUE_DITHER_DISABLE}</td>
+ * <td>Disable dithering.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_DITHER_ENABLE}</td>
+ * <td>Enable dithering.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_DITHER_DEFAULT}</td>
+ * <td>Use the default value for dithering.</td>
+ * </tr>
+ * </table>
+ */
+ public static final Key KEY_DITHERING;
+
+ /**
+ * This value is for use with the {@link #KEY_DITHERING} key.
+ */
+ public static final Object VALUE_DITHER_DISABLE
+ = "Nondithered rendering mode";
+
+ /**
+ * This value is for use with the {@link #KEY_DITHERING} key.
+ */
+ public static final Object VALUE_DITHER_ENABLE
+ = "Dithered rendering mode";
+
+ /**
+ * This value is for use with the {@link #KEY_DITHERING} key.
+ */
+ public static final Object VALUE_DITHER_DEFAULT
+ = "Default dithering mode";
+
+ /**
+ * A key for the 'text antialiasing' hint. Permitted values are:
+ * <p>
+ * <table>
+ * <tr>
+ * <td>{@link #VALUE_TEXT_ANTIALIAS_ON}</td>
+ * <td>Render text with antialiasing (better quality usually).</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_TEXT_ANTIALIAS_OFF}</td>
+ * <td>Render test without antialiasing (better speed).</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_TEXT_ANTIALIAS_DEFAULT}</td>
+ * <td>Use the default value for text antialiasing.</td>
+ * </tr>
+ * </table>
+ */
+ public static final Key KEY_TEXT_ANTIALIASING;
+
+ /**
+ * This value is for use with the {@link #KEY_TEXT_ANTIALIASING} key.
+ */
+ public static final Object VALUE_TEXT_ANTIALIAS_ON
+ = "Antialiased text mode";
+
+ /**
+ * This value is for use with the {@link #KEY_TEXT_ANTIALIASING} key.
+ */
+ public static final Object VALUE_TEXT_ANTIALIAS_OFF
+ = "Nonantialiased text mode";
+
+ /**
+ * This value is for use with the {@link #KEY_TEXT_ANTIALIASING} key.
+ */
+ public static final Object VALUE_TEXT_ANTIALIAS_DEFAULT
+ = "Default antialiasing text mode";
+
+ /**
+ * A key for the 'fractional metrics' hint. Permitted values are:
+ * <p>
+ * <table>
+ * <tr>
+ * <td>{@link #VALUE_FRACTIONALMETRICS_OFF}</td>
+ * <td>Render text with fractional metrics off.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_FRACTIONALMETRICS_ON}</td>
+ * <td>Render text with fractional metrics on.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_FRACTIONALMETRICS_DEFAULT}</td>
+ * <td>Use the default value for fractional metrics.</td>
+ * </tr>
+ * </table>
+ */
+ public static final Key KEY_FRACTIONALMETRICS;
+
+ /**
+ * This value is for use with the {@link #KEY_FRACTIONALMETRICS} key.
+ */
+ public static final Object VALUE_FRACTIONALMETRICS_OFF
+ = "Integer text metrics mode";
+
+ /**
+ * This value is for use with the {@link #KEY_FRACTIONALMETRICS} key.
+ */
+ public static final Object VALUE_FRACTIONALMETRICS_ON
+ = "Fractional text metrics mode";
+
+ /**
+ * This value is for use with the {@link #KEY_FRACTIONALMETRICS} key.
+ */
+ public static final Object VALUE_FRACTIONALMETRICS_DEFAULT
+ = "Default fractional text metrics mode";
+
+ /**
+ * A key for the 'interpolation' hint. Permitted values are:
+ * <p>
+ * <table>
+ * <tr>
+ * <td>{@link #VALUE_INTERPOLATION_NEAREST_NEIGHBOR}</td>
+ * <td>Use nearest neighbour interpolation.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_INTERPOLATION_BILINEAR}</td>
+ * <td>Use bilinear interpolation.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_INTERPOLATION_BICUBIC}</td>
+ * <td>Use bicubic interpolation.</td>
+ * </tr>
+ * </table>
+ */
+ public static final Key KEY_INTERPOLATION;
+
+ /**
+ * This value is for use with the {@link #KEY_INTERPOLATION} key.
+ */
+ public static final Object VALUE_INTERPOLATION_NEAREST_NEIGHBOR
+ = "Nearest Neighbor image interpolation mode";
+
+ /**
+ * This value is for use with the {@link #KEY_INTERPOLATION} key.
+ */
+ public static final Object VALUE_INTERPOLATION_BILINEAR
+ = "Bilinear image interpolation mode";
+
+ /**
+ * This value is for use with the {@link #KEY_INTERPOLATION} key.
+ */
+ public static final Object VALUE_INTERPOLATION_BICUBIC
+ = "Bicubic image interpolation mode";
+
+ /**
+ * A key for the 'alpha interpolation' hint. Permitted values are:
+ * <p>
+ * <table>
+ * <tr>
+ * <td>{@link #VALUE_ALPHA_INTERPOLATION_SPEED}</td>
+ * <td>Prefer speed over quality.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_ALPHA_INTERPOLATION_QUALITY}</td>
+ * <td>Prefer quality over speed.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_ALPHA_INTERPOLATION_DEFAULT}</td>
+ * <td>Use the default setting.</td>
+ * </tr>
+ * </table>
+ */
+ public static final Key KEY_ALPHA_INTERPOLATION;
+
+ /**
+ * This value is for use with the {@link #KEY_ALPHA_INTERPOLATION} key.
+ */
+ public static final Object VALUE_ALPHA_INTERPOLATION_SPEED
+ = "Fastest alpha blending methods";
+
+ /**
+ * This value is for use with the {@link #KEY_ALPHA_INTERPOLATION} key.
+ */
+ public static final Object VALUE_ALPHA_INTERPOLATION_QUALITY
+ = "Highest quality alpha blending methods";
+
+ /**
+ * This value is for use with the {@link #KEY_ALPHA_INTERPOLATION} key.
+ */
+ public static final Object VALUE_ALPHA_INTERPOLATION_DEFAULT
+ = "Default alpha blending methods";
+
+ /**
+ * A key for the 'color rendering' hint. Permitted values are:
+ * <p>
+ * <table>
+ * <tr>
+ * <td>{@link #VALUE_COLOR_RENDER_SPEED}</td>
+ * <td>Prefer speed over quality.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_COLOR_RENDER_QUALITY}</td>
+ * <td>Prefer quality over speed.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_COLOR_RENDER_DEFAULT}</td>
+ * <td>Use the default setting.</td>
+ * </tr>
+ * </table>
+ */
+ public static final Key KEY_COLOR_RENDERING;
+
+ /**
+ * This value is for use with the {@link #KEY_COLOR_RENDERING} key.
+ */
+ public static final Object VALUE_COLOR_RENDER_SPEED
+ = "Fastest color rendering mode";
+
+ /**
+ * This value is for use with the {@link #KEY_COLOR_RENDERING} key.
+ */
+ public static final Object VALUE_COLOR_RENDER_QUALITY
+ = "Highest quality color rendering mode";
+
+ /**
+ * This value is for use with the {@link #KEY_COLOR_RENDERING} key.
+ */
+ public static final Object VALUE_COLOR_RENDER_DEFAULT
+ = "Default color rendering mode";
+
+ /**
+ * A key for the 'stroke control' hint. Permitted values are:
+ * <p>
+ * <table>
+ * <tr>
+ * <td>{@link #VALUE_STROKE_DEFAULT}</td>
+ * <td>Use the default setting.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_STROKE_NORMALIZE}</td>
+ * <td>XXX</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #VALUE_STROKE_PURE}</td>
+ * <td>XXX</td>
+ * </tr>
+ * </table>
+ */
+ public static final Key KEY_STROKE_CONTROL;
+
+ /**
+ * This value is for use with the {@link #KEY_STROKE_CONTROL} key.
+ */
+ public static final Object VALUE_STROKE_DEFAULT
+ = "Default stroke normalization";
+
+ /**
+ * This value is for use with the {@link #KEY_STROKE_CONTROL} key.
+ */
+ public static final Object VALUE_STROKE_NORMALIZE
+ = "Normalize strokes for consistent rendering";
+
+ /**
+ * This value is for use with the {@link #KEY_STROKE_CONTROL} key.
+ */
+ public static final Object VALUE_STROKE_PURE
+ = "Pure stroke conversion for accurate paths";
+
+ static
+ {
+ KEY_ANTIALIASING = new KeyImpl(1, "Global antialiasing enable key",
+ VALUE_ANTIALIAS_ON,
+ VALUE_ANTIALIAS_OFF,
+ VALUE_ANTIALIAS_DEFAULT);
+ KEY_RENDERING = new KeyImpl(2, "Global rendering quality key",
+ VALUE_RENDER_SPEED,
+ VALUE_RENDER_QUALITY,
+ VALUE_RENDER_DEFAULT);
+ KEY_DITHERING = new KeyImpl(3, "Dithering quality key",
+ VALUE_DITHER_DISABLE,
+ VALUE_DITHER_ENABLE,
+ VALUE_DITHER_DEFAULT);
+ KEY_TEXT_ANTIALIASING
+ = new KeyImpl(4, "Text-specific antialiasing enable key",
+ VALUE_TEXT_ANTIALIAS_ON,
+ VALUE_TEXT_ANTIALIAS_OFF,
+ VALUE_TEXT_ANTIALIAS_DEFAULT);
+ KEY_FRACTIONALMETRICS = new KeyImpl(5, "Fractional metrics enable key",
+ VALUE_FRACTIONALMETRICS_OFF,
+ VALUE_FRACTIONALMETRICS_ON,
+ VALUE_FRACTIONALMETRICS_DEFAULT);
+ KEY_INTERPOLATION = new KeyImpl(6, "Image interpolation method key",
+ VALUE_INTERPOLATION_NEAREST_NEIGHBOR,
+ VALUE_INTERPOLATION_BILINEAR,
+ VALUE_INTERPOLATION_BICUBIC);
+ KEY_ALPHA_INTERPOLATION
+ = new KeyImpl(7, "Alpha blending interpolation method key",
+ VALUE_ALPHA_INTERPOLATION_SPEED,
+ VALUE_ALPHA_INTERPOLATION_QUALITY,
+ VALUE_ALPHA_INTERPOLATION_DEFAULT);
+ KEY_COLOR_RENDERING = new KeyImpl(8, "Color rendering quality key",
+ VALUE_COLOR_RENDER_SPEED,
+ VALUE_COLOR_RENDER_QUALITY,
+ VALUE_COLOR_RENDER_DEFAULT);
+ KEY_STROKE_CONTROL = new KeyImpl(9, "Stroke normalization control key",
+ VALUE_STROKE_DEFAULT,
+ VALUE_STROKE_NORMALIZE,
+ VALUE_STROKE_PURE);
+ }
+
+ /**
+ * Creates a new collection of hints containing all the (key, value) pairs
+ * in the specified map.
+ *
+ * @param init a map containing a collection of hints (<code>null</code>
+ * permitted).
+ */
+ public RenderingHints(Map<Key,?> init)
+ {
+ if (init != null)
+ putAll(init);
+ }
+
+ /**
+ * Creates a new collection containing a single (key, value) pair.
+ *
+ * @param key the key.
+ * @param value the value.
+ */
+ public RenderingHints(Key key, Object value)
+ {
+ put(key, value);
+ }
+
+ /**
+ * Returns the number of hints in the collection.
+ *
+ * @return The number of hints.
+ */
+ public int size()
+ {
+ return hintMap.size();
+ }
+
+ /**
+ * Returns <code>true</code> if there are no hints in the collection,
+ * and <code>false</code> otherwise.
+ *
+ * @return A boolean.
+ */
+ public boolean isEmpty()
+ {
+ return hintMap.isEmpty();
+ }
+
+ /**
+ * Returns <code>true</code> if the collection of hints contains the
+ * specified key, and <code>false</code> otherwise.
+ *
+ * @param key the key (<code>null</code> not permitted).
+ *
+ * @return A boolean.
+ *
+ * @throws NullPointerException if <code>key</code> is <code>null</code>.
+ * @throws ClassCastException if <code>key</code> is not a {@link Key}.
+ */
+ public boolean containsKey(Object key)
+ {
+ if (key == null)
+ throw new NullPointerException();
+ // don't remove the cast, it is necessary to throw the required exception
+ return hintMap.containsKey((Key) key);
+ }
+
+ /**
+ * Returns <code>true</code> if the collection of hints contains the
+ * specified value, and <code>false</code> otherwise.
+ *
+ * @param value the value.
+ *
+ * @return A boolean.
+ */
+ public boolean containsValue(Object value)
+ {
+ return hintMap.containsValue(value);
+ }
+
+ /**
+ * Returns the value associated with the specified key, or <code>null</code>
+ * if there is no value defined for the key.
+ *
+ * @param key the key (<code>null</code> permitted).
+ *
+ * @return The value (possibly <code>null</code>).
+ *
+ * @throws ClassCastException if <code>key</code> is not a {@link Key}.
+ *
+ * @see #containsKey(Object)
+ */
+ public Object get(Object key)
+ {
+ // don't remove the cast, it is necessary to throw the required exception
+ return hintMap.get((Key) key);
+ }
+
+ /**
+ * Adds a (key, value) pair to the collection of hints (if the
+ * collection already contains the specified key, then the
+ * value is updated).
+ *
+ * @param key the key.
+ * @param value the value.
+ *
+ * @return the previous value of the key or <code>null</code> if the key
+ * didn't have a value yet.
+ */
+ public Object put(Object key, Object value)
+ {
+ if (key == null || value == null)
+ throw new NullPointerException();
+ if (! ((Key) key).isCompatibleValue(value))
+ throw new IllegalArgumentException();
+ return hintMap.put(key, value);
+ }
+
+ /**
+ * Adds all the hints from a collection to this collection.
+ *
+ * @param hints the hint collection.
+ */
+ public void add(RenderingHints hints)
+ {
+ hintMap.putAll(hints);
+ }
+
+ /**
+ * Clears all the hints from this collection.
+ */
+ public void clear()
+ {
+ hintMap.clear();
+ }
+
+ /**
+ * Removes a hint from the collection.
+ *
+ * @param key the key.
+ *
+ * @return The value that was associated with the key, or <code>null</code> if
+ * the key was not part of the collection
+ *
+ * @throws ClassCastException if the key is not a subclass of
+ * {@link RenderingHints.Key}.
+ */
+ public Object remove(Object key)
+ {
+ // don't remove the (Key) cast, it is necessary to throw the exception
+ // required by the spec
+ return hintMap.remove((Key) key);
+ }
+
+ /**
+ * Adds a collection of (key, value) pairs to the collection.
+ *
+ * @param m a map containing (key, value) items.
+ *
+ * @throws ClassCastException if the map contains a key that is not
+ * a subclass of {@link RenderingHints.Key}.
+ * @throws IllegalArgumentException if the map contains a value that is
+ * not compatible with its key.
+ */
+ public void putAll(Map<?,?> m)
+ {
+ // preprocess map to generate appropriate exceptions
+ Iterator iterator = m.keySet().iterator();
+ while (iterator.hasNext())
+ {
+ Key key = (Key) iterator.next();
+ if (!key.isCompatibleValue(m.get(key)))
+ throw new IllegalArgumentException();
+ }
+ // map is OK, update
+ hintMap.putAll(m);
+ }
+
+ /**
+ * Returns a set containing the keys from this collection.
+ *
+ * @return A set of keys.
+ */
+ public Set<Object> keySet()
+ {
+ return hintMap.keySet();
+ }
+
+ /**
+ * Returns a collection of the values from this hint collection. The
+ * collection is backed by the <code>RenderingHints</code> instance,
+ * so updates to one will affect the other.
+ *
+ * @return A collection of values.
+ */
+ public Collection<Object> values()
+ {
+ return hintMap.values();
+ }
+
+ /**
+ * Returns a set of entries from the collection.
+ *
+ * @return A set of entries.
+ */
+ public Set<Map.Entry<Object,Object>> entrySet()
+ {
+ return Collections.unmodifiableSet(hintMap.entrySet());
+ }
+
+ /**
+ * Checks this collection for equality with an arbitrary object.
+ *
+ * @param o the object (<code>null</code> permitted)
+ *
+ * @return A boolean.
+ */
+ public boolean equals(Object o)
+ {
+ return hintMap.equals(o);
+ }
+
+ /**
+ * Returns a hash code for the collection of hints.
+ *
+ * @return A hash code.
+ */
+ public int hashCode()
+ {
+ return hintMap.hashCode();
+ }
+
+ /**
+ * Creates a clone of this instance.
+ *
+ * @return A clone.
+ */
+ public Object clone()
+ {
+ try
+ {
+ RenderingHints copy = (RenderingHints) super.clone();
+ copy.hintMap = new HashMap<Object,Object>(hintMap);
+ return copy;
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // Impossible
+ }
+ }
+
+ /**
+ * Returns a string representation of this instance.
+ *
+ * @return A string.
+ */
+ public String toString()
+ {
+ return hintMap.toString();
+ }
+} // class RenderingHints
diff --git a/libjava/classpath/java/awt/Robot.java b/libjava/classpath/java/awt/Robot.java
new file mode 100644
index 000000000..30de5ca84
--- /dev/null
+++ b/libjava/classpath/java/awt/Robot.java
@@ -0,0 +1,423 @@
+/* Robot.java -- a native input event generator
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import gnu.java.awt.ClasspathToolkit;
+
+import java.lang.reflect.InvocationTargetException;
+import java.awt.event.InputEvent;
+import java.awt.image.BufferedImage;
+import java.awt.peer.RobotPeer;
+
+/**
+ * The Robot class is used to simulate user interaction with graphical
+ * programs. It can generate native windowing system input events and
+ * retrieve image data from the current screen. Robot is used to test
+ * the AWT and Swing library implementations; it can also be used to
+ * create self-running demo programs.
+ *
+ * Since Robot generates native windowing system events, rather than
+ * simply inserting {@link AWTEvent}s on the AWT event queue, its use
+ * is not restricted to Java programs. It can be used to
+ * programatically drive any graphical application.
+ *
+ * This implementation requires an X server that supports the XTest
+ * extension.
+ *
+ * @author Thomas Fitzsimmons (fitzsim@redhat.com)
+ *
+ * @since 1.3
+ */
+public class Robot
+{
+ private boolean waitForIdle;
+ private int autoDelay;
+ private RobotPeer peer;
+
+ /**
+ * Construct a Robot object that operates on the default screen.
+ *
+ * @exception AWTException if GraphicsEnvironment.isHeadless()
+ * returns true or if the X server does not support the XTest
+ * extension
+ * @exception SecurityException if createRobot permission is not
+ * granted
+ */
+ public Robot () throws AWTException
+ {
+ if (GraphicsEnvironment.isHeadless ())
+ throw new AWTException ("Robot: headless graphics environment");
+
+ SecurityManager sm = System.getSecurityManager ();
+ if (sm != null)
+ sm.checkPermission (new AWTPermission ("createRobot"));
+
+ ClasspathToolkit tk = (ClasspathToolkit) Toolkit.getDefaultToolkit ();
+
+ // createRobot will throw AWTException if XTest is not supported.
+ peer = tk.createRobot (GraphicsEnvironment.getLocalGraphicsEnvironment ()
+ .getDefaultScreenDevice ());
+ }
+
+ /**
+ * Construct a Robot object that operates on the specified screen.
+ *
+ * @exception AWTException if GraphicsEnvironment.isHeadless()
+ * returns true or if the X server does not support the XTest
+ * extension
+ * @exception IllegalArgumentException if screen is not a screen
+ * GraphicsDevice
+ * @exception SecurityException if createRobot permission is not
+ * granted
+ */
+ public Robot (GraphicsDevice screen) throws AWTException
+ {
+ if (GraphicsEnvironment.isHeadless ())
+ throw new AWTException ("Robot: headless graphics environment");
+
+ if (screen.getType () != GraphicsDevice.TYPE_RASTER_SCREEN)
+ throw new IllegalArgumentException ("Robot: graphics"
+ + " device is not a screen");
+
+ SecurityManager sm = System.getSecurityManager ();
+ if (sm != null)
+ sm.checkPermission (new AWTPermission ("createRobot"));
+
+ ClasspathToolkit tk = (ClasspathToolkit) Toolkit.getDefaultToolkit ();
+
+ // createRobot will throw AWTException if XTest is not supported.
+ peer = tk.createRobot (screen);
+ }
+
+ /**
+ * Move the mouse pointer to absolute coordinates (x, y).
+ *
+ * @param x the destination x coordinate
+ * @param y the destination y coordinate
+ */
+ public void mouseMove(int x, int y)
+ {
+ peer.mouseMove (x, y);
+
+ if (waitForIdle)
+ waitForIdle ();
+
+ if (autoDelay > 0)
+ delay (autoDelay);
+ }
+
+ /**
+ * Press one or more mouse buttons.
+ *
+ * @param buttons the buttons to press; a bitmask of one or more of
+ * these {@link InputEvent} fields:
+ *
+ * <ul>
+ * <li>BUTTON1_MASK</li>
+ * <li>BUTTON2_MASK</li>
+ * <li>BUTTON3_MASK</li>
+ * </ul>
+ *
+ * @exception IllegalArgumentException if the button mask is invalid
+ */
+ public void mousePress (int buttons)
+ {
+ if ((buttons & InputEvent.BUTTON1_MASK) == 0
+ && (buttons & InputEvent.BUTTON2_MASK) == 0
+ && (buttons & InputEvent.BUTTON3_MASK) == 0)
+ throw new IllegalArgumentException ("Robot: mousePress:"
+ + " invalid button mask");
+
+ peer.mousePress (buttons);
+
+ if (waitForIdle)
+ waitForIdle ();
+
+ if (autoDelay > 0)
+ delay (autoDelay);
+ }
+
+ /**
+ * Release one or more mouse buttons.
+ *
+ * @param buttons the buttons to release; a bitmask of one or more
+ * of these {@link InputEvent} fields:
+ *
+ * <ul>
+ * <li>BUTTON1_MASK</li>
+ * <li>BUTTON2_MASK</li>
+ * <li>BUTTON3_MASK</li>
+ * </ul>
+ *
+ * @exception IllegalArgumentException if the button mask is invalid
+ */
+ public void mouseRelease(int buttons)
+ {
+ if ((buttons & InputEvent.BUTTON1_MASK) == 0
+ && (buttons & InputEvent.BUTTON2_MASK) == 0
+ && (buttons & InputEvent.BUTTON3_MASK) == 0)
+ throw new IllegalArgumentException ("Robot: mouseRelease:"
+ + " invalid button mask");
+
+ peer.mouseRelease (buttons);
+
+ if (waitForIdle)
+ waitForIdle ();
+
+ if (autoDelay > 0)
+ delay (autoDelay);
+ }
+
+ /**
+ * Rotate the mouse scroll wheel.
+ *
+ * @param wheelAmt number of steps to rotate mouse wheel. negative
+ * to rotate wheel up (away from the user), positive to rotate wheel
+ * down (toward the user).
+ *
+ * @since 1.4
+ */
+ public void mouseWheel (int wheelAmt)
+ {
+ peer.mouseWheel (wheelAmt);
+
+ if (waitForIdle)
+ waitForIdle ();
+
+ if (autoDelay > 0)
+ delay (autoDelay);
+ }
+
+ /**
+ * Press a key.
+ *
+ * @param keycode key to press, a {@link java.awt.event.KeyEvent} VK_ constant
+ *
+ * @exception IllegalArgumentException if keycode is not a valid key
+ */
+ public void keyPress (int keycode)
+ {
+ peer.keyPress (keycode);
+
+ if (waitForIdle)
+ waitForIdle ();
+
+ if (autoDelay > 0)
+ delay (autoDelay);
+ }
+
+ /**
+ * Release a key.
+ *
+ * @param keycode key to release, a {@link java.awt.event.KeyEvent} VK_
+ * constant
+ *
+ * @exception IllegalArgumentException if keycode is not a valid key
+ */
+ public void keyRelease (int keycode)
+ {
+ peer.keyRelease (keycode);
+
+ if (waitForIdle)
+ waitForIdle ();
+
+ if (autoDelay > 0)
+ delay (autoDelay);
+ }
+
+ /**
+ * Return the color of the pixel at the given screen coordinates.
+ *
+ * @param x the x coordinate of the pixel
+ * @param y the y coordinate of the pixel
+ *
+ * @return the Color of the pixel at screen coodinates <code>(x, y)</code>
+ */
+ public Color getPixelColor (int x, int y)
+ {
+ return new Color (peer.getRGBPixel (x, y));
+ }
+
+ /**
+ * Create an image containing pixels read from the screen. The
+ * image does not include the mouse pointer.
+ *
+ * @param screenRect the rectangle of pixels to capture, in screen
+ * coordinates
+ *
+ * @return a BufferedImage containing the requested pixels
+ *
+ * @exception IllegalArgumentException if requested width and height
+ * are not both greater than zero
+ * @exception SecurityException if readDisplayPixels permission is
+ * not granted
+ */
+ public BufferedImage createScreenCapture (Rectangle screenRect)
+ {
+ if (screenRect.width <= 0)
+ throw new IllegalArgumentException ("Robot: capture width is <= 0");
+
+ if (screenRect.height <= 0)
+ throw new IllegalArgumentException ("Robot: capture height is <= 0");
+
+ SecurityManager sm = System.getSecurityManager ();
+ if (sm != null)
+ sm.checkPermission (new AWTPermission ("readDisplayPixels"));
+
+ int[] pixels = peer.getRGBPixels (screenRect);
+
+ BufferedImage bufferedImage =
+ new BufferedImage (screenRect.width, screenRect.height,
+ BufferedImage.TYPE_INT_ARGB);
+
+ bufferedImage.setRGB (0, 0, screenRect.width, screenRect.height,
+ pixels, 0, screenRect.width);
+
+ return bufferedImage;
+ }
+
+ /**
+ * Check if this Robot automatically calls {@link #waitForIdle()} after
+ * generating an event.
+ *
+ * @return true if waitForIdle is automatically called
+ */
+ public boolean isAutoWaitForIdle ()
+ {
+ return waitForIdle;
+ }
+
+ /**
+ * Set whether or not this Robot automatically calls {@link
+ * #waitForIdle()} after generating an event.
+ *
+ * @param isOn true if waitForIdle should be called automatically
+ */
+ public void setAutoWaitForIdle (boolean isOn)
+ {
+ waitForIdle = isOn;
+ }
+
+ /**
+ * Retrieve the length of time this Robot sleeps after generating an
+ * event.
+ *
+ * @return the length of time in milliseconds
+ */
+ public int getAutoDelay ()
+ {
+ return autoDelay;
+ }
+
+ /**
+ * Set the length of time this Robot sleeps after generating an
+ * event.
+ *
+ * @param ms the length of time in milliseconds
+ *
+ * @exception IllegalArgumentException if ms is not between 0 and
+ * 60,000 milliseconds inclusive
+ */
+ public void setAutoDelay (int ms)
+ {
+ if (ms <= 0 || ms >= 60000)
+ throw new IllegalArgumentException ("Robot: delay length out-of-bounds");
+
+ autoDelay = ms;
+ }
+
+ /**
+ * Sleep for a specified length of time.
+ *
+ * @param ms the length of time in milliseconds
+ *
+ * @exception IllegalArgumentException if ms is not between 0 and
+ * 60,000 milliseconds inclusive
+ */
+ public void delay (int ms)
+ {
+ if (ms < 0 || ms > 60000)
+ throw new IllegalArgumentException ("Robot: delay length out-of-bounds");
+
+ try
+ {
+ Thread.sleep (ms);
+ }
+ catch (InterruptedException e)
+ {
+ System.err.println ("Robot: delay interrupted");
+ }
+ }
+
+ /**
+ * Wait until all events currently on the event queue have been
+ * dispatched.
+ */
+ public void waitForIdle ()
+ {
+ if (EventQueue.isDispatchThread ())
+ throw new IllegalThreadStateException ("Robot: waitForIdle called from "
+ + "the event dispatch thread");
+
+ try
+ {
+ EventQueue.invokeAndWait (new Runnable () { public void run () { } });
+ }
+ catch (InterruptedException e)
+ {
+ System.err.println ("Robot: waitForIdle interrupted");
+ }
+ catch (InvocationTargetException e)
+ {
+ System.err.println ("Robot: waitForIdle cannot invoke target");
+ }
+ }
+
+ /**
+ * Return a string representation of this Robot.
+ *
+ * @return a string representation
+ */
+ public String toString ()
+ {
+ return getClass ().getName ()
+ + "[ autoDelay = " + autoDelay + ", autoWaitForIdle = "
+ + waitForIdle + " ]";
+ }
+}
diff --git a/libjava/classpath/java/awt/ScrollPane.java b/libjava/classpath/java/awt/ScrollPane.java
new file mode 100644
index 000000000..14d15f648
--- /dev/null
+++ b/libjava/classpath/java/awt/ScrollPane.java
@@ -0,0 +1,680 @@
+/* ScrollPane.java -- Scrolling window
+ Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.MouseEvent;
+import java.awt.peer.ComponentPeer;
+import java.awt.peer.ScrollPanePeer;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+
+
+/**
+ * This widget provides a scrollable region that allows a single
+ * subcomponent to be viewed through a smaller window.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class ScrollPane extends Container implements Accessible
+{
+
+/*
+ * Static Variables
+ */
+
+/**
+ * Constant indicating that scrollbars are created as needed in this
+ * windows.
+ */
+public static final int SCROLLBARS_AS_NEEDED = 0;
+
+/**
+ * Constant indicating that scrollbars are always displayed in this
+ * window.
+ */
+public static final int SCROLLBARS_ALWAYS = 1;
+
+/**
+ * Constant indicating that scrollbars are never displayed in this window.
+ */
+public static final int SCROLLBARS_NEVER = 2;
+
+/**
+ * The number used to generate the name returned by getName.
+ */
+private static transient long next_scrollpane_number;
+
+// Serialization constant
+private static final long serialVersionUID = 7956609840827222915L;
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * @serial The horizontal scrollbar for this window. The methods
+ * <code>setMinimum()</code>, <code>setMaximum</code>, and
+ * <code>setVisibleAmount</code> must not be called on this scrollbar.
+ */
+private ScrollPaneAdjustable hAdjustable;
+
+/**
+ * @serial The vertical scrollbar for this window. The methods
+ * <code>setMinimum()</code>, <code>setMaximum</code>, and
+ * <code>setVisibleAmount</code> must not be called on this scrollbar.
+ */
+private ScrollPaneAdjustable vAdjustable;
+
+/**
+ * @serial Indicates when scrollbars are displayed in this window, will
+ * be one of the constants from this class.
+ */
+private int scrollbarDisplayPolicy;
+
+// Current scroll position
+private Point scrollPosition = new Point(0, 0);
+
+private boolean wheelScrollingEnabled;
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+ * Initializes a new instance of <code>ScrollPane</code> with a default
+ * scrollbar policy of <code>SCROLLBARS_AS_NEEDED</code>.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+public
+ScrollPane()
+{
+ this(SCROLLBARS_AS_NEEDED);
+}
+
+/*************************************************************************/
+
+/**
+ * Initializes a new instance of <code>ScrollPane</code> with the
+ * specified scrollbar policy.
+ *
+ * @param scrollbarDisplayPolicy When to display scrollbars, which must
+ * be one of the constants defined in this class.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+public
+ScrollPane(int scrollbarDisplayPolicy)
+{
+ if (GraphicsEnvironment.isHeadless ())
+ throw new HeadlessException ();
+
+ this.scrollbarDisplayPolicy = scrollbarDisplayPolicy;
+
+ if (scrollbarDisplayPolicy != SCROLLBARS_ALWAYS
+ && scrollbarDisplayPolicy != SCROLLBARS_AS_NEEDED
+ && scrollbarDisplayPolicy != SCROLLBARS_NEVER)
+ throw new IllegalArgumentException("Bad scrollbarDisplayPolicy: " +
+ scrollbarDisplayPolicy);
+
+ if (scrollbarDisplayPolicy != SCROLLBARS_NEVER)
+ {
+ hAdjustable = new ScrollPaneAdjustable (this, Scrollbar.HORIZONTAL);
+ vAdjustable = new ScrollPaneAdjustable (this, Scrollbar.VERTICAL);
+ }
+
+ wheelScrollingEnabled = true;
+
+ // Default size.
+ setSize(100,100);
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+ * Returns the current scrollbar display policy.
+ *
+ * @return The current scrollbar display policy.
+ */
+public int
+getScrollbarDisplayPolicy()
+{
+ return(scrollbarDisplayPolicy);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the horizontal scrollbar for this object. If the scrollbar
+ * display policy is set to <code>SCROLLBARS_NEVER</code> then this
+ * will be <code>null</code>.
+ *
+ * @return The horizontal scrollbar for this window.
+ */
+public Adjustable
+getHAdjustable()
+{
+ return(hAdjustable);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the vertical scrollbar for this object. If the scrollbar
+ * display policy is set to <code>SCROLLBARS_NEVER</code> then this
+ * will be <code>null</code>.
+ *
+ * @return The horizontal scrollbar for this window.
+ */
+public Adjustable
+getVAdjustable()
+{
+ return(vAdjustable);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the current viewport size. The viewport is the region of
+ * this object's window where the child is actually displayed.
+ *
+ * @return The viewport size.
+ */
+public Dimension getViewportSize ()
+{
+ Dimension viewsize = getSize ();
+ Insets insets = getInsets ();
+
+ viewsize.width -= (insets.left + insets.right);
+ viewsize.height -= (insets.top + insets.bottom);
+
+ Component[] list = getComponents();
+ if ((list == null) || (list.length <= 0))
+ return viewsize;
+
+ Dimension dim = list[0].getPreferredSize();
+
+ if (dim.width <= 0 && dim.height <= 0)
+ return viewsize;
+
+ int vScrollbarWidth = getVScrollbarWidth ();
+ int hScrollbarHeight = getHScrollbarHeight ();
+
+ if (scrollbarDisplayPolicy == SCROLLBARS_ALWAYS)
+ {
+ viewsize.width -= vScrollbarWidth;
+ viewsize.height -= hScrollbarHeight;
+ return viewsize;
+ }
+
+ if (scrollbarDisplayPolicy == SCROLLBARS_NEVER)
+ return viewsize;
+
+ // The scroll policy is SCROLLBARS_AS_NEEDED, so we need to see if
+ // either scrollbar is needed.
+
+ // Assume we don't need either scrollbar.
+ boolean mayNeedVertical = false;
+ boolean mayNeedHorizontal = false;
+
+ boolean needVertical = false;
+ boolean needHorizontal = false;
+
+ // Check if we need vertical scrollbars. If we do, then we need to
+ // subtract the width of the vertical scrollbar from the viewport's
+ // width.
+ if (dim.height > viewsize.height)
+ needVertical = true;
+ else if (dim.height > (viewsize.height - hScrollbarHeight))
+ // This is tricky. In this case the child is tall enough that its
+ // bottom edge would be covered by a horizontal scrollbar, if one
+ // were present. This means that if there's a horizontal
+ // scrollbar then we need a vertical scrollbar.
+ mayNeedVertical = true;
+
+ if (dim.width > viewsize.width)
+ needHorizontal = true;
+ else if (dim.width > (viewsize.width - vScrollbarWidth))
+ mayNeedHorizontal = true;
+
+ if (needVertical && mayNeedHorizontal)
+ needHorizontal = true;
+
+ if (needHorizontal && mayNeedVertical)
+ needVertical = true;
+
+ if (needHorizontal)
+ viewsize.height -= hScrollbarHeight;
+
+ if (needVertical)
+ viewsize.width -= vScrollbarWidth;
+
+ return viewsize;
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the height of a horizontal scrollbar.
+ *
+ * @return The height of a horizontal scrollbar.
+ */
+public int
+getHScrollbarHeight()
+{
+ ScrollPanePeer spp = (ScrollPanePeer)getPeer();
+ if (spp != null)
+ return(spp.getHScrollbarHeight());
+ else
+ return(0); // FIXME: What to do here?
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the width of a vertical scrollbar.
+ *
+ * @return The width of a vertical scrollbar.
+ */
+public int
+getVScrollbarWidth()
+{
+ ScrollPanePeer spp = (ScrollPanePeer)getPeer();
+ if (spp != null)
+ return(spp.getVScrollbarWidth());
+ else
+ return(0); // FIXME: What to do here?
+}
+
+/*************************************************************************/
+
+/**
+ * Returns the current scroll position of the viewport.
+ *
+ * @return The current scroll position of the viewport.
+ *
+ * @throws NullPointerException if the scrollpane does have a child.
+ */
+public Point
+getScrollPosition()
+{
+ if (getComponentCount() == 0)
+ throw new NullPointerException();
+
+ int x = 0;
+ int y = 0;
+
+ Adjustable v = getVAdjustable();
+ Adjustable h = getHAdjustable();
+
+ if (v != null)
+ y = v.getValue();
+ if (h != null)
+ x = h.getValue();
+
+ return(new Point(x, y));
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the scroll position to the specified value.
+ *
+ * @param scrollPosition The new scrollPosition.
+ *
+ * @exception IllegalArgumentException If the specified value is outside
+ * the legal scrolling range.
+ */
+public void
+setScrollPosition(Point scrollPosition) throws IllegalArgumentException
+{
+ setScrollPosition(scrollPosition.x, scrollPosition.y);
+}
+
+/*************************************************************************/
+
+/**
+ * Sets the scroll position to the specified value.
+ *
+ * @param x The new X coordinate of the scroll position.
+ * @param y The new Y coordinate of the scroll position.
+ *
+ * @throws NullPointerException if scrollpane does not have a child.
+ *
+ * @exception IllegalArgumentException If the specified value is outside
+ * the legal scrolling range.
+ */
+public void
+setScrollPosition(int x, int y)
+{
+ if (getComponentCount() == 0)
+ throw new NullPointerException("child is null");
+
+ if (x > (int) (getComponent(0).getWidth() - getViewportSize().getWidth()))
+ x = (int) (getComponent(0).getWidth() - getViewportSize().getWidth());
+ if (y > (int) (getComponent(0).getHeight() - getViewportSize().getHeight()))
+ y = (int) (getComponent(0).getHeight() - getViewportSize().getHeight());
+
+ if (x < 0)
+ x = 0;
+ if (y < 0)
+ y = 0;
+
+ Adjustable h = getHAdjustable();
+ Adjustable v = getVAdjustable();
+
+ if (h != null)
+ h.setValue(x);
+ if (v != null)
+ v.setValue(y);
+
+ ScrollPanePeer spp = (ScrollPanePeer)getPeer();
+ if (spp != null)
+ spp.setScrollPosition(x, y);
+}
+
+/*************************************************************************/
+
+/**
+ * Notifies this object that it should create its native peer.
+ */
+public void
+addNotify()
+{
+ if (peer != null)
+ return;
+
+ setPeer((ComponentPeer)getToolkit().createScrollPane(this));
+ super.addNotify();
+
+ Component[] list = getComponents();
+ if (list != null && list.length > 0 && list[0].isLightweight())
+ {
+ Panel panel = new Panel();
+ panel.setLayout(new BorderLayout());
+ panel.add(list[0], BorderLayout.CENTER);
+ add(panel);
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * Notifies this object that it should destroy its native peers.
+ */
+public void
+removeNotify()
+{
+ super.removeNotify();
+}
+
+/*************************************************************************/
+
+/**
+ * Adds the specified child component to this container. A
+ * <code>ScrollPane</code> can have at most one child, so if a second
+ * one is added, then first one is removed.
+ *
+ * @param component The component to add to this container.
+ * @param constraints A list of layout constraints for this object.
+ * @param index The index at which to add the child, which is ignored
+ * in this implementation.
+ */
+ protected final void addImpl (Component component, Object constraints,
+ int index)
+{
+ Component[] list = getComponents();
+ if ((list != null) && (list.length > 0))
+ remove(list[0]);
+
+ super.addImpl(component, constraints, index);
+}
+
+/*************************************************************************/
+
+/**
+ * Lays out this component. This consists of resizing the sole child
+ * component to its perferred size.
+ */
+public void
+doLayout()
+{
+ layout ();
+}
+
+/*************************************************************************/
+
+/**
+ * Lays out this component. This consists of resizing the sole child
+ * component to its perferred size.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>doLayout()</code>.
+ */
+public void
+layout()
+{
+ Component[] list = getComponents ();
+ if ((list != null) && (list.length > 0))
+ {
+ Dimension dim = list[0].getPreferredSize ();
+ Dimension vp = getViewportSize ();
+
+ if (dim.width < vp.width)
+ dim.width = vp.width;
+
+ if (dim.height < vp.height)
+ dim.height = vp.height;
+
+ ScrollPanePeer peer = (ScrollPanePeer) getPeer ();
+ if (peer != null)
+ peer.childResized (dim.width, dim.height);
+
+ list[0].setSize (dim);
+
+ Point p = getScrollPosition ();
+ if (p.x > dim.width)
+ p.x = dim.width;
+ if (p.y > dim.height)
+ p.y = dim.height;
+
+ setScrollPosition (p);
+
+ list[0].setLocation(new Point());
+ }
+}
+
+/*************************************************************************/
+
+/**
+ * This method overrides its superclass method to ensure no layout
+ * manager is set for this container. <code>ScrollPane</code>'s do
+ * not have layout managers.
+ *
+ * @param layoutManager Ignored
+ * @throws AWTError Always throws this error when called.
+ */
+public final void
+setLayout(LayoutManager layoutManager)
+{
+ throw new AWTError("ScrollPane controls layout");
+}
+
+/*************************************************************************/
+
+/**
+ * Prints all of the components in this container.
+ *
+ * @param graphics The desired graphics context for printing.
+ */
+public void
+printComponents(Graphics graphics)
+{
+ super.printComponents(graphics);
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a debug string for this object.
+ *
+ * @return A debug string for this object.
+ */
+public String
+paramString()
+{
+ Insets insets = getInsets();
+ return getName() + ","
+ + getX() + ","
+ + getY() + ","
+ + getWidth() + "x" + getHeight() + ","
+ + getIsValidString() + ","
+ + "ScrollPosition=(" + scrollPosition.x + ","
+ + scrollPosition.y + "),"
+ + "Insets=(" + insets.top + ","
+ + insets.left + ","
+ + insets.bottom + ","
+ + insets.right + "),"
+ + "ScrollbarDisplayPolicy=" + getScrollbarDisplayPolicyString() + ","
+ + "wheelScrollingEnabled=" + isWheelScrollingEnabled();
+}
+
+private String
+getScrollbarDisplayPolicyString()
+{
+ if (getScrollbarDisplayPolicy() == 0)
+ return "as-needed";
+ else if (getScrollbarDisplayPolicy() == 1)
+ return "always";
+ else
+ return "never";
+}
+
+private String
+getIsValidString()
+{
+ if (isValid())
+ return "valid";
+ else
+ return "invalid";
+}
+
+ /**
+ * Tells whether or not an event is enabled.
+ *
+ * @since 1.4
+ */
+ protected boolean eventTypeEnabled (int type)
+ {
+ if (type == MouseEvent.MOUSE_WHEEL)
+ return wheelScrollingEnabled;
+
+ return super.eventTypeEnabled (type);
+ }
+
+ /**
+ * Tells whether or not wheel scrolling is enabled.
+ *
+ * @since 1.4
+ */
+ public boolean isWheelScrollingEnabled ()
+ {
+ return wheelScrollingEnabled;
+ }
+
+ /**
+ * Enables/disables wheel scrolling.
+ *
+ * @since 1.4
+ */
+ public void setWheelScrollingEnabled (boolean enable)
+ {
+ wheelScrollingEnabled = enable;
+ }
+
+ protected class AccessibleAWTScrollPane extends AccessibleAWTContainer
+ {
+ private static final long serialVersionUID = 6100703663886637L;
+
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.SCROLL_PANE;
+ }
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>ScrollPane</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTScrollPane();
+ return accessibleContext;
+ }
+
+ /**
+ * Generate a unique name for this <code>ScrollPane</code>.
+ *
+ * @return A unique name for this <code>ScrollPane</code>.
+ */
+ String generateName()
+ {
+ return "scrollpane" + getUniqueLong();
+ }
+
+ private static synchronized long getUniqueLong()
+ {
+ return next_scrollpane_number++;
+ }
+
+} // class ScrollPane
diff --git a/libjava/classpath/java/awt/ScrollPaneAdjustable.java b/libjava/classpath/java/awt/ScrollPaneAdjustable.java
new file mode 100644
index 000000000..0f2986d59
--- /dev/null
+++ b/libjava/classpath/java/awt/ScrollPaneAdjustable.java
@@ -0,0 +1,241 @@
+/* ScrollPaneAdjustable.java -- Scrollbars for a ScrollPane
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.AdjustmentListener;
+import java.io.Serializable;
+
+/**
+ * Need this class since the serialization spec for ScrollPane
+ * uses it.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.4
+ */
+public class ScrollPaneAdjustable
+ implements Adjustable, Serializable
+{
+ private static final long serialVersionUID = -3359745691033257079L;
+
+ ScrollPane sp;
+ int orientation;
+ int value;
+ int minimum;
+ int maximum;
+ int visibleAmount;
+ int unitIncrement = 1;
+ int blockIncrement = 1;
+ AdjustmentListener adjustmentListener;
+
+ private transient boolean valueIsAdjusting = false;
+
+ ScrollPaneAdjustable (ScrollPane sp, int orientation)
+ {
+ this.sp = sp;
+ this.orientation = orientation;
+ }
+
+ ScrollPaneAdjustable (ScrollPane sp, int orientation, int value, int minimum,
+ int maximum, int visibleAmount, int unitIncrement,
+ int blockIncrement)
+ {
+ this.sp = sp;
+ this.orientation = orientation;
+ this.value = value;
+ this.minimum = minimum;
+ this.maximum = maximum;
+ this.visibleAmount = visibleAmount;
+ this.unitIncrement = unitIncrement;
+ this.blockIncrement = blockIncrement;
+ }
+
+ public void addAdjustmentListener (AdjustmentListener listener)
+ {
+ if (listener == null)
+ return;
+ adjustmentListener = AWTEventMulticaster.add (adjustmentListener, listener);
+ }
+
+ public void removeAdjustmentListener (AdjustmentListener listener)
+ {
+ if (listener == null)
+ return;
+ adjustmentListener = AWTEventMulticaster.remove (adjustmentListener, listener);
+ }
+
+ public AdjustmentListener[] getAdjustmentListeners ()
+ {
+ return (AdjustmentListener[]) AWTEventMulticaster.getListeners
+ (adjustmentListener, AdjustmentListener.class);
+ }
+
+ public int getBlockIncrement ()
+ {
+ return blockIncrement;
+ }
+
+ public int getMaximum ()
+ {
+ return maximum;
+ }
+
+ public int getMinimum ()
+ {
+ return minimum;
+ }
+
+ public int getOrientation ()
+ {
+ return orientation;
+ }
+
+ public int getUnitIncrement ()
+ {
+ return unitIncrement;
+ }
+
+ public int getValue ()
+ {
+ return value;
+ }
+
+ public int getVisibleAmount ()
+ {
+ return visibleAmount;
+ }
+
+ public void setBlockIncrement (int blockIncrement)
+ {
+ this.blockIncrement = blockIncrement;
+ }
+
+ /**
+ * This method should never be called.
+ *
+ * @param maximum The maximum value to be set.
+ * @throws AWTError Always throws this error when called.
+ */
+ public void setMaximum (int maximum) throws AWTError
+ {
+ throw new AWTError("Can be set by scrollpane only");
+ }
+
+ /**
+ * This method should never be called.
+ *
+ * @param minimum The minimum value to be set.
+ * @throws AWTError Always throws this error when called.
+ */
+ public void setMinimum (int minimum)
+ {
+ throw new AWTError("Can be set by scrollpane only");
+ }
+
+ public void setUnitIncrement (int unitIncrement)
+ {
+ this.unitIncrement = unitIncrement;
+ }
+
+ public void setValue (int value)
+ {
+ this.value = value;
+
+ if (value < minimum)
+ minimum = value;
+
+ if (value > maximum)
+ maximum = value;
+ }
+
+ /**
+ * This method should never be called.
+ *
+ * @param visibleAmount The visible amount to be set.
+ * @throws AWTError Always throws this error when called.
+ */
+ public void setVisibleAmount (int visibleAmount)
+ {
+ throw new AWTError("Can be set by scrollpane only");
+ }
+
+ public String paramString ()
+ {
+ return paramStringHelper()
+ + ",[" + getMinimum() + ".." + getMaximum()
+ + "],val=" + getValue()
+ + ",vis=" + getVisibleAmount()
+ + ",unit=" + getUnitIncrement()
+ + ",block=" + getBlockIncrement()
+ + ",isAdjusting=" + valueIsAdjusting;
+ }
+
+ private String paramStringHelper()
+ {
+ if (getOrientation() == HORIZONTAL)
+ return "horizontal";
+ else
+ return "vertical";
+ }
+
+ public String toString()
+ {
+ return getClass().getName() + "[" + paramString() + "]";
+ }
+
+ /**
+ * Returns true if the value is in the process of changing.
+ *
+ * @since 1.4
+ */
+ public boolean getValueIsAdjusting ()
+ {
+ return valueIsAdjusting;
+ }
+
+ /**
+ * Sets the value of valueIsAdjusting.
+ *
+ * @since 1.4
+ */
+ public void setValueIsAdjusting (boolean valueIsAdjusting)
+ {
+ this.valueIsAdjusting = valueIsAdjusting;
+ }
+
+} // class ScrollPaneAdjustable
diff --git a/libjava/classpath/java/awt/Scrollbar.java b/libjava/classpath/java/awt/Scrollbar.java
new file mode 100644
index 000000000..4a9e36c31
--- /dev/null
+++ b/libjava/classpath/java/awt/Scrollbar.java
@@ -0,0 +1,815 @@
+/* Scrollbar.java -- AWT Scrollbar widget
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.AdjustmentEvent;
+import java.awt.event.AdjustmentListener;
+import java.awt.peer.ScrollbarPeer;
+import java.util.EventListener;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleState;
+import javax.accessibility.AccessibleStateSet;
+import javax.accessibility.AccessibleValue;
+
+/**
+ * This class implements a scrollbar widget.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+public class Scrollbar extends Component implements Accessible, Adjustable
+{
+ // FIXME: Serialization readObject/writeObject
+
+ /**
+ * Constant indicating that a scrollbar is horizontal.
+ */
+ public static final int HORIZONTAL = 0;
+
+ /**
+ * Constant indicating that a scrollbar is vertical.
+ */
+ public static final int VERTICAL = 1;
+
+ /**
+ * Serialization Constant.
+ */
+ private static final long serialVersionUID = 8451667562882310543L;
+
+ /**
+ * @serial The amount by which the value of the scrollbar is changed
+ * when incrementing in line mode.
+ */
+ private int lineIncrement;
+
+ /**
+ * @serial The amount by which the value of the scrollbar is changed
+ * when incrementing in page mode.
+ */
+ private int pageIncrement;
+
+ /**
+ * @serial The maximum value for this scrollbar
+ */
+ private int maximum;
+
+ /**
+ * @serial The minimum value for this scrollbar
+ */
+ private int minimum;
+
+ /**
+ * @serial The orientation of this scrollbar, which will be either
+ * the <code>HORIZONTAL</code> or <code>VERTICAL</code> constant
+ * from this class.
+ */
+ private int orientation;
+
+ /**
+ * @serial The current value of this scrollbar.
+ */
+ private int value;
+
+ /**
+ * @serial The width of the scrollbar's thumb, which is relative
+ * to the minimum and maximum value of the scrollbar.
+ */
+ private int visibleAmount;
+
+ /**
+ * List of AdjustmentListener's.
+ */
+ private AdjustmentListener adjustment_listeners;
+
+ /**
+ * true if the scrollbar is adjusting, false otherwise.
+ */
+ private transient boolean valueIsAdjusting = false;
+
+ /**
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_scrollbar_number;
+
+ /**
+ * Initializes a new instance of <code>Scrollbar</code> with a
+ * vertical orientation and default values for all other parameters.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true,
+ */
+ public Scrollbar()
+ {
+ this(VERTICAL);
+ }
+
+ /**
+ * Initializes a new instance of <code>Scrollbar</code> with the
+ * specified orientation and default values for all other parameters.
+ * The orientation must be either the constant <code>HORIZONTAL</code> or
+ * <code>VERTICAL</code> from this class. An incorrect value will throw
+ * an exception.
+ *
+ * @param orientation The orientation of this scrollbar.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true,
+ * @exception IllegalArgumentException If the orientation value is not valid.
+ */
+ public Scrollbar(int orientation) throws IllegalArgumentException
+ {
+ this(orientation, 0, 10, 0, 100);
+ }
+
+ /**
+ * Initializes a new instance of <code>Scrollbar</code> with the
+ * specified parameters. The orientation must be either the constant
+ * <code>HORIZONTAL</code> or <code>VERTICAL</code>. An incorrect value
+ * will throw an exception. Inconsistent values for other parameters
+ * are silently corrected to valid values.
+ *
+ * @param orientation The orientation of this scrollbar.
+ * @param value The initial value of the scrollbar.
+ * @param visibleAmount The width of the scrollbar thumb.
+ * @param minimum The minimum value of the scrollbar.
+ * @param maximum The maximum value of the scrollbar.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true,
+ * @exception IllegalArgumentException If the orientation value is not valid.
+ */
+ public Scrollbar(int orientation, int value, int visibleAmount, int minimum,
+ int maximum) throws IllegalArgumentException
+ {
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException();
+
+ if ((orientation != HORIZONTAL) && (orientation != VERTICAL))
+ throw new IllegalArgumentException("Bad orientation value: "
+ + orientation);
+
+ this.orientation = orientation;
+
+ setValues(value, visibleAmount, minimum, maximum);
+
+ // Default is 1 according to online docs.
+ lineIncrement = 1;
+
+ // Default is 10 according to javadocs.
+ pageIncrement = 10;
+ }
+
+ /**
+ * Returns the orientation constant for this object.
+ *
+ * @return The orientation constant for this object.
+ */
+ public int getOrientation()
+ {
+ return orientation;
+ }
+
+ /**
+ * Sets the orientation of this scrollbar to the specified value. This
+ * value must be either the constant <code>HORIZONTAL</code> or
+ * <code>VERTICAL</code> from this class or an exception will be thrown.
+ *
+ * @param orientation The new orientation value.
+ *
+ * @exception IllegalArgumentException If the orientation value is not valid.
+ */
+ public void setOrientation(int orientation)
+ {
+ if ((orientation != HORIZONTAL) && (orientation != VERTICAL))
+ throw new IllegalArgumentException("Bad orientation value: "
+ + orientation);
+
+ // FIXME: Communicate to peer? Or must this be called before peer creation?
+ this.orientation = orientation;
+ }
+
+ /**
+ * Returns the current value for this scrollbar.
+ *
+ * @return The current value for this scrollbar.
+ */
+ public int getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Sets the current value for this scrollbar to the specified value.
+ * If this is inconsistent with the minimum and maximum values for this
+ * scrollbar, the value is silently adjusted.
+ *
+ * @param value The new value for this scrollbar.
+ */
+ public void setValue(int value)
+ {
+ setValues(value, visibleAmount, minimum, maximum);
+ }
+
+ /**
+ * Returns the maximum value for this scrollbar.
+ *
+ * @return The maximum value for this scrollbar.
+ */
+ public int getMaximum()
+ {
+ return maximum;
+ }
+
+ /**
+ * Sets the maximum value for this scrollbar to the specified value.
+ * If the value is less than the current minimum value, it is silent
+ * set to equal the minimum value.
+ *
+ * @param maximum The new maximum value for this scrollbar.
+ */
+ public void setMaximum(int maximum)
+ {
+ setValues(value, visibleAmount, minimum, maximum);
+ }
+
+ /**
+ * Returns the minimum value for this scrollbar.
+ *
+ * @return The minimum value for this scrollbar.
+ */
+ public int getMinimum()
+ {
+ return minimum;
+ }
+
+ /**
+ * Sets the minimum value for this scrollbar to the specified value. If
+ * this is not consistent with the current value and maximum, it is
+ * silently adjusted to be consistent.
+ *
+ * @param minimum The new minimum value for this scrollbar.
+ */
+ public void setMinimum(int minimum)
+ {
+ setValues(value, visibleAmount, minimum, maximum);
+ }
+
+ /**
+ * Returns the width of the scrollbar's thumb, in units relative to the
+ * maximum and minimum value of the scrollbar.
+ *
+ * @return The width of the scrollbar's thumb.
+ */
+ public int getVisibleAmount()
+ {
+ return getVisible();
+ }
+
+ /**
+ * Returns the width of the scrollbar's thumb, in units relative to the
+ * maximum and minimum value of the scrollbar.
+ *
+ * @return The width of the scrollbar's thumb.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getVisibleAmount()</code>.
+ */
+ public int getVisible()
+ {
+ return visibleAmount;
+ }
+
+ /**
+ * Sets the width of the scrollbar's thumb, in units relative to the
+ * maximum and minimum value of the scrollbar.
+ *
+ * @param visibleAmount The new visible amount value of the scrollbar.
+ */
+ public void setVisibleAmount(int visibleAmount)
+ {
+ setValues(value, visibleAmount, minimum, maximum);
+ }
+
+ /**
+ * Sets the current value, visible amount, minimum, and maximum for this
+ * scrollbar. These values are adjusted to be internally consistent
+ * if necessary.
+ *
+ * @param value The new value for this scrollbar.
+ * @param visibleAmount The new visible amount for this scrollbar.
+ * @param minimum The new minimum value for this scrollbar.
+ * @param maximum The new maximum value for this scrollbar.
+ */
+ public synchronized void setValues(int value, int visibleAmount,
+ int minimum, int maximum)
+ {
+ if (visibleAmount <= 0)
+ visibleAmount = 1;
+
+ if (maximum <= minimum)
+ maximum = minimum + 1;
+
+ if (value < minimum)
+ value = minimum;
+
+ if (visibleAmount > maximum - minimum)
+ visibleAmount = maximum - minimum;
+
+ // According to documentation, the actual maximum
+ // value is (maximum - visibleAmount)
+ if (value > maximum - visibleAmount)
+ value = maximum - visibleAmount;
+
+ ScrollbarPeer peer = (ScrollbarPeer) getPeer();
+ if (peer != null
+ && (this.value != value || this.visibleAmount != visibleAmount
+ || this.minimum != minimum || this.maximum != maximum))
+ peer.setValues(value, visibleAmount, minimum, maximum);
+
+ this.value = value;
+ this.visibleAmount = visibleAmount;
+ this.minimum = minimum;
+ this.maximum = maximum;
+ }
+
+ /**
+ * Returns the value added or subtracted when the user activates the scrollbar
+ * scroll by a "unit" amount.
+ *
+ * @return The unit increment value.
+ */
+ public int getUnitIncrement()
+ {
+ return getLineIncrement();
+ }
+
+ /**
+ * Returns the value added or subtracted when the user selects the scrollbar
+ * scroll by a "unit" amount control.
+ *
+ * @return The unit increment value.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getUnitIncrement()</code>.
+ */
+ public int getLineIncrement()
+ {
+ return lineIncrement;
+ }
+
+ /**
+ * Sets the value added or subtracted to the scrollbar value when the
+ * user selects the scroll by a "unit" amount control.
+ *
+ * @param unitIncrement The new unit increment amount.
+ */
+ public synchronized void setUnitIncrement(int unitIncrement)
+ {
+ setLineIncrement(unitIncrement);
+ }
+
+ /**
+ * Sets the value added or subtracted to the scrollbar value when the
+ * user selects the scroll by a "unit" amount control.
+ *
+ * @param lineIncrement The new unit increment amount.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>setUnitIncrement()</code>.
+ */
+ public void setLineIncrement(int lineIncrement)
+ {
+ if (lineIncrement < 0)
+ throw new IllegalArgumentException("Unit increment less than zero.");
+
+ if (lineIncrement == 0)
+ lineIncrement = 1;
+
+ if (lineIncrement == this.lineIncrement)
+ return;
+
+ this.lineIncrement = lineIncrement;
+
+ ScrollbarPeer peer = (ScrollbarPeer) getPeer();
+ if (peer != null)
+ peer.setLineIncrement(this.lineIncrement);
+ }
+
+ /**
+ * Returns the value added or subtracted when the user activates the scrollbar
+ * scroll by a "block" amount.
+ *
+ * @return The block increment value.
+ */
+ public int getBlockIncrement()
+ {
+ return getPageIncrement();
+ }
+
+ /**
+ * Returns the value added or subtracted when the user selects the scrollbar
+ * scroll by a "block" amount control.
+ *
+ * @return The block increment value.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getBlockIncrement()</code>.
+ */
+ public int getPageIncrement()
+ {
+ return pageIncrement;
+ }
+
+ /**
+ * Sets the value added or subtracted to the scrollbar value when the
+ * user selects the scroll by a "block" amount control.
+ *
+ * @param blockIncrement The new block increment amount.
+ */
+ public synchronized void setBlockIncrement(int blockIncrement)
+ {
+ setPageIncrement(blockIncrement);
+ }
+
+ /**
+ * Sets the value added or subtracted to the scrollbar value when the
+ * user selects the scroll by a "block" amount control.
+ *
+ * @param pageIncrement The new block increment amount.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>setBlockIncrement()</code>.
+ */
+ public void setPageIncrement(int pageIncrement)
+ {
+ if (pageIncrement < 0)
+ throw new IllegalArgumentException("Block increment less than zero.");
+
+ if (pageIncrement == 0)
+ pageIncrement = 1;
+
+ if (pageIncrement == this.pageIncrement)
+ return;
+
+ this.pageIncrement = pageIncrement;
+
+ ScrollbarPeer peer = (ScrollbarPeer) getPeer();
+ if (peer != null)
+ peer.setPageIncrement(this.pageIncrement);
+ }
+
+ /**
+ * Notifies this object to create its native peer.
+ */
+ public synchronized void addNotify()
+ {
+ if (peer == null)
+ peer = getToolkit().createScrollbar(this);
+ super.addNotify();
+ }
+
+ /**
+ * Adds a new adjustment listener to the list of registered listeners
+ * for this object.
+ *
+ * @param listener The listener to add.
+ */
+ public synchronized void addAdjustmentListener(AdjustmentListener listener)
+ {
+ adjustment_listeners = AWTEventMulticaster.add(adjustment_listeners,
+ listener);
+ enableEvents(AWTEvent.ADJUSTMENT_EVENT_MASK);
+ }
+
+ /**
+ * Removes the specified listener from the list of registered listeners
+ * for this object.
+ *
+ * @param listener The listener to remove.
+ */
+ public synchronized void removeAdjustmentListener(AdjustmentListener listener)
+ {
+ adjustment_listeners = AWTEventMulticaster.remove(adjustment_listeners,
+ listener);
+ }
+
+ /**
+ * Processes events for this scrollbar. It does this by calling
+ * <code>processAdjustmentEvent()</code> if the event is an instance of
+ * <code>AdjustmentEvent</code>, otherwise it calls the superclass to
+ * process the event.
+ *
+ * @param event The event to process.
+ */
+ protected void processEvent(AWTEvent event)
+ {
+ if (event instanceof AdjustmentEvent)
+ processAdjustmentEvent((AdjustmentEvent) event);
+ else
+ super.processEvent(event);
+ }
+
+ /**
+ * Processes adjustment events for this object by dispatching them to
+ * any registered listeners. Note that this method will only be called
+ * if adjustment events are enabled. This will happen automatically if
+ * any listeners are registered. Otherwise, it can be enabled by a
+ * call to <code>enableEvents()</code>.
+ *
+ * @param event The event to process.
+ */
+ protected void processAdjustmentEvent(AdjustmentEvent event)
+ {
+ value = event.getValue();
+ if (adjustment_listeners != null)
+ adjustment_listeners.adjustmentValueChanged(event);
+ }
+
+ /**
+ * Package private method to determine whether to call
+ * processEvent() or not. Will handle events from peer and update
+ * the current value.
+ */
+ void dispatchEventImpl(AWTEvent e)
+ {
+ if (e.id <= AdjustmentEvent.ADJUSTMENT_LAST
+ && e.id >= AdjustmentEvent.ADJUSTMENT_FIRST)
+ {
+ AdjustmentEvent ae = (AdjustmentEvent) e;
+ boolean adjusting = ae.getValueIsAdjusting();
+ if (adjusting)
+ setValueIsAdjusting(true);
+ try
+ {
+ setValue(((AdjustmentEvent) e).getValue());
+ if (adjustment_listeners != null
+ || (eventMask & AWTEvent.ADJUSTMENT_EVENT_MASK) != 0)
+ processEvent(e);
+ }
+ finally
+ {
+ if (adjusting)
+ setValueIsAdjusting(false);
+ }
+ }
+ else
+ super.dispatchEventImpl(e);
+ }
+
+ /**
+ * Returns a debugging string for this object.
+ *
+ * @return A debugging string for this object.
+ */
+ protected String paramString()
+ {
+ return ("value=" + getValue() + ",visibleAmount=" + getVisibleAmount()
+ + ",minimum=" + getMinimum() + ",maximum=" + getMaximum()
+ + ",pageIncrement=" + pageIncrement + ",lineIncrement="
+ + lineIncrement + ",orientation="
+ + (orientation == HORIZONTAL ? "HORIZONTAL" : "VERTICAL")
+ + super.paramString());
+ }
+
+ /**
+ * Returns an array of all the objects currently registered as FooListeners
+ * upon this <code>Scrollbar</code>. FooListeners are registered using the
+ * addFooListener method.
+ *
+ * @exception ClassCastException If listenerType doesn't specify a class or
+ * interface that implements java.util.EventListener.
+ */
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
+ {
+ if (listenerType == AdjustmentListener.class)
+ return AWTEventMulticaster.getListeners(adjustment_listeners,
+ listenerType);
+
+ return super.getListeners(listenerType);
+ }
+
+ /**
+ * Returns an array of all registered adjustment listeners.
+ */
+ public AdjustmentListener[] getAdjustmentListeners()
+ {
+ return (AdjustmentListener[]) getListeners(AdjustmentListener.class);
+ }
+
+ /**
+ * Returns true if the value is in the process of changing.
+ *
+ * @since 1.4
+ */
+ public boolean getValueIsAdjusting()
+ {
+ return valueIsAdjusting;
+ }
+
+ /**
+ * Sets the value of valueIsAdjusting.
+ *
+ * @since 1.4
+ */
+ public void setValueIsAdjusting(boolean valueIsAdjusting)
+ {
+ this.valueIsAdjusting = valueIsAdjusting;
+ }
+
+ /**
+ * Generate a unique name for this scroll bar.
+ *
+ * @return A unique name for this scroll bar.
+ */
+ String generateName()
+ {
+ return "scrollbar" + getUniqueLong();
+ }
+
+ private static synchronized long getUniqueLong()
+ {
+ return next_scrollbar_number++;
+ }
+
+ /**
+ * This class provides accessibility support for the
+ * scrollbar.
+ *
+ * @author Jerry Quinn (jlquinn@optonline.net)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+ protected class AccessibleAWTScrollBar extends AccessibleAWTComponent
+ implements AccessibleValue
+ {
+ /**
+ * Serialization constant to match JDK 1.5
+ */
+ private static final long serialVersionUID = -344337268523697807L;
+
+ /**
+ * Returns the role of this accessible object.
+ *
+ * @return the instance of <code>AccessibleRole</code>,
+ * which describes this object.
+ *
+ * @see javax.accessibility.AccessibleRole
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.SCROLL_BAR;
+ }
+
+ /**
+ * Returns the state set of this accessible object.
+ *
+ * @return a set of <code>AccessibleState</code>s which
+ * represent the current state of the accessible object.
+ *
+ * @see javax.accessibility.AccessibleState
+ * @see javax.accessibility.AccessibleStateSet
+ */
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ AccessibleStateSet states = super.getAccessibleStateSet();
+ if (getOrientation() == HORIZONTAL)
+ states.add(AccessibleState.HORIZONTAL);
+ else
+ states.add(AccessibleState.VERTICAL);
+ if (getValueIsAdjusting())
+ states.add(AccessibleState.BUSY);
+ return states;
+ }
+
+ /**
+ * Returns an implementation of the <code>AccessibleValue</code>
+ * interface for this accessible object. In this case, the
+ * current instance is simply returned (with a more appropriate
+ * type), as it also implements the accessible value as well as
+ * the context.
+ *
+ * @return the accessible value associated with this context.
+ *
+ * @see javax.accessibility.AccessibleValue
+ */
+ public AccessibleValue getAccessibleValue()
+ {
+ return this;
+ }
+
+ /**
+ * Returns the current value of this accessible object.
+ * In this case, this is the same as the value for
+ * the scrollbar, wrapped in an <code>Integer</code>
+ * object.
+ *
+ * @return the numeric value of this scrollbar.
+ *
+ * @see javax.accessibility.AccessibleValue#getCurrentAccessibleValue()
+ */
+ public Number getCurrentAccessibleValue()
+ {
+ return new Integer(getValue());
+ }
+
+ /**
+ * Sets the current value of this accessible object
+ * to that supplied. In this case, the value of the
+ * scrollbar is set, and this method always returns
+ * true.
+ *
+ * @param number the new accessible value.
+ *
+ * @return true if the value was set.
+ *
+ * @see javax.accessibility.AccessibleValue#setCurrentAccessibleValue(java.lang.Number)
+ */
+ public boolean setCurrentAccessibleValue(Number number)
+ {
+ setValue(number.intValue());
+ return true;
+ }
+
+ /**
+ * Returns the minimum acceptable accessible value used
+ * by this object. In this case, this is the same as
+ * the minimum value of the scrollbar, wrapped in an
+ * object.
+ *
+ * @return the minimum value of this scrollbar.
+ *
+ * @see javax.accessibility.AccessibleValue#getMinimumAccessibleValue()
+ */
+ public Number getMinimumAccessibleValue()
+ {
+ return new Integer(getMinimum());
+ }
+
+ /**
+ * Returns the maximum acceptable accessible value used
+ * by this object. In this case, this is the same as
+ * the maximum value of the scrollbar, wrapped in an
+ * object.
+ *
+ * @return the maximum value of this scrollbar.
+ *
+ * @see javax.accessibility.AccessibleValue#getMaximumAccessibleValue()
+ */
+ public Number getMaximumAccessibleValue()
+ {
+ return new Integer(getMaximum());
+ }
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>Scrollbar</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTScrollBar();
+
+ return accessibleContext;
+ }
+}
diff --git a/libjava/classpath/java/awt/Shape.java b/libjava/classpath/java/awt/Shape.java
new file mode 100644
index 000000000..495a980cb
--- /dev/null
+++ b/libjava/classpath/java/awt/Shape.java
@@ -0,0 +1,205 @@
+/* Shape.java -- the classic Object-Oriented shape interface
+ Copyright (C) 1999, 2002, 2005, 2006, Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * This interface represents an abstract shape. The shape is described by
+ * a {@link PathIterator}, and has callbacks for determining bounding box,
+ * where points and rectangles lie in relation to the shape, and tracing
+ * the trajectory.
+ *
+ * <p>A point is inside if it is completely inside, or on the boundary and
+ * adjacent points in the increasing x or y direction are completely inside.
+ * Unclosed shapes are considered as implicitly closed when performing
+ * <code>contains</code> or <code>intersects</code>.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see PathIterator
+ * @see AffineTransform
+ * @see java.awt.geom.FlatteningPathIterator
+ * @see java.awt.geom.GeneralPath
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public interface Shape
+{
+ /**
+ * Returns a <code>Rectange</code> that bounds the shape. There is no
+ * guarantee that this is the minimum bounding box, particularly if
+ * the shape overflows the finite integer range of a bound. Generally,
+ * <code>getBounds2D</code> returns a tighter bound.
+ *
+ * @return the shape's bounding box
+ * @see #getBounds2D()
+ */
+ Rectangle getBounds();
+
+ /**
+ * Returns a high precision bounding box of the shape. There is no guarantee
+ * that this is the minimum bounding box, but at least it never overflows.
+ *
+ * @return the shape's bounding box
+ * @see #getBounds()
+ * @since 1.2
+ */
+ Rectangle2D getBounds2D();
+
+ /**
+ * Test if the coordinates lie in the shape.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @return true if (x,y) lies inside the shape
+ * @since 1.2
+ */
+ boolean contains(double x, double y);
+
+ /**
+ * Test if the point lie in the shape.
+ *
+ * @param p the high-precision point
+ * @return true if p lies inside the shape
+ * @throws NullPointerException if p is null
+ * @since 1.2
+ */
+ boolean contains(Point2D p);
+
+ /**
+ * Test if a high-precision rectangle intersects the shape. This is true
+ * if any point in the rectangle is in the shape, with the caveat that the
+ * operation may include high probability estimates when the actual
+ * calculation is prohibitively expensive. The {@link java.awt.geom.Area}
+ * class can be used for more precise answers.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle, undefined results if negative
+ * @param h the height of the rectangle, undefined results if negative
+ * @return true if the rectangle intersects this shape
+ * @see java.awt.geom.Area
+ * @since 1.2
+ */
+ boolean intersects(double x, double y, double w, double h);
+
+ /**
+ * Test if a high-precision rectangle intersects the shape. This is true
+ * if any point in the rectangle is in the shape, with the caveat that the
+ * operation may include high probability estimates when the actual
+ * calculation is prohibitively expensive. The {@link java.awt.geom.Area}
+ * class can be used for more precise answers.
+ *
+ * @param r the rectangle
+ * @return true if the rectangle intersects this shape
+ * @throws NullPointerException if r is null
+ * @see #intersects(double, double, double, double)
+ * @since 1.2
+ */
+ boolean intersects(Rectangle2D r);
+
+ /**
+ * Test if a high-precision rectangle lies completely in the shape. This is
+ * true if all points in the rectangle are in the shape, with the caveat
+ * that the operation may include high probability estimates when the actual
+ * calculation is prohibitively expensive. The {@link java.awt.geom.Area}
+ * class can be used for more precise answers.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle, undefined results if negative
+ * @param h the height of the rectangle, undefined results if negative
+ * @return true if the rectangle is contained in this shape
+ * @see java.awt.geom.Area
+ * @since 1.2
+ */
+ boolean contains(double x, double y, double w, double h);
+
+ /**
+ * Test if a high-precision rectangle lies completely in the shape. This is
+ * true if all points in the rectangle are in the shape, with the caveat
+ * that the operation may include high probability estimates when the actual
+ * calculation is prohibitively expensive. The {@link java.awt.geom.Area}
+ * class can be used for more precise answers.
+ *
+ * @param r the rectangle
+ * @return true if the rectangle is contained in this shape
+ * @throws NullPointerException if r is null
+ * @see #contains(double, double, double, double)
+ * @since 1.2
+ */
+ boolean contains(Rectangle2D r);
+
+ /**
+ * Return an iterator along the shape boundary. If the optional transform
+ * is provided, the iterator is transformed accordingly. Each call returns
+ * a new object, independent from others in use. It is recommended, but
+ * not required, that the Shape isolate iterations from future changes to
+ * the boundary, and document this fact.
+ *
+ * @param transform an optional transform to apply to the
+ * iterator (<code>null</code> permitted).
+ * @return a new iterator over the boundary
+ * @since 1.2
+ */
+ PathIterator getPathIterator(AffineTransform transform);
+
+ /**
+ * Return an iterator along the flattened version of the shape boundary.
+ * Only SEG_MOVETO, SEG_LINETO, and SEG_CLOSE points are returned in the
+ * iterator. The flatness parameter controls how far points are allowed to
+ * differ from the real curve; although a limit on accuracy may cause this
+ * parameter to be enlarged if needed.
+ *
+ * <p>If the optional transform is provided, the iterator is transformed
+ * accordingly. Each call returns a new object, independent from others in
+ * use. It is recommended, but not required, that the Shape isolate
+ * iterations from future changes to the boundary, and document this fact.
+ *
+ * @param transform an optional transform to apply to the
+ * iterator (<code>null</code> permitted).
+ * @param flatness the maximum distance for deviation from the real boundary
+ * @return a new iterator over the boundary
+ * @since 1.2
+ */
+ PathIterator getPathIterator(AffineTransform transform, double flatness);
+}
diff --git a/libjava/classpath/java/awt/Stroke.java b/libjava/classpath/java/awt/Stroke.java
new file mode 100644
index 000000000..1a4c61cfb
--- /dev/null
+++ b/libjava/classpath/java/awt/Stroke.java
@@ -0,0 +1,65 @@
+/* Stroke.java -- a stroked outline of a shape
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+/**
+ * This interface allows a Graphics2D to grab the outline of a shape, as if
+ * stroked by a marking pen of appropriate size and shape. The area inked
+ * by the pen is the area of this stroke. Anything in the graphic which
+ * traces an outline will use this stroke, such as <code>drawLine</code>.
+ * Strokes must be immutable, because the graphics object does not clone
+ * them.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see BasicStroke
+ * @see Graphics2D#setStroke(Stroke)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface Stroke
+{
+ /**
+ * Returns a shape which outlines the boundary of the given shape, in
+ * effect converting the infinitely thin line into a new shape.
+ *
+ * @param s the shape to stroke
+ * @return the stroked outline shape
+ */
+ Shape createStrokedShape(Shape s);
+} // interface Stroke
diff --git a/libjava/classpath/java/awt/SystemColor.java b/libjava/classpath/java/awt/SystemColor.java
new file mode 100644
index 000000000..95bcaa696
--- /dev/null
+++ b/libjava/classpath/java/awt/SystemColor.java
@@ -0,0 +1,462 @@
+/* SystemColor.java -- access dynamic system color values
+ Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.ColorModel;
+import java.io.Serializable;
+
+/**
+ * This class contains the various "system colors" in use by the native
+ * windowing system. The <code>getRGB()</code> method is dynamic on systems
+ * which support dynamic system color changes, and most methods in the
+ * superclass are written to use this dynamic value when reporting colors.
+ * However, the <code>equals()</code> method is not dynamic, and does not
+ * track the actual color of instances in this class. This means that equals
+ * may give surprising results; you are better off relying on getRGB.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public final class SystemColor extends Color implements Serializable
+{
+ // Implementation note: To be serial compatible with JDK, this class must
+ // violate the semantic meaning of super.value to be one of the
+ // NUM_COLORS constants instead of the actual RGB value. Hence there are
+ // a lot of ugly workarounds in Color and in this class. I would have
+ // designed it MUCH differently, making a separate id field in this class.
+
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 4503142729533789064L;
+
+ /**
+ * Array index of the desktop color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #desktop
+ */
+ public static final int DESKTOP = 0;
+
+ /**
+ * Array index of the active caption color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #activeCaption
+ */
+ public static final int ACTIVE_CAPTION = 1;
+
+ /**
+ * Array index of the active caption text color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #activeCaptionText
+ */
+ public static final int ACTIVE_CAPTION_TEXT = 2;
+
+ /**
+ * Array index of the active caption border color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #activeCaptionBorder
+ */
+ public static final int ACTIVE_CAPTION_BORDER = 3;
+
+ /**
+ * Array index of the inactive caption color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #inactiveCaption
+ */
+ public static final int INACTIVE_CAPTION = 4;
+
+ /**
+ * Array index of the inactive caption text color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #inactiveCaptionText
+ */
+ public static final int INACTIVE_CAPTION_TEXT = 5;
+
+ /**
+ * Array index of the inactive caption border color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #inactiveCaptionBorder
+ */
+ public static final int INACTIVE_CAPTION_BORDER = 6;
+
+ /**
+ * Array index of the window background color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #window
+ */
+ public static final int WINDOW = 7;
+
+ /**
+ * Array index of the window border color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #windowBorder
+ */
+ public static final int WINDOW_BORDER = 8;
+
+ /**
+ * Array index of the window text color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #windowText
+ */
+ public static final int WINDOW_TEXT = 9;
+
+ /**
+ * Array index of the menu background color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #menu
+ */
+ public static final int MENU = 10;
+
+ /**
+ * Array index of the menu text color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #menuText
+ */
+ public static final int MENU_TEXT = 11;
+
+ /**
+ * Array index of the text background color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #text
+ */
+ public static final int TEXT = 12;
+
+ /**
+ * Array index of the text foreground color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #textText
+ */
+ public static final int TEXT_TEXT = 13;
+
+ /**
+ * Array index of the highlighted text background color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #textHighlight
+ */
+ public static final int TEXT_HIGHLIGHT = 14;
+
+ /**
+ * Array index of the highlighted text foreground color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #textHighlightText
+ */
+ public static final int TEXT_HIGHLIGHT_TEXT = 15;
+
+ /**
+ * Array index of the inactive text foreground color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #textInactiveText
+ */
+ public static final int TEXT_INACTIVE_TEXT = 16;
+
+ /**
+ * Array index of the control background color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #control
+ */
+ public static final int CONTROL = 17;
+
+ /**
+ * Array index of the control text color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #controlText
+ */
+ public static final int CONTROL_TEXT = 18;
+
+ /**
+ * Array index of the highlighted control background color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #controlHighlight
+ */
+ public static final int CONTROL_HIGHLIGHT = 19;
+
+ /**
+ * Array index of the lightly highlighted control background color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #controlLtHighlight
+ */
+ public static final int CONTROL_LT_HIGHLIGHT = 20;
+
+ /**
+ * Array index of the shadowed control background color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #controlShadow
+ */
+ public static final int CONTROL_SHADOW = 21;
+
+ /**
+ * Array index of the darkly shadowed control background color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #controlDkShadow
+ */
+ public static final int CONTROL_DK_SHADOW = 22;
+
+ /**
+ * Array index of the scrollbar background color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #scrollbar
+ */
+ public static final int SCROLLBAR = 23;
+
+ /**
+ * Array index of the info background color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #info
+ */
+ public static final int INFO = 24;
+
+ /**
+ * Array index of the info text color. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ *
+ * @see #infoText
+ */
+ public static final int INFO_TEXT = 25;
+
+ /**
+ * The number of system colors. Used by
+ * {@link Toolkit#loadSystemColors(int[])}.
+ */
+ public static final int NUM_COLORS = 26;
+
+ /**
+ * The internal array used to dynamically update <code>getRGB()</code>.
+ */
+ private static final int[] colors = new int[NUM_COLORS];
+
+ /** The desktop color. */
+ public static final SystemColor desktop
+ = new SystemColor(DESKTOP);
+
+ /** The active caption background color. */
+ public static final SystemColor activeCaption
+ = new SystemColor(ACTIVE_CAPTION);
+
+ /** The active caption text color. */
+ public static final SystemColor activeCaptionText
+ = new SystemColor(ACTIVE_CAPTION_TEXT);
+
+ /** The active caption border color. */
+ public static final SystemColor activeCaptionBorder
+ = new SystemColor(ACTIVE_CAPTION_BORDER);
+
+ /** The inactive caption background color. */
+ public static final SystemColor inactiveCaption
+ = new SystemColor(INACTIVE_CAPTION);
+
+ /** The inactive caption text color. */
+ public static final SystemColor inactiveCaptionText
+ = new SystemColor(INACTIVE_CAPTION_TEXT);
+
+ /** The inactive caption border color. */
+ public static final SystemColor inactiveCaptionBorder
+ = new SystemColor(INACTIVE_CAPTION_BORDER);
+
+ /** The window background color. */
+ public static final SystemColor window
+ = new SystemColor(WINDOW);
+
+ /** The window border color. */
+ public static final SystemColor windowBorder
+ = new SystemColor(WINDOW_BORDER);
+
+ /** The window text color. */
+ public static final SystemColor windowText
+ = new SystemColor(WINDOW_TEXT);
+
+ /** The menu background color. */
+ public static final SystemColor menu
+ = new SystemColor(MENU);
+
+ /** The menu text color. */
+ public static final SystemColor menuText
+ = new SystemColor(MENU_TEXT);
+
+ /** The text background color. */
+ public static final SystemColor text
+ = new SystemColor(TEXT);
+
+ /** The text foreground color. */
+ public static final SystemColor textText
+ = new SystemColor(TEXT_TEXT);
+
+ /** The highlighted text background color. */
+ public static final SystemColor textHighlight
+ = new SystemColor(TEXT_HIGHLIGHT);
+
+ /** The highlighted text foreground color. */
+ public static final SystemColor textHighlightText
+ = new SystemColor(TEXT_HIGHLIGHT_TEXT);
+
+ /** The inactive text color. */
+ public static final SystemColor textInactiveText
+ = new SystemColor(TEXT_INACTIVE_TEXT);
+
+ /** The control background color. */
+ public static final SystemColor control
+ = new SystemColor(CONTROL);
+
+ /** The control text color. */
+ public static final SystemColor controlText
+ = new SystemColor(CONTROL_TEXT);
+
+ /** The control highlight color. */
+ public static final SystemColor controlHighlight
+ = new SystemColor(CONTROL_HIGHLIGHT);
+
+ /** The control light highlight color. */
+ public static final SystemColor controlLtHighlight
+ = new SystemColor(CONTROL_LT_HIGHLIGHT);
+
+ /** The control shadow color. */
+ public static final SystemColor controlShadow
+ = new SystemColor(CONTROL_SHADOW);
+
+ /** The control dark shadow color. */
+ public static final SystemColor controlDkShadow
+ = new SystemColor(CONTROL_DK_SHADOW);
+
+ /** The scrollbar color. */
+ public static final SystemColor scrollbar
+ = new SystemColor(SCROLLBAR);
+
+ /** The info text background color. */
+ public static final SystemColor info
+ = new SystemColor(INFO);
+
+ /** The info text foreground color. */
+ public static final SystemColor infoText
+ = new SystemColor(INFO_TEXT);
+
+ /**
+ * Construct a system color which is dynamically updated.
+ *
+ * @param id the color id
+ */
+ private SystemColor(int id)
+ {
+ // Note: See Color#Color(int, boolean) to explain why we use this
+ // particular constructor.
+ super(id, true);
+ }
+
+ /**
+ * Returns the RGB value for this color, in the sRGB color space. The blue
+ * value will be in bits 0-7, green in 8-15, red in 6-23, and the alpha
+ * value (bits 24-31) is 0xff. This is dynamically updated, so it may not
+ * match the results of <code>getRed()</code>, <code>getGreen()</code>, or
+ * <code>getBlue()</code>.
+ *
+ * @return the current RGB value
+ */
+ public int getRGB()
+ {
+ Toolkit.getDefaultToolkit().loadSystemColors(colors);
+ return colors[value] | ALPHA_MASK;
+ }
+
+ /**
+ * Returns a paint context, used for filling areas of a raster scan with
+ * the current value of this system color. Since the system colors may be
+ * dynamically updated, the returned value may not always be the same; but
+ * as the system color is solid, the context does not need any of the
+ * passed parameters to do its job.
+ *
+ * @param cm the requested color model
+ * @param deviceBounds the bounding box in device coordinates, ignored
+ * @param userBounds the bounding box in user coordinates, ignored
+ * @param xform the bounds transformation, ignored
+ * @param hints any rendering hints, ignored
+ * @return a context for painting this solid color
+ */
+ public PaintContext createContext(ColorModel cm, Rectangle deviceBounds,
+ Rectangle2D userBounds,
+ AffineTransform xform,
+ RenderingHints hints)
+ {
+ Toolkit.getDefaultToolkit().loadSystemColors(colors);
+ int color = colors[value] | ALPHA_MASK;
+ if (context == null || color != context.color || !context.getColorModel().equals(cm))
+ context = new ColorPaintContext(cm,color);
+ return context;
+ }
+
+ /**
+ * Returns a string describing this color. This is in the format
+ * "java.awt.SystemColor[i=" + index + ']', where index is one of the
+ * integer constants of this class. Unfortunately, this description
+ * does not describe the current value of the color; for that you should
+ * use <code>new Color(syscolor.getRGB()).toString()</code>.
+ *
+ * @return a string describing this color
+ */
+ public String toString()
+ {
+ return "java.awt.SystemColor[i=" + value + ']';
+ }
+} // class SystemColor
diff --git a/libjava/classpath/java/awt/TextArea.java b/libjava/classpath/java/awt/TextArea.java
new file mode 100644
index 000000000..265f8c8b6
--- /dev/null
+++ b/libjava/classpath/java/awt/TextArea.java
@@ -0,0 +1,631 @@
+/* TextArea.java -- A multi-line text entry component
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.KeyEvent;
+import java.awt.peer.ComponentPeer;
+import java.awt.peer.TextAreaPeer;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleStateSet;
+
+
+/**
+ * A TextArea is a text component capable of displaying multiple lines
+ * of user-editable text. A TextArea handles its own scrolling and
+ * can display vertical and horizontal scrollbars as navigation aids.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class TextArea extends TextComponent implements java.io.Serializable
+{
+ /**
+ * Display both horiztonal and vertical scroll bars.
+ */
+ public static final int SCROLLBARS_BOTH = 0;
+
+ /**
+ * Display vertical scroll bar only.
+ */
+ public static final int SCROLLBARS_VERTICAL_ONLY = 1;
+
+ /**
+ * Display horizatonal scroll bar only.
+ */
+ public static final int SCROLLBARS_HORIZONTAL_ONLY = 2;
+
+ /**
+ * Do not display scrollbars.
+ */
+ public static final int SCROLLBARS_NONE = 3;
+
+ /**
+ * Serialization constant.
+ */
+ private static final long serialVersionUID = 3692302836626095722L;
+
+ /**
+ * @serial The number of columns used in this text area's preferred
+ * and minimum size calculations.
+ */
+ private int columns;
+
+ /**
+ * @serial The number of rows used in this text area's preferred and
+ * minimum size calculations.
+ */
+ private int rows;
+
+ /**
+ * @serial The scrollbar display policy. One of SCROLLBARS_BOTH,
+ * SCROLLBARS_VERTICAL_ONLY, SCROLLBARS_HORIZONTAL_ONLY,
+ * SCROLLBARS_NONE.
+ */
+ private int scrollbarVisibility;
+
+ /*
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_text_number;
+
+ /**
+ * Initialize a new instance of <code>TextArea</code> that is empty.
+ * Conceptually the <code>TextArea</code> has 0 rows and 0 columns
+ * but its initial bounds are defined by its peer or by the
+ * container in which it is packed. Both horizontal and vertical
+ * scrollbars will be displayed.
+ *
+ * @exception HeadlessException if GraphicsEnvironment.isHeadless () is true
+ */
+ public TextArea ()
+ {
+ this ("", 0, 0, SCROLLBARS_BOTH);
+ }
+
+ /**
+ * Initialize a new instance of <code>TextArea</code> that contains
+ * the specified text. Conceptually the <code>TextArea</code> has 0
+ * rows and 0 columns but its initial bounds are defined by its peer
+ * or by the container in which it is packed. Both horizontal and
+ * veritcal scrollbars will be displayed. The TextArea initially contains
+ * the specified text. If text specified as <code>null<code>, it will
+ * be set to "".
+ *
+ * @param text The text to display in this text area (<code>null</code> permitted).
+ *
+ * @exception HeadlessException if GraphicsEnvironment.isHeadless () is true
+ */
+ public TextArea (String text)
+ {
+ this (text, 0, 0, SCROLLBARS_BOTH);
+ }
+
+ /**
+ * Initialize a new instance of <code>TextArea</code> that is empty
+ * and can display the specified number of rows and columns of text,
+ * without the need to scroll. Both horizontal and vertical
+ * scrollbars will be displayed.
+ *
+ * @param rows The number of rows in this text area.
+ * @param columns The number of columns in this text area.
+ *
+ * @exception HeadlessException if GraphicsEnvironment.isHeadless () is true
+ */
+ public TextArea (int rows, int columns)
+ {
+ this ("", rows, columns, SCROLLBARS_BOTH);
+ }
+
+ /**
+ * Initialize a new instance of <code>TextArea</code> that can
+ * display the specified number of rows and columns of text, without
+ * the need to scroll. The TextArea initially contains the
+ * specified text. If text specified as <code>null<code>, it will
+ * be set to "".
+ *
+ * @param text The text to display in this text area (<code>null</code> permitted).
+ * @param rows The number of rows in this text area.
+ * @param columns The number of columns in this text area.
+ *
+ * @exception HeadlessException if GraphicsEnvironment.isHeadless () is true
+ */
+ public TextArea (String text, int rows, int columns)
+ {
+ this (text, rows, columns, SCROLLBARS_BOTH);
+ }
+
+ /**
+ * Initialize a new instance of <code>TextArea</code> that initially
+ * contains the specified text. The TextArea can display the
+ * specified number of rows and columns of text, without the need to
+ * scroll. This constructor allows specification of the scroll bar
+ * display policy. The TextArea initially contains the specified text.
+ * If text specified as <code>null<code>, it will be set to "".
+ *
+ * @param text The text to display in this text area (<code>null</code> permitted).
+ * @param rows The number of rows in this text area.
+ * @param columns The number of columns in this text area.
+ * @param scrollbarVisibility The scroll bar display policy. One of
+ * SCROLLBARS_BOTH, SCROLLBARS_VERTICAL_ONLY,
+ * SCROLLBARS_HORIZONTAL_ONLY, SCROLLBARS_NONE.
+ *
+ * @exception HeadlessException if GraphicsEnvironment.isHeadless () is true
+ */
+ public TextArea (String text, int rows, int columns, int scrollbarVisibility)
+ {
+ super (text);
+
+ if (GraphicsEnvironment.isHeadless ())
+ throw new HeadlessException ();
+
+ if (rows < 0)
+ this.rows = 0;
+ else
+ this.rows = rows;
+
+ if (columns < 0)
+ this.columns = 0;
+ else
+ this.columns = columns;
+
+ if (scrollbarVisibility < 0 || scrollbarVisibility > 4)
+ this.scrollbarVisibility = SCROLLBARS_BOTH;
+ else
+ this.scrollbarVisibility = scrollbarVisibility;
+
+ // TextAreas need to receive tab key events so we override the
+ // default forward and backward traversal key sets.
+ Set s = new HashSet ();
+ s.add (AWTKeyStroke.getAWTKeyStroke (KeyEvent.VK_TAB,
+ KeyEvent.CTRL_DOWN_MASK));
+ setFocusTraversalKeys (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, s);
+ s = new HashSet ();
+ s.add (AWTKeyStroke.getAWTKeyStroke (KeyEvent.VK_TAB,
+ KeyEvent.SHIFT_DOWN_MASK
+ | KeyEvent.CTRL_DOWN_MASK));
+ setFocusTraversalKeys (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, s);
+ }
+
+ /**
+ * Retrieve the number of columns that this text area would prefer
+ * to display. This value may or may not correspond to the number
+ * of columns that are actually displayed.
+ *
+ * @return The preferred number of columns.
+ */
+ public int getColumns ()
+ {
+ return columns;
+ }
+
+ /**
+ * Set the preferred number of columns for this text area. This
+ * method does not cause the number of columns displayed by the text
+ * area to be updated, if the text area is currently visible.
+ *
+ * @param columns The preferred number of columns.
+ *
+ * @exception IllegalArgumentException If columns is less than zero.
+ */
+ public synchronized void setColumns (int columns)
+ {
+ if (columns < 0)
+ throw new IllegalArgumentException ("Value is less than zero: "
+ + columns);
+
+ this.columns = columns;
+ }
+
+ /**
+ * Retrieve the number of rows that this text area would prefer to
+ * display. This value may or may not correspond to the number of
+ * rows that are actually displayed.
+ *
+ * @return The preferred number of rows.
+ */
+ public int getRows ()
+ {
+ return rows;
+ }
+
+ /**
+ * Set the preferred number of rows for this text area. This method
+ * does not cause the number of columns displayed by the text area
+ * to be updated, if the text area is currently visible.
+ *
+ * @param rows The preferred number of rows.
+ *
+ * @exception IllegalArgumentException If rows is less than zero.
+ */
+ public synchronized void setRows (int rows)
+ {
+ if (rows < 1)
+ throw new IllegalArgumentException ("Value is less than one: " + rows);
+
+ this.rows = rows;
+ }
+
+ /**
+ * Retrieve the minimum size for this text area.
+ *
+ * @return The minimum size for this text field.
+ */
+ public Dimension getMinimumSize ()
+ {
+ return getMinimumSize (getRows (), getColumns ());
+ }
+
+ /**
+ * Retrieve the minimum size for this text area. If the minimum
+ * size has been set, then rows and columns are used in the calculation.
+ *
+ * @param rows The number of rows to use in the minimum size
+ * calculation.
+ * @param columns The number of columns to use in the minimum size
+ * calculation.
+ *
+ * @return The minimum size for this text area.
+ */
+ public Dimension getMinimumSize (int rows, int columns)
+ {
+ return minimumSize (rows, columns);
+ }
+
+ /**
+ * Retrieve the minimum size for this text area.
+ *
+ * @return The minimum size for this text area.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getMinimumSize ()</code>.
+ */
+ public Dimension minimumSize ()
+ {
+ return minimumSize (getRows (), getColumns ());
+ }
+
+ /**
+ * Retrieve the minimum size for this text area. If the minimum
+ * size has been set, then rows and columns are used in the calculation.
+ *
+ * @param rows The number of rows to use in the minimum size
+ * calculation.
+ * @param columns The number of columns to use in the minimum size
+ * calculation.
+ *
+ * @return The minimum size for this text area.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getMinimumSize (int, int)</code>.
+ */
+ public Dimension minimumSize (int rows, int columns)
+ {
+ if (isMinimumSizeSet())
+ return new Dimension(minSize);
+
+ TextAreaPeer peer = (TextAreaPeer) getPeer ();
+ if (peer == null)
+ return new Dimension (getWidth(), getHeight());
+
+ return peer.getMinimumSize (rows, columns);
+ }
+
+ /**
+ * Retrieve the preferred size for this text area.
+ *
+ * @return The preferred size for this text field.
+ */
+ public Dimension getPreferredSize ()
+ {
+ return getPreferredSize (getRows (), getColumns ());
+ }
+
+ /**
+ * Retrieve the preferred size for this text area. If the preferred
+ * size has been set, then rows and columns are used in the calculation.
+ *
+ * @param rows The number of rows to use in the preferred size
+ * calculation.
+ * @param columns The number of columns to use in the preferred size
+ * calculation.
+ *
+ * @return The preferred size for this text area.
+ */
+ public Dimension getPreferredSize (int rows, int columns)
+ {
+ return preferredSize (rows, columns);
+ }
+
+ /**
+ * Retrieve the preferred size for this text area.
+ *
+ * @return The preferred size for this text field.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getPreferredSize ()</code>.
+ */
+ public Dimension preferredSize ()
+ {
+ return preferredSize (getRows (), getColumns ());
+ }
+
+ /**
+ * Retrieve the preferred size for this text area. If the preferred
+ * size has been set, then rows and columns are used in the calculation.
+ *
+ * @param rows The number of rows to use in the preferred size
+ * calculation.
+ * @param columns The number of columns to use in the preferred size
+ * calculation.
+ *
+ * @return The preferred size for this text area.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getPreferredSize (int, int)</code>.
+ */
+ public Dimension preferredSize (int rows, int columns)
+ {
+ if (isPreferredSizeSet())
+ return new Dimension(prefSize);
+
+ TextAreaPeer peer = (TextAreaPeer) getPeer ();
+ if (peer == null)
+ return new Dimension (getWidth(), getHeight());
+
+ return peer.getPreferredSize (rows, columns);
+ }
+
+ /**
+ * Retrieve the scroll bar display policy -- one of SCROLLBARS_BOTH,
+ * SCROLLBARS_VERTICAL_ONLY, SCROLLBARS_HORIZONTAL_ONLY,
+ * SCROLLBARS_NONE.
+ *
+ * @return The current scroll bar display policy.
+ */
+ public int getScrollbarVisibility ()
+ {
+ return scrollbarVisibility;
+ }
+
+ /**
+ * Notify this object that it should create its native peer.
+ */
+ public void addNotify ()
+ {
+ if (getPeer () == null)
+ setPeer ((ComponentPeer) getToolkit().createTextArea (this));
+ }
+
+ /**
+ * Append the specified text to the end of the current text.
+ *
+ * @param str The text to append.
+ */
+ public void append (String str)
+ {
+ appendText (str);
+ }
+
+ /**
+ * Append the specified text to the end of the current text.
+ *
+ * @param str The text to append.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>append ()</code>.
+ */
+ public void appendText (String str)
+ {
+ TextAreaPeer peer = (TextAreaPeer) getPeer ();
+
+ if (peer != null)
+ peer.insert (str, peer.getText().length ());
+ else
+ setText(getText() + str);
+ }
+
+ /**
+ * Insert the specified text at the specified position. The first
+ * character in the text area is at position zero.
+ *
+ * @param str The text to insert.
+ * @param pos The position at which to insert text.
+ */
+ public void insert (String str, int pos)
+ {
+ insertText (str, pos);
+ }
+
+ /**
+ * Insert the specified text at the specified position. The first
+ * character in the text area is at position zero.
+ *
+ * @param str The text to insert.
+ * @param pos The position at which to insert text.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>insert ()</code>.
+ */
+ public void insertText (String str, int pos)
+ {
+ String tmp1 = null;
+ String tmp2 = null;
+
+ TextAreaPeer peer = (TextAreaPeer) getPeer ();
+
+ if (peer != null)
+ peer.insert (str, pos);
+ else
+ {
+ tmp1 = getText().substring(0, pos);
+ tmp2 = getText().substring(pos, getText().length());
+ setText(tmp1 + str + tmp2);
+ }
+ }
+
+ /**
+ * Replace a range of characters with the specified text. The
+ * character at the start position will be replaced, unless start ==
+ * end. The character at the end posistion will not be replaced.
+ * The first character in the text area is at position zero. The
+ * length of the replacement text may differ from the length of the
+ * text that is replaced.
+ *
+ * @param str The new text for the range.
+ * @param start The start position of the replacement range.
+ * @param end The end position of the replacement range.
+ */
+ public void replaceRange (String str, int start, int end)
+ {
+ replaceText (str, start, end);
+ }
+
+ /**
+ * Replace a range of characters with the specified text. The
+ * character at the start position will be replaced, unless start ==
+ * end. The character at the end posistion will not be replaced.
+ * The first character in the text area is at position zero. The
+ * length of the replacement text may differ from the length of the
+ * text that is replaced.
+ *
+ * @param str The new text for the range.
+ * @param start The start position of the replacement range.
+ * @param end The end position of the replacement range.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>replaceRange ()</code>.
+ */
+ public void replaceText (String str, int start, int end)
+ {
+ String tmp1 = null;
+ String tmp2 = null;
+
+ TextAreaPeer peer = (TextAreaPeer) getPeer();
+
+ if (peer != null)
+ peer.replaceRange(str, start, end);
+ else
+ {
+ tmp1 = getText().substring(0, start);
+ tmp2 = getText().substring(end, getText().length());
+ setText(tmp1 + str + tmp2);
+ }
+ }
+
+ /**
+ * Retrieve a debugging string for this text area.
+ *
+ * @return A debugging string for this text area.
+ */
+ protected String paramString ()
+ {
+ String sbVisibility = "";
+
+ switch (scrollbarVisibility)
+ {
+ case SCROLLBARS_BOTH:
+ sbVisibility = "both";
+ break;
+ case SCROLLBARS_VERTICAL_ONLY:
+ sbVisibility = "vertical-only";
+ break;
+ case SCROLLBARS_HORIZONTAL_ONLY:
+ sbVisibility = "horizontal-only";
+ break;
+ case SCROLLBARS_NONE:
+ sbVisibility = "none";
+ break;
+ }
+
+ String editable = "";
+ if (isEditable ())
+ editable = "editable,";
+
+ return getName () + "," + getX () + "," + getY () + "," + getWidth ()
+ + "x" + getHeight () + "," + "text=" + getText () + "," + editable
+ + "selection=" + getSelectionStart () + "-" + getSelectionEnd ()
+ + ",rows=" + rows + ",columns=" + columns + ",scrollbarVisibility="
+ + sbVisibility;
+ }
+
+ /**
+ * Generate a unique name for this text area.
+ *
+ * @return A unique name for this text area.
+ */
+ String generateName ()
+ {
+ return "text" + getUniqueLong ();
+ }
+
+ private static synchronized long getUniqueLong ()
+ {
+ return next_text_number++;
+ }
+
+ protected class AccessibleAWTTextArea extends AccessibleAWTTextComponent
+ {
+ private static final long serialVersionUID = 3472827823632144419L;
+
+ protected AccessibleAWTTextArea()
+ {
+ }
+
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ return super.getAccessibleStateSet();
+ }
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>TextArea</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTTextArea();
+ return accessibleContext;
+ }
+}
diff --git a/libjava/classpath/java/awt/TextComponent.java b/libjava/classpath/java/awt/TextComponent.java
new file mode 100644
index 000000000..31ea3f5de
--- /dev/null
+++ b/libjava/classpath/java/awt/TextComponent.java
@@ -0,0 +1,676 @@
+/* TextComponent.java -- Widgets for entering text
+ Copyright (C) 1999, 2002, 2003, 2006, Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.TextEvent;
+import java.awt.event.TextListener;
+import java.awt.peer.TextComponentPeer;
+import java.io.Serializable;
+import java.text.BreakIterator;
+import java.util.EventListener;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleState;
+import javax.accessibility.AccessibleStateSet;
+import javax.accessibility.AccessibleText;
+import javax.swing.text.AttributeSet;
+
+/**
+ * This class provides common functionality for widgets than
+ * contain text.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class TextComponent extends Component
+ implements Serializable, Accessible
+{
+
+ private static final long serialVersionUID = -2214773872412987419L;
+
+ /**
+ * @serial Indicates whether or not this component is editable.
+ * This is package-private to avoid an accessor method.
+ */
+ boolean editable;
+
+ /**
+ * @serial The starting position of the selected text region.
+ * This is package-private to avoid an accessor method.
+ */
+ int selectionStart;
+
+ /**
+ * @serial The ending position of the selected text region.
+ * This is package-private to avoid an accessor method.
+ */
+ int selectionEnd;
+
+ /**
+ * @serial The text in the component
+ * This is package-private to avoid an accessor method.
+ */
+ String text;
+
+ /**
+ * A list of listeners that will receive events from this object.
+ */
+ protected transient TextListener textListener;
+
+ protected class AccessibleAWTTextComponent
+ extends AccessibleAWTComponent
+ implements AccessibleText, TextListener
+ {
+ private static final long serialVersionUID = 3631432373506317811L;
+
+ // Constructor
+ // Adds a listener for tracking caret changes
+ public AccessibleAWTTextComponent()
+ {
+ TextComponent.this.addTextListener(this);
+ }
+
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.TEXT;
+ }
+
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ // TODO: Docs say PropertyChangeEvent will fire if this state changes.
+ // That means that the event has to fire when editable changes.
+ AccessibleStateSet ss = super.getAccessibleStateSet();
+ if (editable)
+ ss.add(AccessibleState.EDITABLE);
+ return ss;
+ }
+
+ public AccessibleText getAccessibleText()
+ {
+ return this;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleText#getIndexAtPoint(java.awt.Point)
+ */
+ public int getIndexAtPoint(Point point)
+ {
+ return TextComponent.this.getIndexAtPoint(point);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleText#getCharacterBounds(int)
+ */
+ public Rectangle getCharacterBounds(int index)
+ {
+ return TextComponent.this.getCharacterBounds(index);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleText#getCharCount()
+ */
+ public int getCharCount()
+ {
+ return text.length();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleText#getCaretPosition()
+ */
+ public int getCaretPosition()
+ {
+ return TextComponent.this.getCaretPosition();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleText#getAtIndex(int, int)
+ */
+ public String getAtIndex(int part, int index)
+ {
+ if (index < 0 || index >= text.length())
+ return null;
+ BreakIterator it = null;
+ switch (part)
+ {
+ case CHARACTER:
+ return text.substring(index, index + 1);
+ case WORD:
+ it = BreakIterator.getWordInstance();
+ break;
+ case SENTENCE:
+ it = BreakIterator.getSentenceInstance();
+ break;
+ default:
+ return null;
+ }
+ it.setText(text);
+ int start = index;
+ if (!it.isBoundary(index))
+ start = it.preceding(index);
+ int end = it.following(index);
+ if (end == -1)
+ return text.substring(index);
+ else
+ return text.substring(index, end);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleText#getAfterIndex(int, int)
+ */
+ public String getAfterIndex(int part, int index) {
+ if (index < 0 || index >= text.length())
+ return null;
+ BreakIterator it = null;
+ switch (part)
+ {
+ case CHARACTER:
+ return text.substring(index, index + 1);
+ case WORD:
+ it = BreakIterator.getWordInstance();
+ break;
+ case SENTENCE:
+ it = BreakIterator.getSentenceInstance();
+ break;
+ default:
+ return null;
+ }
+ it.setText(text);
+ int start = index;
+ if (!it.isBoundary(index))
+ start = it.following(index);
+ // Make sure there was a complete unit. I.e. if index is in the middle
+ // of a word, return null if there is no word after the that one.
+ if (start == -1)
+ return null;
+ int end = it.following(start);
+ if (end == -1)
+ return text.substring(index);
+ else
+ return text.substring(index, end);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleText#getBeforeIndex(int, int)
+ */
+ public String getBeforeIndex(int part, int index)
+ {
+ if (index < 1 || index >= text.length())
+ return null;
+ BreakIterator it = null;
+ switch (part)
+ {
+ case CHARACTER:
+ return text.substring(index - 1, index);
+ case WORD:
+ it = BreakIterator.getWordInstance();
+ break;
+ case SENTENCE:
+ it = BreakIterator.getSentenceInstance();
+ break;
+ default:
+ return null;
+ }
+ it.setText(text);
+ int end = index;
+ if (!it.isBoundary(index))
+ end = it.preceding(index);
+ // Make sure there was a complete unit. I.e. if index is in the middle
+ // of a word, return null if there is no word before that one.
+ if (end == -1)
+ return null;
+ int start = it.preceding(end);
+ if (start == -1)
+ return text.substring(0, end);
+ else
+ return text.substring(start, end);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleText#getCharacterAttribute(int)
+ */
+ public AttributeSet getCharacterAttribute(int index)
+ {
+ // FIXME: I suspect this really gets filled in by subclasses.
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleText#getSelectionStart()
+ */
+ public int getSelectionStart() {
+ // TODO Auto-generated method stub
+ return selectionStart;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleText#getSelectionEnd()
+ */
+ public int getSelectionEnd()
+ {
+ return selectionEnd;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.accessibility.AccessibleText#getSelectedText()
+ */
+ public String getSelectedText()
+ {
+ if (selectionEnd - selectionStart > 0)
+ return text.substring(selectionStart, selectionEnd);
+ else
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.event.TextListener#textValueChanged(java.awt.event.TextEvent)
+ */
+ public void textValueChanged(TextEvent event)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ }
+
+
+ TextComponent(String text)
+ {
+ if (text == null)
+ this.text = "";
+ else
+ this.text = text;
+
+ this.editable = true;
+ }
+
+
+ /**
+ * Returns the text in this component
+ *
+ * @return The text in this component.
+ */
+ public synchronized String getText()
+ {
+ TextComponentPeer tcp = (TextComponentPeer) getPeer();
+ if (tcp != null)
+ text = tcp.getText();
+
+ return(text);
+ }
+
+ /**
+ * Sets the text in this component to the specified string.
+ *
+ * @param text The new text for this component.
+ */
+ public synchronized void setText(String text)
+ {
+ if (text == null)
+ text = "";
+
+ this.text = text;
+
+ TextComponentPeer tcp = (TextComponentPeer) getPeer();
+ if (tcp != null)
+ tcp.setText(text);
+ setCaretPosition(0);
+ }
+
+ /**
+ * Returns a string that contains the text that is currently selected.
+ *
+ * @return The currently selected text region.
+ */
+ public synchronized String getSelectedText()
+ {
+ String alltext = getText();
+ int start = getSelectionStart();
+ int end = getSelectionEnd();
+
+ return(alltext.substring(start, end));
+ }
+
+ /**
+ * Returns the starting position of the selected text region.
+ * If the text is not selected then caret position is returned.
+ *
+ * @return The starting position of the selected text region.
+ */
+ public synchronized int getSelectionStart()
+ {
+ TextComponentPeer tcp = (TextComponentPeer) getPeer();
+ if (tcp != null)
+ selectionStart = tcp.getSelectionStart();
+
+ return(selectionStart);
+ }
+
+ /**
+ * Sets the starting position of the selected region to the
+ * specified value. If the specified value is out of range, then it
+ * will be silently changed to the nearest legal value.
+ *
+ * @param selectionStart The new start position for selected text.
+ */
+ public synchronized void setSelectionStart(int selectionStart)
+ {
+ select(selectionStart,
+ (getSelectionEnd() < selectionStart)
+ ? selectionStart : getSelectionEnd());
+ }
+
+ /**
+ * Returns the ending position of the selected text region.
+ * If the text is not selected, then caret position is returned
+ *
+ * @return The ending position of the selected text region.
+ */
+ public synchronized int getSelectionEnd()
+ {
+ TextComponentPeer tcp = (TextComponentPeer) getPeer();
+ if (tcp != null)
+ selectionEnd = tcp.getSelectionEnd();
+
+ return(selectionEnd);
+ }
+
+ /**
+ * Sets the ending position of the selected region to the
+ * specified value. If the specified value is out of range, then it
+ * will be silently changed to the nearest legal value.
+ *
+ * @param selectionEnd The new start position for selected text.
+ */
+ public synchronized void setSelectionEnd(int selectionEnd)
+ {
+ select(getSelectionStart(), selectionEnd);
+ }
+
+ /**
+ * This method sets the selected text range to the text between the
+ * specified start and end positions. Illegal values for these
+ * positions are silently fixed.
+ *
+ * @param selectionStart The new start position for the selected text.
+ * @param selectionEnd The new end position for the selected text.
+ */
+ public synchronized void select(int selectionStart, int selectionEnd)
+ {
+ if (selectionStart < 0)
+ selectionStart = 0;
+
+ if (selectionStart > getText().length())
+ selectionStart = text.length();
+
+ if (selectionEnd > text.length())
+ selectionEnd = text.length();
+
+ if (selectionStart > selectionEnd)
+ selectionStart = selectionEnd;
+
+ this.selectionStart = selectionStart;
+ this.selectionEnd = selectionEnd;
+
+ TextComponentPeer tcp = (TextComponentPeer) getPeer();
+ if (tcp != null)
+ tcp.select(selectionStart, selectionEnd);
+ }
+
+ /**
+ * Selects all of the text in the component.
+ */
+ public synchronized void selectAll()
+ {
+ select(0, getText().length());
+ }
+
+ /**
+ * Returns the current caret position in the text.
+ *
+ * @return The caret position in the text.
+ */
+ public synchronized int getCaretPosition()
+ {
+ TextComponentPeer tcp = (TextComponentPeer) getPeer();
+ if (tcp != null)
+ return(tcp.getCaretPosition());
+ else
+ return(0);
+ }
+
+ /**
+ * Sets the caret position to the specified value.
+ *
+ * @param caretPosition The new caret position.
+ *
+ * @exception IllegalArgumentException If the value supplied for position
+ * is less than zero.
+ *
+ * @since 1.1
+ */
+ public synchronized void setCaretPosition(int caretPosition)
+ {
+ if (caretPosition < 0)
+ throw new IllegalArgumentException();
+
+ TextComponentPeer tcp = (TextComponentPeer) getPeer();
+ if (tcp != null)
+ tcp.setCaretPosition(caretPosition);
+ }
+
+ /**
+ * Tests whether or not this component's text can be edited.
+ *
+ * @return <code>true</code> if the text can be edited, <code>false</code>
+ * otherwise.
+ */
+ public boolean isEditable()
+ {
+ return(editable);
+ }
+
+ /**
+ * Sets whether or not this component's text can be edited.
+ *
+ * @param editable <code>true</code> to enable editing of the text,
+ * <code>false</code> to disable it.
+ */
+ public synchronized void setEditable(boolean editable)
+ {
+ this.editable = editable;
+
+ TextComponentPeer tcp = (TextComponentPeer) getPeer();
+ if (tcp != null)
+ tcp.setEditable(editable);
+ }
+
+ /**
+ * Notifies the component that it should destroy its native peer.
+ */
+ public void removeNotify()
+ {
+ super.removeNotify();
+ }
+
+ /**
+ * Adds a new listener to the list of text listeners for this
+ * component.
+ *
+ * @param listener The listener to be added.
+ */
+ public synchronized void addTextListener(TextListener listener)
+ {
+ textListener = AWTEventMulticaster.add(textListener, listener);
+
+ enableEvents(AWTEvent.TEXT_EVENT_MASK);
+ }
+
+ /**
+ * Removes the specified listener from the list of listeners
+ * for this component.
+ *
+ * @param listener The listener to remove.
+ */
+ public synchronized void removeTextListener(TextListener listener)
+ {
+ textListener = AWTEventMulticaster.remove(textListener, listener);
+ }
+
+ /**
+ * Processes the specified event for this component. Text events are
+ * processed by calling the <code>processTextEvent()</code> method.
+ * All other events are passed to the superclass method.
+ *
+ * @param event The event to process.
+ */
+ protected void processEvent(AWTEvent event)
+ {
+ if (event instanceof TextEvent)
+ processTextEvent((TextEvent)event);
+ else
+ super.processEvent(event);
+ }
+
+ /**
+ * Processes the specified text event by dispatching it to any listeners
+ * that are registered. Note that this method will only be called
+ * if text event's are enabled. This will be true if there are any
+ * registered listeners, or if the event has been specifically
+ * enabled using <code>enableEvents()</code>.
+ *
+ * @param event The text event to process.
+ */
+ protected void processTextEvent(TextEvent event)
+ {
+ if (textListener != null)
+ textListener.textValueChanged(event);
+ }
+
+ void dispatchEventImpl(AWTEvent e)
+ {
+ if (e.id <= TextEvent.TEXT_LAST
+ && e.id >= TextEvent.TEXT_FIRST
+ && (textListener != null
+ || (eventMask & AWTEvent.TEXT_EVENT_MASK) != 0))
+ processEvent(e);
+ else
+ super.dispatchEventImpl(e);
+ }
+
+ /**
+ * Returns a debugging string.
+ *
+ * @return A debugging string.
+ */
+ protected String paramString()
+ {
+ return(getClass().getName() + "(text=" + getText() + ")");
+ }
+
+ /**
+ * Returns an array of all the objects currently registered as FooListeners
+ * upon this <code>TextComponent</code>. FooListeners are registered using
+ * the addFooListener method.
+ *
+ * @exception ClassCastException If listenerType doesn't specify a class or
+ * interface that implements java.util.EventListener.
+ */
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
+ {
+ if (listenerType == TextListener.class)
+ return AWTEventMulticaster.getListeners(textListener, listenerType);
+
+ return super.getListeners(listenerType);
+ }
+
+ /**
+ * Returns all text listeners registered to this object.
+ */
+ public TextListener[] getTextListeners()
+ {
+ return (TextListener[]) getListeners(TextListener.class);
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>TextComponent</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTTextComponent();
+ return accessibleContext;
+ }
+
+
+ // Provide AccessibleAWTTextComponent access to several peer functions that
+ // aren't publicly exposed. This is package-private to avoid an accessor
+ // method.
+ synchronized int getIndexAtPoint(Point p)
+ {
+ TextComponentPeer tcp = (TextComponentPeer) getPeer();
+ if (tcp != null)
+ return tcp.getIndexAtPoint(p.x, p.y);
+ return -1;
+ }
+
+ synchronized Rectangle getCharacterBounds(int i)
+ {
+ TextComponentPeer tcp = (TextComponentPeer) getPeer();
+ if (tcp != null)
+ return tcp.getCharacterBounds(i);
+ return null;
+ }
+
+ /**
+ * All old mouse events for this component should
+ * be ignored.
+ *
+ * @return true to ignore all old mouse events.
+ */
+ static boolean ignoreOldMouseEvents()
+ {
+ return true;
+ }
+
+} // class TextComponent
diff --git a/libjava/classpath/java/awt/TextField.java b/libjava/classpath/java/awt/TextField.java
new file mode 100644
index 000000000..5a58b440d
--- /dev/null
+++ b/libjava/classpath/java/awt/TextField.java
@@ -0,0 +1,484 @@
+/* TextField.java -- A one line text entry field
+ Copyright (C) 1999, 2002, 2004, 2006, Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.peer.ComponentPeer;
+import java.awt.peer.TextFieldPeer;
+import java.util.EventListener;
+
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleStateSet;
+
+/**
+ * This class implements a single line text entry field widget
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class TextField extends TextComponent
+{
+
+ /**
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_textfield_number;
+
+
+ private static final long serialVersionUID = -2966288784432217853L;
+
+
+ /**
+ * @serial The number of columns in the text entry field.
+ */
+ private int columns;
+
+ /**
+ * @serial The character that is echoed when doing protected input
+ */
+ private char echoChar;
+
+ // List of registered ActionListener's for this object.
+ private ActionListener action_listeners;
+
+ /**
+ * Initializes a new instance of <code>TextField</code> that is empty
+ * and has one column.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true,
+ */
+ public TextField()
+ {
+ this("", 0);
+ }
+
+ /**
+ * Initializes a new instance of <code>TextField</code> containing
+ * the specified text. The number of columns will be equal to the
+ * length of the text string.
+ *
+ * @param text The text to display in the field.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true,
+ */
+ public TextField(String text)
+ {
+ this(text, (text == null) ? 0 : text.length());
+ }
+
+ /**
+ * Initializes a new instance of <code>TextField</code> that is empty
+ * and has the specified number of columns.
+ *
+ * @param columns The number of columns in the text field.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true,
+ */
+ public TextField(int columns)
+ {
+ this("", columns);
+ }
+
+ /**
+ * Initializes a new instance of <code>TextField</code> with the
+ * specified text and number of columns.
+ *
+ * @param text The text to display in the field.
+ * @param columns The number of columns in the field.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true,
+ */
+ public TextField(String text, int columns)
+ {
+ super(text);
+
+ if (columns < 0)
+ this.columns = 0;
+ else
+ this.columns = columns;
+
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException ();
+ }
+
+ /**
+ * Returns the number of columns in the field.
+ *
+ * @return The number of columns in the field.
+ */
+ public int getColumns()
+ {
+ return(columns);
+ }
+
+ /**
+ * Sets the number of columns in this field to the specified value.
+ *
+ * @param columns The new number of columns in the field.
+ *
+ * @exception IllegalArgumentException If columns is less than zero.
+ */
+ public synchronized void setColumns(int columns)
+ {
+ if (columns < 0)
+ throw new IllegalArgumentException("Value is less than zero: " +
+ columns);
+
+ this.columns = columns;
+ // FIXME: How to we communicate this to our peer?
+ }
+
+ /**
+ * Returns the character that is echoed to the screen when a text
+ * field is protected (such as when a password is being entered).
+ *
+ * @return The echo character for this text field.
+ */
+ public char getEchoChar()
+ {
+ return(echoChar);
+ }
+
+ /**
+ * Sets the character that is echoed when protected input such as
+ * a password is displayed.
+ *
+ * @param echoChar The new echo character.
+ */
+ public void setEchoChar(char echoChar)
+ {
+ setEchoCharacter(echoChar);
+ }
+
+ /**
+ * Sets the character that is echoed when protected input such as
+ * a password is displayed.
+ *
+ * @param echoChar The new echo character.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>setEchoChar()</code>
+ */
+ public void setEchoCharacter(char echoChar)
+ {
+ this.echoChar = echoChar;
+
+ TextFieldPeer peer = (TextFieldPeer) getPeer ();
+ if (peer != null)
+ peer.setEchoChar (echoChar);
+ }
+
+ /**
+ * Tests whether or not this text field has an echo character set
+ * so that characters the user type are not echoed to the screen.
+ *
+ * @return <code>true</code> if an echo character is set,
+ * <code>false</code> otherwise.
+ */
+ public boolean echoCharIsSet()
+ {
+ if (echoChar == '\u0000')
+ return(false);
+ else
+ return(true);
+ }
+
+ /**
+ * Returns the minimum size for this text field.
+ *
+ * @return The minimum size for this text field.
+ */
+ public Dimension getMinimumSize()
+ {
+ return getMinimumSize (getColumns ());
+ }
+
+ /**
+ * Returns the minimum size of a text field with the specified number
+ * of columns.
+ *
+ * @param columns The number of columns to get the minimum size for.
+ */
+ public Dimension getMinimumSize(int columns)
+ {
+ return minimumSize(columns);
+ }
+
+ /**
+ * Returns the minimum size for this text field.
+ *
+ * @return The minimum size for this text field.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getMinimumSize()</code>.
+ */
+ public Dimension minimumSize()
+ {
+ return minimumSize(getColumns ());
+ }
+
+ /**
+ * Returns the minimum size of a text field with the specified number
+ * of columns.
+ *
+ * @param columns The number of columns to get the minimum size for.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getMinimumSize(int)</code>.
+ */
+ public Dimension minimumSize(int columns)
+ {
+ if (isMinimumSizeSet())
+ return new Dimension(minSize);
+
+ TextFieldPeer peer = (TextFieldPeer) getPeer ();
+ if (peer == null)
+ return new Dimension(getWidth(), getHeight());
+
+ return peer.getMinimumSize (columns);
+ }
+
+ /**
+ * Returns the preferred size for this text field.
+ *
+ * @return The preferred size for this text field.
+ */
+ public Dimension getPreferredSize()
+ {
+ return getPreferredSize(getColumns ());
+ }
+
+ /**
+ * Returns the preferred size of a text field with the specified number
+ * of columns.
+ *
+ * @param columns The number of columns to get the preferred size for.
+ */
+ public Dimension getPreferredSize(int columns)
+ {
+ return preferredSize(columns);
+ }
+
+ /**
+ * Returns the preferred size for this text field.
+ *
+ * @return The preferred size for this text field.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getPreferredSize()</code>.
+ */
+ public Dimension preferredSize()
+ {
+ return preferredSize(getColumns ());
+ }
+
+ /**
+ * Returns the preferred size of a text field with the specified number
+ * of columns.
+ *
+ * @param columns The number of columns to get the preferred size for.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getPreferredSize(int)</code>.
+ */
+ public Dimension preferredSize(int columns)
+ {
+ if (isPreferredSizeSet())
+ return new Dimension(prefSize);
+
+ TextFieldPeer peer = (TextFieldPeer) getPeer ();
+ if (peer == null)
+ return new Dimension (getWidth(), getHeight());
+
+ return peer.getPreferredSize (columns);
+ }
+
+ /**
+ * Notifies this object that it should create its native peer.
+ */
+ public void addNotify()
+ {
+ if (getPeer() != null)
+ return;
+
+ setPeer((ComponentPeer)getToolkit().createTextField(this));
+ super.addNotify();
+ }
+
+ /**
+ * Addes a new listener to the list of action listeners for this
+ * object.
+ *
+ * @param listener The listener to add to the list.
+ */
+ public synchronized void addActionListener(ActionListener listener)
+ {
+ action_listeners = AWTEventMulticaster.add(action_listeners, listener);
+
+ enableEvents(AWTEvent.ACTION_EVENT_MASK);
+ }
+
+ /**
+ * Removes the specified listener from the list of action listeners
+ * for this object.
+ *
+ * @param listener The listener to remove from the list.
+ */
+ public synchronized void removeActionListener(ActionListener listener)
+ {
+ action_listeners = AWTEventMulticaster.remove(action_listeners, listener);
+ }
+
+ /**
+ * Processes the specified event. If the event is an instance of
+ * <code>ActionEvent</code> then <code>processActionEvent()</code> is
+ * called to process it, otherwise the event is sent to the
+ * superclass.
+ *
+ * @param event The event to process.
+ */
+ protected void processEvent(AWTEvent event)
+ {
+ if (event instanceof ActionEvent)
+ processActionEvent((ActionEvent)event);
+ else
+ super.processEvent(event);
+ }
+
+ /**
+ * Processes an action event by calling any registered listeners.
+ * Note to subclasses: This method is not called unless action events
+ * are enabled on this object. This will be true if any listeners
+ * are registered, or if action events were specifically enabled
+ * using <code>enableEvents()</code>.
+ *
+ * @param event The event to process.
+ */
+ protected void processActionEvent(ActionEvent event)
+ {
+ if (action_listeners != null)
+ action_listeners.actionPerformed(event);
+ }
+
+ void dispatchEventImpl(AWTEvent e)
+ {
+ if (e.id <= ActionEvent.ACTION_LAST
+ && e.id >= ActionEvent.ACTION_FIRST
+ && (action_listeners != null
+ || (eventMask & AWTEvent.ACTION_EVENT_MASK) != 0))
+ processEvent(e);
+ else
+ super.dispatchEventImpl(e);
+ }
+
+ /**
+ * Returns a debug string for this object.
+ *
+ * @return A debug string for this object.
+ */
+ protected String paramString()
+ {
+ return(getClass().getName() + "(columns=" + getColumns() + ",echoChar=" +
+ getEchoChar());
+ }
+
+ /**
+ * Returns an array of all the objects currently registered as FooListeners
+ * upon this <code>TextField</code>. FooListeners are registered using the
+ * addFooListener method.
+ *
+ * @exception ClassCastException If listenerType doesn't specify a class or
+ * interface that implements java.util.EventListener.
+ *
+ * @since 1.3
+ */
+ public <T extends EventListener> T[] getListeners (Class<T> listenerType)
+ {
+ if (listenerType == ActionListener.class)
+ return AWTEventMulticaster.getListeners (action_listeners, listenerType);
+
+ return super.getListeners (listenerType);
+ }
+
+ /**
+ * Return all ActionListeners register to this <code>TextField</code> object
+ * as an array.
+ *
+ * @since 1.4
+ */
+ public ActionListener[] getActionListeners ()
+ {
+ return (ActionListener[]) getListeners (ActionListener.class);
+ }
+
+ /**
+ * Generate a unique name for this <code>TextField</code>.
+ *
+ * @return A unique name for this <code>TextField</code>.
+ */
+ String generateName()
+ {
+ return "textfield" + getUniqueLong();
+ }
+
+ private static synchronized long getUniqueLong()
+ {
+ return next_textfield_number++;
+ }
+
+ protected class AccessibleAWTTextField extends AccessibleAWTTextComponent
+ {
+ private static final long serialVersionUID = 6219164359235943158L;
+
+ protected AccessibleAWTTextField()
+ {
+ }
+
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ return super.getAccessibleStateSet();
+ }
+ }
+
+ public AccessibleContext getAccessibleContext()
+ {
+ return new AccessibleAWTTextField();
+ }
+
+}
diff --git a/libjava/classpath/java/awt/TexturePaint.java b/libjava/classpath/java/awt/TexturePaint.java
new file mode 100644
index 000000000..f88e77b23
--- /dev/null
+++ b/libjava/classpath/java/awt/TexturePaint.java
@@ -0,0 +1,118 @@
+/* TexturePaint.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import gnu.java.awt.java2d.TexturePaintContext;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+
+/**
+ * This class provides a way to fill a Shape with a texture that is
+ * specified by a BufferedImage.
+ */
+public class TexturePaint implements Paint
+{
+ private final BufferedImage texture;
+ private final Rectangle2D anchor;
+
+ /**
+ * Constructor.
+ *
+ * @param texture - the texture
+ * @param anchor - the shape
+ */
+ public TexturePaint(BufferedImage texture, Rectangle2D anchor)
+ {
+ this.texture = texture;
+ this.anchor = anchor;
+ }
+
+ /**
+ * Gets the texture image.
+ *
+ * @return the texture
+ */
+ public BufferedImage getImage()
+ {
+ return texture;
+ }
+
+ /**
+ * Gets the shape anchor.
+ *
+ * @return the shape anchor
+ */
+ public Rectangle2D getAnchorRect()
+ {
+ return anchor;
+ }
+
+ /**
+ * Creates the context used to paint the texture.
+ *
+ * @param cm - the ColorModel that receives the Paint data. Used only as a hint.
+ * @param deviceBounds - the device space being rendered.
+ * @param userBounds - the user space being rendered
+ * @param xform - the AffineTransform from user space into device space
+ * @param hints - a RenderingHints object that is used to specify how the
+ * pattern is rendered
+ * @return the paint context used to paint the texture
+ */
+ public PaintContext createContext(ColorModel cm, Rectangle deviceBounds,
+ Rectangle2D userBounds,
+ AffineTransform xform, RenderingHints hints)
+ {
+ // TODO: Maybe add some hook for providing alternative/accelerated
+ // implementations of this.
+ return new TexturePaintContext(this, deviceBounds, userBounds, xform);
+ }
+
+ /**
+ * Returns the transparency mode.
+ *
+ * @return the transparency mode.
+ */
+ public int getTransparency()
+ {
+ return texture.getTransparency();
+ }
+} // class TexturePaint
diff --git a/libjava/classpath/java/awt/Toolkit.java b/libjava/classpath/java/awt/Toolkit.java
new file mode 100644
index 000000000..6b1eb9d4b
--- /dev/null
+++ b/libjava/classpath/java/awt/Toolkit.java
@@ -0,0 +1,1429 @@
+/* Toolkit.java -- AWT Toolkit superclass
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import gnu.classpath.SystemProperties;
+import gnu.java.awt.AWTUtilities;
+import gnu.java.awt.peer.GLightweightPeer;
+import gnu.java.awt.peer.headless.HeadlessToolkit;
+
+import java.awt.datatransfer.Clipboard;
+import java.awt.dnd.DragGestureEvent;
+import java.awt.dnd.DragGestureListener;
+import java.awt.dnd.DragGestureRecognizer;
+import java.awt.dnd.DragSource;
+import java.awt.dnd.peer.DragSourceContextPeer;
+import java.awt.event.AWTEventListener;
+import java.awt.event.AWTEventListenerProxy;
+import java.awt.event.KeyEvent;
+import java.awt.font.TextAttribute;
+import java.awt.im.InputMethodHighlight;
+import java.awt.image.ColorModel;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.peer.ButtonPeer;
+import java.awt.peer.CanvasPeer;
+import java.awt.peer.CheckboxMenuItemPeer;
+import java.awt.peer.CheckboxPeer;
+import java.awt.peer.ChoicePeer;
+import java.awt.peer.DesktopPeer;
+import java.awt.peer.DialogPeer;
+import java.awt.peer.FileDialogPeer;
+import java.awt.peer.FontPeer;
+import java.awt.peer.FramePeer;
+import java.awt.peer.LabelPeer;
+import java.awt.peer.LightweightPeer;
+import java.awt.peer.ListPeer;
+import java.awt.peer.MenuBarPeer;
+import java.awt.peer.MenuItemPeer;
+import java.awt.peer.MenuPeer;
+import java.awt.peer.MouseInfoPeer;
+import java.awt.peer.PanelPeer;
+import java.awt.peer.PopupMenuPeer;
+import java.awt.peer.ScrollPanePeer;
+import java.awt.peer.ScrollbarPeer;
+import java.awt.peer.TextAreaPeer;
+import java.awt.peer.TextFieldPeer;
+import java.awt.peer.WindowPeer;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+/**
+ * The AWT system uses a set of native peer objects to implement its
+ * widgets. These peers are provided by a peer toolkit, that is accessed
+ * via a subclass of this superclass. The system toolkit is retrieved
+ * by the static methods <code>getDefaultToolkit</code>. This method
+ * determines the system toolkit by examining the system property
+ * <code>awt.toolkit</code>. That property is set to the name of the
+ * <code>Toolkit</code> subclass for the specified peer set. If the
+ * <code>awt.toolkit</code> property is not set, then the default
+ * toolkit <code>gnu.java.awt.peer.gtk.GtkToolkit</code> is used. This
+ * toolkit creates its peers using the GTK+ toolkit.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public abstract class Toolkit
+{
+ /** The default toolkit name. */
+ private static String default_toolkit_name
+ = gnu.classpath.Configuration.default_awt_peer_toolkit;
+
+ /**
+ * The toolkit in use. Once we load it, we don't ever change it
+ * if the awt.toolkit property is set.
+ */
+ private static Toolkit toolkit;
+
+ /** The toolkit properties. */
+ private static Properties props = new Properties();
+
+ protected final Map<String,Object> desktopProperties =
+ new Hashtable<String,Object>();
+
+ protected final PropertyChangeSupport desktopPropsSupport
+ = new PropertyChangeSupport(this);
+
+ /**
+ * All registered AWTEventListener objects. This is package private, so the
+ * event queue can efficiently access this list.
+ */
+ AWTEventListenerProxy[] awtEventListeners;
+
+ /**
+ * The shared peer for all lightweight components.
+ */
+ private GLightweightPeer lightweightPeer;
+
+ /**
+ * Default constructor for subclasses.
+ */
+ public Toolkit()
+ {
+ awtEventListeners = new AWTEventListenerProxy[0];
+ }
+
+ /**
+ *
+ * @param target
+ * @return
+ * @throws HeadlessException
+ */
+ protected abstract DesktopPeer createDesktopPeer(Desktop target)
+ throws HeadlessException;
+
+ /**
+ * Creates a peer object for the specified <code>Button</code>.
+ *
+ * @param target The <code>Button</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>Button</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract ButtonPeer createButton(Button target);
+
+ /**
+ * Creates a peer object for the specified <code>TextField</code>.
+ *
+ * @param target The <code>TextField</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>TextField</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract TextFieldPeer createTextField(TextField target);
+
+ /**
+ * Creates a peer object for the specified <code>Label</code>.
+ *
+ * @param target The <code>Label</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>Label</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract LabelPeer createLabel(Label target);
+
+ /**
+ * Creates a peer object for the specified <code>List</code>.
+ *
+ * @param target The <code>List</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>List</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract ListPeer createList(List target);
+
+ /**
+ * Creates a peer object for the specified <code>Checkbox</code>.
+ *
+ * @param target The <code>Checkbox</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>Checkbox</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract CheckboxPeer createCheckbox(Checkbox target);
+
+ /**
+ * Creates a peer object for the specified <code>Scrollbar</code>.
+ *
+ * @param target The <code>Scrollbar</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>Scrollbar</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract ScrollbarPeer createScrollbar(Scrollbar target);
+
+ /**
+ * Creates a peer object for the specified <code>ScrollPane</code>.
+ *
+ * @param target The <code>ScrollPane</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>ScrollPane</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract ScrollPanePeer createScrollPane(ScrollPane target);
+
+ /**
+ * Creates a peer object for the specified <code>TextArea</code>.
+ *
+ * @param target The <code>TextArea</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>TextArea</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract TextAreaPeer createTextArea(TextArea target);
+
+ /**
+ * Creates a peer object for the specified <code>Choice</code>.
+ *
+ * @param target The <code>Choice</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>Choice</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract ChoicePeer createChoice(Choice target);
+
+ /**
+ * Creates a peer object for the specified <code>Frame</code>.
+ *
+ * @param target The <code>Frame</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>Frame</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract FramePeer createFrame(Frame target);
+
+ /**
+ * Creates a peer object for the specified <code>Canvas</code>.
+ *
+ * @param target The <code>Canvas</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>Canvas</code> object.
+ */
+ protected abstract CanvasPeer createCanvas(Canvas target);
+
+ /**
+ * Creates a peer object for the specified <code>Panel</code>.
+ *
+ * @param target The <code>Panel</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>Panel</code> object.
+ */
+ protected abstract PanelPeer createPanel(Panel target);
+
+ /**
+ * Creates a peer object for the specified <code>Window</code>.
+ *
+ * @param target The <code>Window</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>Window</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract WindowPeer createWindow(Window target);
+
+ /**
+ * Creates a peer object for the specified <code>Dialog</code>.
+ *
+ * @param target The dialog to create the peer for
+ *
+ * @return The peer for the specified font name.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract DialogPeer createDialog(Dialog target);
+
+ /**
+ * Creates a peer object for the specified <code>MenuBar</code>.
+ *
+ * @param target The <code>MenuBar</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>MenuBar</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract MenuBarPeer createMenuBar(MenuBar target);
+
+ /**
+ * Creates a peer object for the specified <code>Menu</code>.
+ *
+ * @param target The <code>Menu</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>Menu</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract MenuPeer createMenu(Menu target);
+
+ /**
+ * Creates a peer object for the specified <code>PopupMenu</code>.
+ *
+ * @param target The <code>PopupMenu</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>PopupMenu</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract PopupMenuPeer createPopupMenu(PopupMenu target);
+
+ /**
+ * Creates a peer object for the specified <code>MenuItem</code>.
+ *
+ * @param target The <code>MenuItem</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>MenuItem</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract MenuItemPeer createMenuItem(MenuItem target);
+
+ /**
+ * Returns a MouseInfoPeer.
+ * The default implementation of this method throws
+ * UnsupportedOperationException.
+ *
+ * Toolkit implementations should overload this if possible, however.
+ */
+ protected MouseInfoPeer getMouseInfoPeer()
+ {
+ throw new UnsupportedOperationException("No mouse info peer.");
+ }
+
+ /**
+ * Creates a peer object for the specified <code>FileDialog</code>.
+ *
+ * @param target The <code>FileDialog</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>FileDialog</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract FileDialogPeer createFileDialog(FileDialog target);
+
+ /**
+ * Creates a peer object for the specified <code>CheckboxMenuItem</code>.
+ *
+ * @param target The <code>CheckboxMenuItem</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>CheckboxMenuItem</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected abstract CheckboxMenuItemPeer
+ createCheckboxMenuItem(CheckboxMenuItem target);
+
+ /**
+ * Creates a peer object for the specified <code>Component</code>. The
+ * peer returned by this method is not a native windowing system peer
+ * with its own native window. Instead, this method allows the component
+ * to draw on its parent window as a "lightweight" widget.
+ *
+ * @param target The <code>Component</code> to create the peer for.
+ *
+ * @return The peer for the specified <code>Component</code> object.
+ */
+ protected LightweightPeer createComponent(Component target)
+ {
+ if (lightweightPeer == null)
+ lightweightPeer = new GLightweightPeer();
+ return lightweightPeer;
+ }
+
+ /**
+ * Creates a peer object for the specified font name.
+ *
+ * @param name The font to create the peer for.
+ * @param style The font style to create the peer for.
+ *
+ * @return The peer for the specified font name.
+ *
+ * @deprecated
+ */
+ protected abstract FontPeer getFontPeer(String name, int style);
+
+ /**
+ * Copies the current system colors into the specified array. This is
+ * the interface used by the <code>SystemColor</code> class. Although
+ * this method fills in the array with some default colors a real Toolkit
+ * should override this method and provide real system colors for the
+ * native GUI platform.
+ *
+ * @param systemColors The array to copy the system colors into.
+ * It must be at least 26 elements.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ *
+ * @see java.awt.SystemColor
+ */
+ protected void loadSystemColors(int systemColors[])
+ {
+ systemColors[SystemColor.DESKTOP] = 0xFF005C5C;
+ systemColors[SystemColor.ACTIVE_CAPTION] = 0xFF000080;
+ systemColors[SystemColor.ACTIVE_CAPTION_TEXT] = 0xFFFFFFFF;
+ systemColors[SystemColor.ACTIVE_CAPTION_BORDER] = 0xFFC0C0C0;
+ systemColors[SystemColor.INACTIVE_CAPTION] = 0xFF808080;
+ systemColors[SystemColor.INACTIVE_CAPTION_TEXT] = 0xFFC0C0C0;
+ systemColors[SystemColor.INACTIVE_CAPTION_BORDER] = 0xFFC0C0C0;
+ systemColors[SystemColor.WINDOW] = 0xFFFFFFFF;
+ systemColors[SystemColor.WINDOW_BORDER] = 0xFF000000;
+ systemColors[SystemColor.WINDOW_TEXT] = 0xFF000000;
+ systemColors[SystemColor.MENU] = 0xFFC0C0C0;
+ systemColors[SystemColor.MENU_TEXT] = 0xFF000000;
+ systemColors[SystemColor.TEXT] = 0xFFC0C0C0;
+ systemColors[SystemColor.TEXT_TEXT] = 0xFF000000;
+ systemColors[SystemColor.TEXT_HIGHLIGHT] = 0xFF000090;
+ systemColors[SystemColor.TEXT_HIGHLIGHT_TEXT] = 0xFFFFFFFF;
+ systemColors[SystemColor.TEXT_INACTIVE_TEXT] = 0xFF808080;
+ systemColors[SystemColor.CONTROL] = 0xFFC0C0C0;
+ systemColors[SystemColor.CONTROL_TEXT] = 0xFF000000;
+ systemColors[SystemColor.CONTROL_HIGHLIGHT] = 0xFFFFFFFF;
+ systemColors[SystemColor.CONTROL_LT_HIGHLIGHT] = 0xFFE0E0E0;
+ systemColors[SystemColor.CONTROL_SHADOW] = 0xFF808080;
+ systemColors[SystemColor.CONTROL_DK_SHADOW] = 0xFF000000;
+ systemColors[SystemColor.SCROLLBAR] = 0xFFE0E0E0;
+ systemColors[SystemColor.INFO] = 0xFFE0E000;
+ systemColors[SystemColor.INFO_TEXT] = 0xFF000000;
+ }
+
+ /**
+ * @since 1.4
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public void setDynamicLayout(boolean dynamic)
+ {
+ }
+
+ /**
+ * @since 1.4
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ protected boolean isDynamicLayoutSet()
+ {
+ return false;
+ }
+
+ /**
+ * @since 1.4
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public boolean isDynamicLayoutActive()
+ {
+ return false;
+ }
+
+ /**
+ * Returns the dimensions of the screen in pixels.
+ *
+ * @return The dimensions of the screen in pixels.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public abstract Dimension getScreenSize();
+
+ /**
+ * Returns the screen resolution in dots per square inch.
+ *
+ * @return The screen resolution in dots per square inch.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public abstract int getScreenResolution();
+
+ /**
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ *
+ * @since 1.4
+ */
+ public Insets getScreenInsets(GraphicsConfiguration gc)
+ {
+ return new Insets(0, 0, 0, 0);
+ }
+
+ /**
+ * Returns the color model of the screen.
+ *
+ * @return The color model of the screen.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public abstract ColorModel getColorModel();
+
+ /**
+ * Returns the names of the available fonts.
+ *
+ * @return The names of the available fonts.
+ *
+ * @deprecated
+ */
+ public abstract String[] getFontList();
+
+ /**
+ * Return the font metrics for the specified font
+ *
+ * @param name The name of the font to return metrics for.
+ *
+ * @return The requested font metrics.
+ *
+ * @deprecated
+ */
+ public abstract FontMetrics getFontMetrics(Font name);
+
+ /**
+ * Flushes any buffered data to the screen so that it is in sync with
+ * what the AWT system has drawn to it.
+ */
+ public abstract void sync();
+
+ /**
+ * Returns an instance of the default toolkit. The default toolkit is
+ * the subclass of <code>Toolkit</code> specified in the system property
+ * <code>awt.toolkit</code>, or <code>gnu.java.awt.peer.gtk.GtkToolkit</code>
+ * if the property is not set.
+ *
+ * @return An instance of the system default toolkit.
+ *
+ * @throws AWTError If the toolkit cannot be loaded.
+ */
+ public static synchronized Toolkit getDefaultToolkit()
+ {
+ if (toolkit != null)
+ return toolkit;
+
+ String toolkit_name = SystemProperties.getProperty("awt.toolkit",
+ default_toolkit_name);
+ try
+ {
+ ClassLoader cl;
+ cl = (ClassLoader) AccessController.doPrivileged
+ (new PrivilegedAction()
+ {
+ public Object run()
+ {
+ return ClassLoader.getSystemClassLoader();
+ }
+ });
+ Class cls = Class.forName(toolkit_name, true, cl);
+ Object obj = cls.newInstance();
+ if (!(obj instanceof Toolkit))
+ throw new AWTError(toolkit_name + " is not a subclass of " +
+ "java.awt.Toolkit");
+ toolkit = (Toolkit) obj;
+
+ initAccessibility();
+ return toolkit;
+ }
+ catch (ThreadDeath death)
+ {
+ throw death;
+ }
+ catch (Throwable t)
+ {
+ // Check for the headless property.
+ if (GraphicsEnvironment.isHeadless())
+ {
+ toolkit = new HeadlessToolkit();
+ return toolkit;
+ }
+ else
+ {
+ AWTError e = new AWTError("Cannot load AWT toolkit: "
+ + toolkit_name);
+ throw (AWTError) e.initCause(t);
+ }
+ }
+ }
+
+ /**
+ * Returns an image from the specified file, which must be in a
+ * recognized format. Supported formats vary from toolkit to toolkit.
+ *
+ * @return name The name of the file to read the image from.
+ */
+ public abstract Image getImage(String name);
+
+ /**
+ * Returns an image from the specified URL, which must be in a
+ * recognized format. Supported formats vary from toolkit to toolkit.
+ *
+ * @return url The URl to read the image from.
+ */
+ public abstract Image getImage(URL url);
+
+ public abstract Image createImage(String filename);
+
+ public abstract Image createImage(URL url);
+
+ /**
+ * Readies an image to be rendered on the screen. The width and height
+ * values can be set to the default sizes for the image by passing -1
+ * in those parameters.
+ *
+ * @param image The image to prepare for rendering.
+ * @param width The width of the image.
+ * @param height The height of the image.
+ * @param observer The observer to receive events about the preparation
+ * process.
+ *
+ * @return <code>true</code> if the image is already prepared for rendering,
+ * <code>false</code> otherwise.
+ */
+ public abstract boolean prepareImage(Image image, int width, int height,
+ ImageObserver observer);
+
+ /**
+ * Checks the status of specified image as it is being readied for
+ * rendering.
+ *
+ * @param image The image to prepare for rendering.
+ * @param width The width of the image.
+ * @param height The height of the image.
+ * @param observer The observer to receive events about the preparation
+ * process.
+ *
+ * @return A union of the bitmasks from
+ * <code>java.awt.image.ImageObserver</code> that indicates the current
+ * state of the imaging readying process.
+ */
+ public abstract int checkImage(Image image, int width, int height,
+ ImageObserver observer);
+
+ /**
+ * Creates an image using the specified <code>ImageProducer</code>
+ *
+ * @param producer The <code>ImageProducer</code> to create the image from.
+ *
+ * @return The created image.
+ */
+ public abstract Image createImage(ImageProducer producer);
+
+ /**
+ * Creates an image from the specified byte array. The array must be in
+ * a recognized format. Supported formats vary from toolkit to toolkit.
+ *
+ * @param data The raw image data.
+ *
+ * @return The created image.
+ */
+ public Image createImage(byte[] data)
+ {
+ return createImage(data, 0, data.length);
+ }
+
+ /**
+ * Creates an image from the specified portion of the byte array passed.
+ * The array must be in a recognized format. Supported formats vary from
+ * toolkit to toolkit.
+ *
+ * @param data The raw image data.
+ * @param offset The offset into the data where the image data starts.
+ * @param len The length of the image data.
+ *
+ * @return The created image.
+ */
+ public abstract Image createImage(byte[] data, int offset, int len);
+
+ /**
+ * Returns a instance of <code>PrintJob</code> for the specified
+ * arguments.
+ *
+ * @param frame The window initiating the print job.
+ * @param title The print job title.
+ * @param props The print job properties.
+ *
+ * @return The requested print job, or <code>null</code> if the job
+ * was cancelled.
+ *
+ * @exception NullPointerException If frame is null,
+ * or GraphicsEnvironment.isHeadless() returns true.
+ * @exception SecurityException If this thread is not allowed to initiate
+ * a print job request.
+ */
+ public abstract PrintJob getPrintJob(Frame frame, String title,
+ Properties props);
+
+ /**
+ * Returns a instance of <code>PrintJob</code> for the specified
+ * arguments.
+ *
+ * @param frame The window initiating the print job.
+ * @param title The print job title.
+ * @param jobAttr A set of job attributes which will control the print job.
+ * @param pageAttr A set of page attributes which will control the print job.
+ *
+ * @exception NullPointerException If frame is null, and either jobAttr is null
+ * or jobAttr.getDialog() returns JobAttributes.DialogType.NATIVE.
+ * @exception IllegalArgumentException If pageAttrspecifies differing cross
+ * feed and feed resolutions, or when GraphicsEnvironment.isHeadless() returns
+ * true.
+ * @exception SecurityException If this thread is not allowed to initiate
+ * a print job request.
+ *
+ * @since 1.3
+ */
+ public PrintJob getPrintJob(Frame frame, String title,
+ JobAttributes jobAttr, PageAttributes pageAttr)
+ {
+ // FIXME: it is possible this check may be removed
+ // if this method, when written, always delegates to
+ // getPrintJob(Frame, String, Properties).
+ SecurityManager sm;
+ sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPrintJobAccess();
+
+ return null;
+ }
+
+ /**
+ * Causes a "beep" tone to be generated.
+ */
+ public abstract void beep();
+
+ /**
+ * Returns the system clipboard.
+ *
+ * @return THe system clipboard.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public abstract Clipboard getSystemClipboard();
+
+ /**
+ * Gets the singleton instance of the system selection as a
+ * Clipboard object. The system selection contains the selected text
+ * of the last component/widget that had focus and a text selection.
+ * The default implementation returns null.
+ *
+ * @return The Clipboard holding the system (text) selection or null
+ * if the Toolkit or system doesn't support a selection clipboard.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * is true.
+ * @exception SecurityException If the current security manager
+ * checkSystemClipboardAccess() doesn't allow access.
+ *
+ * @since 1.4
+ */
+ public Clipboard getSystemSelection()
+ {
+ return null;
+ }
+
+ /**
+ * Returns the accelerator key mask for menu shortcuts. The default is
+ * <code>Event.CTRL_MASK</code>. A toolkit must override this method
+ * to change the default.
+ *
+ * @return The key mask for the menu accelerator key.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public int getMenuShortcutKeyMask()
+ {
+ return Event.CTRL_MASK;
+ }
+
+ /**
+ * Returns whether the given locking key on the keyboard is currently in its
+ * "on" state.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ * @exception IllegalArgumentException If keyCode is not one of the valid keys.
+ * @exception UnsupportedOperationException If the host system doesn't allow
+ * getting the state of this key programmatically, or if the keyboard doesn't
+ * have this key.
+ */
+ public boolean getLockingKeyState(int keyCode)
+ {
+ if (AWTUtilities.isValidKey(keyCode))
+ throw new UnsupportedOperationException
+ ("cannot get locking state of key code " + keyCode);
+
+ throw new IllegalArgumentException("invalid key code " + keyCode);
+ }
+
+ /**
+ * Sets the state of the given locking key on the keyboard.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ * @exception IllegalArgumentException If keyCode is not one of the valid keys.
+ * @exception UnsupportedOperationException If the host system doesn't allow
+ * getting the state of this key programmatically, or if the keyboard doesn't
+ * have this key.
+ */
+ public void setLockingKeyState(int keyCode, boolean on)
+ {
+ if (keyCode != KeyEvent.VK_CAPS_LOCK
+ && keyCode != KeyEvent.VK_NUM_LOCK
+ && keyCode != KeyEvent.VK_SCROLL_LOCK)
+ throw new IllegalArgumentException();
+
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns the native container object of the specified component. This
+ * method is necessary because the parent component might be a lightweight
+ * component.
+ *
+ * @param component The component to fetch the native container for.
+ *
+ * @return The native container object for this component.
+ */
+ protected static Container getNativeContainer(Component component)
+ {
+ component = component.getParent();
+ while (true)
+ {
+ if (component == null)
+ return null;
+ if (! (component instanceof Container))
+ {
+ component = component.getParent();
+ continue;
+ }
+ if (component.getPeer() instanceof LightweightPeer)
+ {
+ component = component.getParent();
+ continue;
+ }
+ return (Container) component;
+ }
+ }
+
+ /**
+ * Creates a new custom cursor object.
+ *
+ * @exception IndexOutOfBoundsException If the hotSpot values are outside
+ * the bounds of the cursor.
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public Cursor createCustomCursor(Image cursor, Point hotSpot, String name)
+ {
+ // Presumably the only reason this isn't abstract is for backwards
+ // compatibility? FIXME?
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException("No custom cursor in an headless graphics "
+ + "environment.");
+ return null;
+ }
+
+ /**
+ * Returns the supported cursor dimension which is closest to the
+ * desired sizes.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public Dimension getBestCursorSize(int preferredWidth, int preferredHeight)
+ {
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException("No best cursor size in an headless "
+ + "graphics environment.");
+ return new Dimension (0,0);
+ }
+
+ /**
+ * Returns the maximum number of colors the Toolkit supports in a custom
+ * cursor palette.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public int getMaximumCursorColors()
+ {
+ return 0;
+ }
+
+ /**
+ * Returns whether Toolkit supports this state for Frames.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ *
+ * @since 1.4
+ */
+ public boolean isFrameStateSupported(int state)
+ {
+ return false;
+ }
+
+ /**
+ * Returns the value of the property with the specified name, or the
+ * default value if the property does not exist.
+ *
+ * @param key The name of the property to retrieve.
+ * @param def The default value of the property.
+ */
+ public static String getProperty(String key, String def)
+ {
+ return props.getProperty(key, def);
+ }
+
+
+ /**
+ * Returns the event queue that is suitable for the calling context.
+ *
+ * <p>Despite the word &#x201c;System&#x201d; in the name of this
+ * method, a toolkit may provide different event queues for each
+ * applet. There is no guarantee that the same queue is shared
+ * system-wide.
+ *
+ * <p>The implementation first checks whether a
+ * SecurityManager has been installed. If so, its {@link
+ * java.lang.SecurityManager#checkAwtEventQueueAccess()} method gets
+ * called. The security manager will throw a SecurityException if it
+ * does not grant the permission to access the event queue.
+ *
+ * <p>Next, the call is delegated to {@link
+ * #getSystemEventQueueImpl()}.
+ *
+ * @return The event queue for this applet (or application).
+ *
+ * @throws SecurityException if a security manager has been
+ * installed, and it does not grant the permission to access the
+ * event queue.
+ */
+ public final EventQueue getSystemEventQueue()
+ {
+ SecurityManager sm;
+
+ sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkAwtEventQueueAccess();
+
+ return getSystemEventQueueImpl();
+ }
+
+
+ /**
+ * Returns the event queue that is suitable for the calling context.
+ *
+ * <p>Despite the word &#x201c;System&#x201d; in the name of this
+ * method, a toolkit may provide different event queues for each
+ * applet. There is no guarantee that the same queue is shared
+ * system-wide.
+ *
+ * <p>No security checks are performed, which is why this method
+ * may only be called by Toolkits.
+ *
+ * @see #getSystemEventQueue()
+ */
+ protected abstract EventQueue getSystemEventQueueImpl();
+
+
+ /**
+ * @since 1.3
+ */
+ public abstract DragSourceContextPeer
+ createDragSourceContextPeer(DragGestureEvent e);
+
+ /**
+ * @since 1.3
+ */
+ public <T extends DragGestureRecognizer> T
+ createDragGestureRecognizer(Class<T> recognizer, DragSource ds,
+ Component comp, int actions,
+ DragGestureListener l)
+ {
+ return null;
+ }
+
+ public final Object getDesktopProperty(String propertyName)
+ {
+ return desktopProperties.get(propertyName);
+ }
+
+ protected final void setDesktopProperty(String name, Object newValue)
+ {
+ Object oldValue = getDesktopProperty(name);
+ desktopProperties.put(name, newValue);
+ desktopPropsSupport.firePropertyChange(name, oldValue, newValue);
+ }
+
+ protected Object lazilyLoadDesktopProperty(String name)
+ {
+ // FIXME - what is this??
+ return null;
+ }
+
+ protected void initializeDesktopProperties()
+ {
+ // Overridden by toolkit implementation?
+ }
+
+ public void addPropertyChangeListener(String name,
+ PropertyChangeListener pcl)
+ {
+ desktopPropsSupport.addPropertyChangeListener(name, pcl);
+ }
+
+ public void removePropertyChangeListener(String name,
+ PropertyChangeListener pcl)
+ {
+ desktopPropsSupport.removePropertyChangeListener(name, pcl);
+ }
+
+ /**
+ * @since 1.4
+ */
+ public PropertyChangeListener[] getPropertyChangeListeners()
+ {
+ return desktopPropsSupport.getPropertyChangeListeners();
+ }
+
+ /**
+ * @since 1.4
+ */
+ public PropertyChangeListener[] getPropertyChangeListeners(String name)
+ {
+ return desktopPropsSupport.getPropertyChangeListeners(name);
+ }
+
+ /**
+ * Adds an AWTEventListener to this toolkit. This listener is informed about
+ * all events that pass the eventqueue that match the specified
+ * <code>evenMask</code>. The <code>eventMask</code> is an ORed combination
+ * of event masks as defined in {@link AWTEvent}.
+ *
+ * If a security manager is installed, it is asked first if an
+ * <code>AWTPermission(&quot;listenToAllAWTEvents&quot;)</code> is allowed.
+ * This may result in a <code>SecurityException</code> beeing thrown.
+ *
+ * It is not recommended to use this kind of notification for normal
+ * applications. It is intended solely for the purpose of debugging and to
+ * support special facilities.
+ *
+ * @param listener the listener to add
+ * @param eventMask the event mask of event types which the listener is
+ * interested in
+ *
+ * @since 1.2
+ *
+ * @throws SecurityException if there is a <code>SecurityManager</code> that
+ * doesn't grant
+ * <code>AWTPermission(&quot;listenToAllAWTEvents&quot;)</code>
+ *
+ * @see #getAWTEventListeners()
+ * @see #getAWTEventListeners(long)
+ * @see #removeAWTEventListener(AWTEventListener)
+ */
+ public void addAWTEventListener(AWTEventListener listener, long eventMask)
+ {
+ // First we must check the security permissions.
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkPermission(new AWTPermission("listenToAllAWTEvents"));
+
+ // Go through the list and check if the requested listener is already
+ // registered.
+ boolean found = false;
+ for (int i = 0; i < awtEventListeners.length; ++i)
+ {
+ AWTEventListenerProxy proxy = awtEventListeners[i];
+ if (proxy.getListener() == listener)
+ {
+ found = true;
+ // Modify the proxies event mask to include the new event mask.
+ AWTEventListenerProxy newProxy =
+ new AWTEventListenerProxy(proxy.getEventMask() | eventMask,
+ listener);
+ awtEventListeners[i] = newProxy;
+ break;
+ }
+ }
+
+ // If that listener was not found, then add it.
+ if (! found)
+ {
+ AWTEventListenerProxy proxy =
+ new AWTEventListenerProxy(eventMask, listener);
+ AWTEventListenerProxy[] newArray =
+ new AWTEventListenerProxy[awtEventListeners.length + 1];
+ System.arraycopy(awtEventListeners, 0, newArray, 0,
+ awtEventListeners.length);
+ newArray[newArray.length - 1] = proxy;
+ awtEventListeners = newArray;
+ }
+ }
+
+ /**
+ * Removes an AWT event listener from this toolkit. This listener is no
+ * longer informed of any event types it was registered in.
+ *
+ * If a security manager is installed, it is asked first if an
+ * <code>AWTPermission(&quot;listenToAllAWTEvents&quot;)</code> is allowed.
+ * This may result in a <code>SecurityException</code> beeing thrown.
+ *
+ * It is not recommended to use this kind of notification for normal
+ * applications. It is intended solely for the purpose of debugging and to
+ * support special facilities.
+ *
+ * @param listener the listener to remove
+ *
+ * @throws SecurityException if there is a <code>SecurityManager</code> that
+ * doesn't grant
+ * <code>AWTPermission(&quot;listenToAllAWTEvents&quot;)</code>
+ *
+ * @since 1.2
+ *
+ * @see #addAWTEventListener(AWTEventListener, long)
+ * @see #getAWTEventListeners()
+ * @see #getAWTEventListeners(long)
+ */
+ public void removeAWTEventListener(AWTEventListener listener)
+ {
+ // First we must check the security permissions.
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkPermission(new AWTPermission("listenToAllAWTEvents"));
+
+
+ // Find the index of the listener.
+ int index = -1;
+ for (int i = 0; i < awtEventListeners.length; ++i)
+ {
+ AWTEventListenerProxy proxy = awtEventListeners[i];
+ if (proxy.getListener() == listener)
+ {
+ index = i;
+ break;
+ }
+ }
+
+ // Copy over the arrays and leave out the removed element.
+ if (index != -1)
+ {
+ AWTEventListenerProxy[] newArray =
+ new AWTEventListenerProxy[awtEventListeners.length - 1];
+ if (index > 0)
+ System.arraycopy(awtEventListeners, 0, newArray, 0, index);
+ if (index < awtEventListeners.length - 1)
+ System.arraycopy(awtEventListeners, index + 1, newArray, index,
+ awtEventListeners.length - index - 1);
+ awtEventListeners = newArray;
+ }
+ }
+
+ /**
+ * Returns all registered AWT event listeners. This method returns a copy of
+ * the listener array, so that application cannot trash the listener list.
+ *
+ * If a security manager is installed, it is asked first if an
+ * <code>AWTPermission(&quot;listenToAllAWTEvents&quot;)</code> is allowed.
+ * This may result in a <code>SecurityException</code> beeing thrown.
+ *
+ * It is not recommended to use this kind of notification for normal
+ * applications. It is intended solely for the purpose of debugging and to
+ * support special facilities.
+ *
+ * @return all registered AWT event listeners
+ *
+ * @throws SecurityException if there is a <code>SecurityManager</code> that
+ * doesn't grant
+ * <code>AWTPermission(&quot;listenToAllAWTEvents&quot;)</code>
+ *
+ * @since 1.4
+ *
+ * @see #addAWTEventListener(AWTEventListener, long)
+ * @see #removeAWTEventListener(AWTEventListener)
+ * @see #getAWTEventListeners(long)
+ */
+ public AWTEventListener[] getAWTEventListeners()
+ {
+ // First we must check the security permissions.
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkPermission(new AWTPermission("listenToAllAWTEvents"));
+
+ // Create a copy of the array.
+ AWTEventListener[] copy = new AWTEventListener[awtEventListeners.length];
+ System.arraycopy(awtEventListeners, 0, copy, 0, awtEventListeners.length);
+ return copy;
+ }
+
+ /**
+ * Returns all registered AWT event listeners that listen for events with
+ * the specified <code>eventMask</code>. This method returns a copy of
+ * the listener array, so that application cannot trash the listener list.
+ *
+ * If a security manager is installed, it is asked first if an
+ * <code>AWTPermission(&quot;listenToAllAWTEvents&quot;)</code> is allowed.
+ * This may result in a <code>SecurityException</code> beeing thrown.
+ *
+ * It is not recommended to use this kind of notification for normal
+ * applications. It is intended solely for the purpose of debugging and to
+ * support special facilities.
+ *
+ * @param mask the event mask
+ *
+ * @throws SecurityException if there is a <code>SecurityManager</code> that
+ * doesn't grant
+ * <code>AWTPermission(&quot;listenToAllAWTEvents&quot;)</code>
+ *
+ *
+ * @since 1.4
+ *
+ * @see #addAWTEventListener(AWTEventListener, long)
+ * @see #removeAWTEventListener(AWTEventListener)
+ * @see #getAWTEventListeners()
+ */
+ public AWTEventListener[] getAWTEventListeners(long mask)
+ {
+ // First we must check the security permissions.
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ s.checkPermission(new AWTPermission("listenToAllAWTEvents"));
+
+ // Create a copy of the array with only the requested listeners in it.
+ ArrayList l = new ArrayList(awtEventListeners.length);
+ for (int i = 0; i < awtEventListeners.length; ++i)
+ {
+ if ((awtEventListeners[i].getEventMask() & mask) != 0)
+ l.add(awtEventListeners[i]);
+ }
+
+ return (AWTEventListener[] ) l.toArray(new AWTEventListener[l.size()]);
+ }
+
+
+ /**
+ * Dispatches events to listeners registered to this Toolkit. This is called
+ * by {@link Component#dispatchEventImpl(AWTEvent)} in order to dispatch
+ * events globally.
+ *
+ * @param ev the event to dispatch
+ */
+ void globalDispatchEvent(AWTEvent ev)
+ {
+ // We do not use the accessor methods here because they create new
+ // arrays each time. We must be very efficient, so we access this directly.
+ for (int i = 0; i < awtEventListeners.length; ++i)
+ {
+ AWTEventListenerProxy proxy = awtEventListeners[i];
+ if ((proxy.getEventMask() & AWTEvent.eventIdToMask(ev.getID())) != 0)
+ proxy.eventDispatched(ev);
+ }
+ }
+
+ /**
+ * @since 1.3
+ */
+ public abstract Map<TextAttribute,?>
+ mapInputMethodHighlight(InputMethodHighlight highlight);
+
+ public abstract boolean isModalExclusionTypeSupported
+ (Dialog.ModalExclusionType modalExclusionType);
+
+ public abstract boolean isModalityTypeSupported
+ (Dialog.ModalityType modalityType);
+
+ /**
+ * Initializes the accessibility framework. In particular, this loads the
+ * properties javax.accessibility.screen_magnifier_present and
+ * javax.accessibility.screen_reader_present and loads
+ * the classes specified in javax.accessibility.assistive_technologies.
+ */
+ private static void initAccessibility()
+ {
+ AccessController.doPrivileged
+ (new PrivilegedAction()
+ {
+ public Object run()
+ {
+ Properties props = new Properties();
+ String sep = File.separator;
+
+ // Try the user configuration.
+ try
+ {
+ File propsFile = new File(System.getProperty("user.home") + sep
+ + ".accessibility.properties");
+ FileInputStream in = new FileInputStream(propsFile);
+ props.load(in);
+ in.close();
+ }
+ catch (Exception ex)
+ {
+ // User configuration not present, ignore.
+ }
+
+ // Try the system configuration if there was no user configuration.
+ if (props.size() == 0)
+ {
+ try
+ {
+ File propsFile =
+ new File(System.getProperty("gnu.classpath.home.url")
+ + sep + "accessibility.properties");
+ FileInputStream in = new FileInputStream(propsFile);
+ props.load(in);
+ in.close();
+ }
+ catch (Exception ex)
+ {
+ // System configuration not present, ignore.
+ }
+ }
+
+ // Fetch the screen_magnifier_present property. Check systen properties
+ // first, then fallback to the configuration file.
+ String magPresent = SystemProperties.getProperty
+ ("javax.accessibility.screen_magnifier_present");
+ if (magPresent == null)
+ {
+ magPresent = props.getProperty("screen_magnifier_present");
+ if (magPresent != null)
+ {
+ SystemProperties.setProperty
+ ("javax.accessibility.screen_magnifier_present", magPresent);
+ }
+ }
+
+ // Fetch the screen_reader_present property. Check systen properties
+ // first, then fallback to the configuration file.
+ String readerPresent = SystemProperties.getProperty
+ ("javax.accessibility.screen_reader_present");
+ if (readerPresent == null)
+ {
+ readerPresent = props.getProperty("screen_reader_present");
+ if (readerPresent != null)
+ {
+ SystemProperties.setProperty
+ ("javax.accessibility.screen_reader_present", readerPresent);
+ }
+ }
+
+ // Fetch the list of classes to be loaded.
+ String classes = SystemProperties.getProperty
+ ("javax.accessibility.assistive_technologies");
+ if (classes == null)
+ {
+ classes = props.getProperty("assistive_technologies");
+ if (classes != null)
+ {
+ SystemProperties.setProperty
+ ("javax.accessibility.assistive_technologies", classes);
+ }
+ }
+
+ // Try to load the assisitive_technologies classes.
+ if (classes != null)
+ {
+ ClassLoader cl = ClassLoader.getSystemClassLoader();
+ StringTokenizer tokenizer = new StringTokenizer(classes, ",");
+ while (tokenizer.hasMoreTokens())
+ {
+ String className = tokenizer.nextToken();
+ try
+ {
+ Class atClass = cl.loadClass(className);
+ atClass.newInstance();
+ }
+ catch (ClassNotFoundException ex)
+ {
+ AWTError err = new AWTError("Assistive Technology class not"
+ + " found: " + className);
+ err.initCause(ex);
+ throw err;
+ }
+ catch (InstantiationException ex)
+ {
+ AWTError err =
+ new AWTError("Assistive Technology class cannot be "
+ + "instantiated: " + className);
+ err.initCause(ex);
+ throw err;
+ }
+ catch (IllegalAccessException ex)
+ {
+ AWTError err =
+ new AWTError("Assistive Technology class cannot be "
+ + "accessed: " + className);
+ err.initCause(err);
+ throw err;
+ }
+ }
+ }
+ return null;
+ }
+ });
+
+ }
+
+} // class Toolkit
diff --git a/libjava/classpath/java/awt/Transparency.java b/libjava/classpath/java/awt/Transparency.java
new file mode 100644
index 000000000..888587176
--- /dev/null
+++ b/libjava/classpath/java/awt/Transparency.java
@@ -0,0 +1,67 @@
+/* Transparency.java -- common transparency modes in graphics
+ Copyright (C) 2000, 2002, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt;
+
+/**
+ * A common transparency mode for layering graphics.
+ *
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface Transparency
+{
+ /** Image data which is completely opaque, for an alpha value of 1.0. */
+ int OPAQUE = 1;
+
+ /**
+ * Image data which is either completely opaque or transparent, for an
+ * exact integer alpha value.
+ */
+ int BITMASK = 2;
+
+ /** Image data which is translucent, for a non-integer alpha value. */
+ int TRANSLUCENT = 3;
+
+ /**
+ * Return the transparency type.
+ *
+ * @return One of {@link #OPAQUE}, {@link #BITMASK}, or {@link #TRANSLUCENT}.
+ */
+ int getTransparency();
+} // interface Transparency
diff --git a/libjava/classpath/java/awt/Window.java b/libjava/classpath/java/awt/Window.java
new file mode 100644
index 000000000..986d1304a
--- /dev/null
+++ b/libjava/classpath/java/awt/Window.java
@@ -0,0 +1,1286 @@
+/* Window.java --
+ Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.ComponentEvent;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowFocusListener;
+import java.awt.event.WindowListener;
+import java.awt.event.WindowStateListener;
+import java.awt.image.BufferStrategy;
+import java.awt.peer.WindowPeer;
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
+import java.util.EventListener;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.util.Vector;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleState;
+import javax.accessibility.AccessibleStateSet;
+
+/**
+ * This class represents a top-level window with no decorations.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Warren Levy (warrenl@cygnus.com)
+ */
+public class Window extends Container implements Accessible
+{
+ private static final long serialVersionUID = 4497834738069338734L;
+
+ // Serialized fields, from Sun's serialization spec.
+ private String warningString = null;
+ private int windowSerializedDataVersion = 0; // FIXME
+ /** @since 1.2 */
+ // private FocusManager focusMgr; // FIXME: what is this?
+ /** @since 1.2 */
+ private int state = 0;
+ /** @since 1.4 */
+ private boolean focusableWindowState = true;
+ /** @since 1.5 */
+ private boolean alwaysOnTop = false;
+
+ // A list of other top-level windows owned by this window.
+ private transient Vector ownedWindows = new Vector();
+
+ private transient WindowListener windowListener;
+ private transient WindowFocusListener windowFocusListener;
+ private transient WindowStateListener windowStateListener;
+
+ private transient boolean shown;
+
+ // This is package-private to avoid an accessor method.
+ transient Component windowFocusOwner;
+
+ /*
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_window_number;
+
+ protected class AccessibleAWTWindow extends AccessibleAWTContainer
+ {
+ private static final long serialVersionUID = 4215068635060671780L;
+
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.WINDOW;
+ }
+
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ AccessibleStateSet states = super.getAccessibleStateSet();
+ if (isActive())
+ states.add(AccessibleState.ACTIVE);
+ return states;
+ }
+ }
+
+ /**
+ * This (package access) constructor is used by subclasses that want
+ * to build windows that do not have parents. Eg. toplevel
+ * application frames. Subclasses cannot call super(null), since
+ * null is an illegal argument.
+ */
+ Window()
+ {
+ visible = false;
+ // Windows are the only Containers that default to being focus
+ // cycle roots.
+ focusCycleRoot = true;
+ setLayout(new BorderLayout());
+
+ GraphicsEnvironment g = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ graphicsConfig = g.getDefaultScreenDevice().getDefaultConfiguration();
+ }
+
+ Window(GraphicsConfiguration gc)
+ {
+ this();
+ graphicsConfig = gc;
+ }
+
+ /**
+ * Initializes a new instance of <code>Window</code> with the specified
+ * parent. The window will initially be invisible.
+ *
+ * @param owner The owning <code>Frame</code> of this window.
+ *
+ * @exception IllegalArgumentException If the owner's GraphicsConfiguration
+ * is not from a screen device, or if owner is null; this exception is always
+ * thrown when GraphicsEnvironment.isHeadless returns true.
+ */
+ public Window(Frame owner)
+ {
+ this (owner, owner.getGraphicsConfiguration ());
+ }
+
+ /**
+ * Initializes a new instance of <code>Window</code> with the specified
+ * parent. The window will initially be invisible.
+ *
+ * @exception IllegalArgumentException If the owner's GraphicsConfiguration
+ * is not from a screen device, or if owner is null; this exception is always
+ * thrown when GraphicsEnvironment.isHeadless returns true.
+ *
+ * @since 1.2
+ */
+ public Window(Window owner)
+ {
+ this (owner, owner.getGraphicsConfiguration ());
+ }
+
+ /**
+ * Initializes a new instance of <code>Window</code> with the specified
+ * parent. The window will initially be invisible.
+ *
+ * @exception IllegalArgumentException If owner is null or if gc is not from a
+ * screen device; this exception is always thrown when
+ * GraphicsEnvironment.isHeadless returns true.
+ *
+ * @since 1.3
+ */
+ public Window(Window owner, GraphicsConfiguration gc)
+ {
+ this ();
+
+ synchronized (getTreeLock())
+ {
+ if (owner == null)
+ throw new IllegalArgumentException ("owner must not be null");
+
+ parent = owner;
+ owner.ownedWindows.add(new WeakReference(this));
+ }
+
+ // FIXME: make this text visible in the window.
+ SecurityManager s = System.getSecurityManager();
+ if (s != null && ! s.checkTopLevelWindow(this))
+ warningString = System.getProperty("awt.appletWarning");
+
+ if (gc != null
+ && gc.getDevice().getType() != GraphicsDevice.TYPE_RASTER_SCREEN)
+ throw new IllegalArgumentException ("gc must be from a screen device");
+
+ if (gc == null)
+ graphicsConfig = GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice()
+ .getDefaultConfiguration();
+ else
+ graphicsConfig = gc;
+ }
+
+ /**
+ * Creates the native peer for this window.
+ */
+ public void addNotify()
+ {
+ if (peer == null)
+ peer = getToolkit().createWindow(this);
+ super.addNotify();
+ }
+
+ /**
+ * Relays out this window's child components at their preferred size.
+ *
+ * @specnote pack() doesn't appear to be called internally by show(), so
+ * we duplicate some of the functionality.
+ */
+ public void pack()
+ {
+ if (parent != null && !parent.isDisplayable())
+ parent.addNotify();
+ if (peer == null)
+ addNotify();
+
+ setSize(getPreferredSize());
+
+ validate();
+ }
+
+ /**
+ * Shows on-screen this window and any of its owned windows for whom
+ * isVisible returns true.
+ * @specnote: Deprecated starting in 1.5.
+ */
+ @Deprecated
+ public void show()
+ {
+ synchronized (getTreeLock())
+ {
+ if (peer == null)
+ addNotify();
+
+ validate();
+ if (visible)
+ toFront();
+ else
+ {
+ super.show();
+ // Show visible owned windows.
+ Iterator e = ownedWindows.iterator();
+ while (e.hasNext())
+ {
+ Window w = (Window) (((Reference) e.next()).get());
+ if (w != null)
+ {
+ if (w.isVisible())
+ w.getPeer().setVisible(true);
+ }
+ else
+ // Remove null weak reference from ownedWindows.
+ // Unfortunately this can't be done in the Window's
+ // finalize method because there is no way to guarantee
+ // synchronous access to ownedWindows there.
+ e.remove();
+ }
+ }
+ KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
+ manager.setGlobalFocusedWindow(this);
+
+ if (! shown)
+ {
+ FocusTraversalPolicy policy = getFocusTraversalPolicy();
+ Component initialFocusOwner = null;
+
+ if (policy != null)
+ initialFocusOwner = policy.getInitialComponent(this);
+
+ if (initialFocusOwner != null)
+ initialFocusOwner.requestFocusInWindow();
+
+ // Post WINDOW_OPENED from here.
+ if (windowListener != null
+ || (eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0)
+ {
+ WindowEvent ev = new WindowEvent(this,
+ WindowEvent.WINDOW_OPENED);
+ Toolkit tk = Toolkit.getDefaultToolkit();
+ tk.getSystemEventQueue().postEvent(ev);
+ }
+ shown = true;
+ }
+ }
+ }
+
+ /**
+ * @specnote: Deprecated starting in 1.5.
+ */
+ @Deprecated
+ public void hide()
+ {
+ // Hide visible owned windows.
+ synchronized (getTreeLock ())
+ {
+ Iterator e = ownedWindows.iterator();
+ while(e.hasNext())
+ {
+ Window w = (Window)(((Reference) e.next()).get());
+ if (w != null)
+ {
+ if (w.isVisible() && w.getPeer() != null)
+ w.getPeer().setVisible(false);
+ }
+ else
+ e.remove();
+ }
+ }
+ super.hide();
+ }
+
+ /**
+ * Destroys any resources associated with this window. This includes
+ * all components in the window and all owned top-level windows.
+ */
+ public void dispose()
+ {
+ hide();
+
+ synchronized (getTreeLock ())
+ {
+ Iterator e = ownedWindows.iterator();
+ while(e.hasNext())
+ {
+ Window w = (Window)(((Reference) e.next()).get());
+ if (w != null)
+ w.dispose();
+ else
+ // Remove null weak reference from ownedWindows.
+ e.remove();
+ }
+
+ for (int i = 0; i < ncomponents; ++i)
+ component[i].removeNotify();
+ this.removeNotify();
+
+ // Post WINDOW_CLOSED from here.
+ if (windowListener != null
+ || (eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0)
+ {
+ WindowEvent ev = new WindowEvent(this,
+ WindowEvent.WINDOW_CLOSED);
+ Toolkit tk = Toolkit.getDefaultToolkit();
+ tk.getSystemEventQueue().postEvent(ev);
+ }
+ }
+ }
+
+ /**
+ * Sends this window to the back so that all other windows display in
+ * front of it.
+ *
+ * If the window is set to be always-on-top, this will remove its
+ * always-on-top status.
+ */
+ public void toBack()
+ {
+ if (peer != null)
+ {
+ if( alwaysOnTop )
+ setAlwaysOnTop( false );
+ ( (WindowPeer) peer ).toBack();
+ }
+ }
+
+ /**
+ * Brings this window to the front so that it displays in front of
+ * any other windows.
+ */
+ public void toFront()
+ {
+ if (peer != null)
+ ( (WindowPeer) peer ).toFront();
+ }
+
+ /**
+ * Returns the toolkit used to create this window.
+ *
+ * @return The toolkit used to create this window.
+ *
+ * @specnote Unlike Component.getToolkit, this implementation always
+ * returns the value of Toolkit.getDefaultToolkit().
+ */
+ public Toolkit getToolkit()
+ {
+ return Toolkit.getDefaultToolkit();
+ }
+
+ /**
+ * Returns the warning string that will be displayed if this window is
+ * popped up by an unsecure applet or application.
+ *
+ * @return The unsecure window warning message.
+ */
+ public final String getWarningString()
+ {
+ return warningString;
+ }
+
+ /**
+ * Returns the locale that this window is configured for.
+ *
+ * @return The locale this window is configured for.
+ */
+ public Locale getLocale()
+ {
+ return locale == null ? Locale.getDefault() : locale;
+ }
+
+ /*
+ /** @since 1.2
+ public InputContext getInputContext()
+ {
+ // FIXME
+ }
+ */
+
+ /**
+ * Sets the cursor for this window to the specifiec cursor.
+ *
+ * @param cursor The new cursor for this window.
+ */
+ public void setCursor(Cursor cursor)
+ {
+ super.setCursor(cursor);
+ }
+
+ public Window getOwner()
+ {
+ return (Window) parent;
+ }
+
+ /** @since 1.2 */
+ public Window[] getOwnedWindows()
+ {
+ Window [] trimmedList;
+ synchronized (getTreeLock ())
+ {
+ // Windows with non-null weak references in ownedWindows.
+ Window [] validList = new Window [ownedWindows.size()];
+
+ Iterator e = ownedWindows.iterator();
+ int numValid = 0;
+ while (e.hasNext())
+ {
+ Window w = (Window)(((Reference) e.next()).get());
+ if (w != null)
+ validList[numValid++] = w;
+ else
+ // Remove null weak reference from ownedWindows.
+ e.remove();
+ }
+
+ if (numValid != validList.length)
+ {
+ trimmedList = new Window [numValid];
+ System.arraycopy (validList, 0, trimmedList, 0, numValid);
+ }
+ else
+ trimmedList = validList;
+ }
+ return trimmedList;
+ }
+
+ /**
+ * Adds the specified listener to the list of <code>WindowListeners</code>
+ * that will receive events for this window.
+ *
+ * @param listener The <code>WindowListener</code> to add.
+ */
+ public synchronized void addWindowListener(WindowListener listener)
+ {
+ if (listener != null)
+ {
+ newEventsOnly = true;
+ windowListener = AWTEventMulticaster.add(windowListener, listener);
+ }
+ }
+
+ /**
+ * Removes the specified listener from the list of
+ * <code>WindowListeners</code> that will receive events for this window.
+ *
+ * @param listener The <code>WindowListener</code> to remove.
+ */
+ public synchronized void removeWindowListener(WindowListener listener)
+ {
+ windowListener = AWTEventMulticaster.remove(windowListener, listener);
+ }
+
+ /**
+ * Returns an array of all the window listeners registered on this window.
+ *
+ * @since 1.4
+ */
+ public synchronized WindowListener[] getWindowListeners()
+ {
+ return (WindowListener[])
+ AWTEventMulticaster.getListeners(windowListener,
+ WindowListener.class);
+ }
+
+ /**
+ * Returns an array of all the window focus listeners registered on this
+ * window.
+ *
+ * @since 1.4
+ */
+ public synchronized WindowFocusListener[] getWindowFocusListeners()
+ {
+ return (WindowFocusListener[])
+ AWTEventMulticaster.getListeners(windowFocusListener,
+ WindowFocusListener.class);
+ }
+
+ /**
+ * Returns an array of all the window state listeners registered on this
+ * window.
+ *
+ * @since 1.4
+ */
+ public synchronized WindowStateListener[] getWindowStateListeners()
+ {
+ return (WindowStateListener[])
+ AWTEventMulticaster.getListeners(windowStateListener,
+ WindowStateListener.class);
+ }
+
+ /**
+ * Adds the specified listener to this window.
+ */
+ public void addWindowFocusListener (WindowFocusListener wfl)
+ {
+ if (wfl != null)
+ {
+ newEventsOnly = true;
+ windowFocusListener = AWTEventMulticaster.add (windowFocusListener,
+ wfl);
+ }
+ }
+
+ /**
+ * Adds the specified listener to this window.
+ *
+ * @since 1.4
+ */
+ public void addWindowStateListener (WindowStateListener wsl)
+ {
+ if (wsl != null)
+ {
+ newEventsOnly = true;
+ windowStateListener = AWTEventMulticaster.add (windowStateListener,
+ wsl);
+ }
+ }
+
+ /**
+ * Removes the specified listener from this window.
+ */
+ public void removeWindowFocusListener (WindowFocusListener wfl)
+ {
+ windowFocusListener = AWTEventMulticaster.remove (windowFocusListener, wfl);
+ }
+
+ /**
+ * Removes the specified listener from this window.
+ *
+ * @since 1.4
+ */
+ public void removeWindowStateListener (WindowStateListener wsl)
+ {
+ windowStateListener = AWTEventMulticaster.remove (windowStateListener, wsl);
+ }
+
+ /**
+ * Returns an array of all the objects currently registered as FooListeners
+ * upon this Window. FooListeners are registered using the addFooListener
+ * method.
+ *
+ * @exception ClassCastException If listenerType doesn't specify a class or
+ * interface that implements java.util.EventListener.
+ *
+ * @since 1.3
+ */
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
+ {
+ if (listenerType == WindowListener.class)
+ return (T[]) getWindowListeners();
+ return super.getListeners(listenerType);
+ }
+
+ void dispatchEventImpl(AWTEvent e)
+ {
+ if (e.getID() == ComponentEvent.COMPONENT_RESIZED)
+ {
+ invalidate();
+ validate();
+ }
+ super.dispatchEventImpl(e);
+ }
+
+ /**
+ * Processes the specified event for this window. If the event is an
+ * instance of <code>WindowEvent</code>, then
+ * <code>processWindowEvent()</code> is called to process the event,
+ * otherwise the superclass version of this method is invoked.
+ *
+ * @param evt The event to process.
+ */
+ protected void processEvent(AWTEvent evt)
+ {
+ if (evt instanceof WindowEvent)
+ {
+ WindowEvent we = (WindowEvent) evt;
+ switch (evt.getID())
+ {
+ case WindowEvent.WINDOW_OPENED:
+ case WindowEvent.WINDOW_CLOSED:
+ case WindowEvent.WINDOW_CLOSING:
+ case WindowEvent.WINDOW_ICONIFIED:
+ case WindowEvent.WINDOW_DEICONIFIED:
+ case WindowEvent.WINDOW_ACTIVATED:
+ case WindowEvent.WINDOW_DEACTIVATED:
+ processWindowEvent(we);
+ break;
+ case WindowEvent.WINDOW_GAINED_FOCUS:
+ case WindowEvent.WINDOW_LOST_FOCUS:
+ processWindowFocusEvent(we);
+ break;
+ case WindowEvent.WINDOW_STATE_CHANGED:
+ processWindowStateEvent(we);
+ break;
+ }
+ }
+ else
+ super.processEvent(evt);
+ }
+
+ /**
+ * Dispatches this event to any listeners that are listening for
+ * <code>WindowEvents</code> on this window. This method only gets
+ * invoked if it is enabled via <code>enableEvents()</code> or if
+ * a listener has been added.
+ *
+ * @param evt The event to process.
+ */
+ protected void processWindowEvent(WindowEvent evt)
+ {
+ if (windowListener != null)
+ {
+ switch (evt.getID())
+ {
+ case WindowEvent.WINDOW_ACTIVATED:
+ windowListener.windowActivated(evt);
+ break;
+ case WindowEvent.WINDOW_CLOSED:
+ windowListener.windowClosed(evt);
+ break;
+ case WindowEvent.WINDOW_CLOSING:
+ windowListener.windowClosing(evt);
+ break;
+ case WindowEvent.WINDOW_DEACTIVATED:
+ windowListener.windowDeactivated(evt);
+ break;
+ case WindowEvent.WINDOW_DEICONIFIED:
+ windowListener.windowDeiconified(evt);
+ break;
+ case WindowEvent.WINDOW_ICONIFIED:
+ windowListener.windowIconified(evt);
+ break;
+ case WindowEvent.WINDOW_OPENED:
+ windowListener.windowOpened(evt);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Identifies if this window is active. The active window is a Frame or
+ * Dialog that has focus or owns the active window.
+ *
+ * @return true if active, else false.
+ * @since 1.4
+ */
+ public boolean isActive()
+ {
+ KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
+ return manager.getActiveWindow() == this;
+ }
+
+ /**
+ * Identifies if this window is focused. A window is focused if it is the
+ * focus owner or it contains the focus owner.
+ *
+ * @return true if focused, else false.
+ * @since 1.4
+ */
+ public boolean isFocused()
+ {
+ KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
+ return manager.getFocusedWindow() == this;
+ }
+
+ /**
+ * Returns the child window that has focus if this window is active.
+ * This method returns <code>null</code> if this window is not active
+ * or no children have focus.
+ *
+ * @return The component that has focus, or <code>null</code> if no
+ * component has focus.
+ */
+ public Component getFocusOwner ()
+ {
+ KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
+
+ Window activeWindow = manager.getActiveWindow ();
+
+ // The currently-focused Component belongs to the active Window.
+ if (activeWindow == this)
+ return manager.getFocusOwner ();
+ else
+ return null;
+ }
+
+ /**
+ * Returns the child component of this window that would receive
+ * focus if this window were to become focused. If the window
+ * already has the top-level focus, then this method returns the
+ * same component as getFocusOwner. If no child component has
+ * requested focus within the window, then the initial focus owner
+ * is returned. If this is a non-focusable window, this method
+ * returns null.
+ *
+ * @return the child component of this window that most recently had
+ * the focus, or <code>null</code>
+ * @since 1.4
+ */
+ public Component getMostRecentFocusOwner ()
+ {
+ return windowFocusOwner;
+ }
+
+ /**
+ * Set the focus owner for this window. This method is used to
+ * remember which component was focused when this window lost
+ * top-level focus, so that when it regains top-level focus the same
+ * child component can be refocused.
+ *
+ * @param windowFocusOwner the component in this window that owns
+ * the focus.
+ */
+ void setFocusOwner (Component windowFocusOwner)
+ {
+ this.windowFocusOwner = windowFocusOwner;
+ }
+
+ /**
+ * Post a Java 1.0 event to the event queue.
+ *
+ * @param e The event to post.
+ *
+ * @deprecated
+ */
+ public boolean postEvent(Event e)
+ {
+ return handleEvent (e);
+ }
+
+ /**
+ * Tests whether or not this window is visible on the screen.
+ *
+ * In contrast to the normal behaviour of Container, which is that
+ * a container is showing if its parent is visible and showing, a Window
+ * is even showing, if its parent (i.e. an invisible Frame) is not showing.
+ *
+ * @return <code>true</code> if this window is visible, <code>false</code>
+ * otherwise.
+ */
+ public boolean isShowing()
+ {
+ return isVisible();
+ }
+
+ public void setLocationRelativeTo(Component c)
+ {
+ int x = 0;
+ int y = 0;
+
+ if (c == null || !c.isShowing())
+ {
+ GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ Point center = ge.getCenterPoint();
+ x = center.x - (width / 2);
+ y = center.y - (height / 2);
+ }
+ else
+ {
+ int cWidth = c.getWidth();
+ int cHeight = c.getHeight();
+ Dimension screenSize = getToolkit().getScreenSize();
+
+ x = c.getLocationOnScreen().x;
+ y = c.getLocationOnScreen().y;
+
+ // If bottom of component is cut off, window placed
+ // on the left or the right side of component
+ if ((y + cHeight) > screenSize.height)
+ {
+ // If the right side of the component is closer to the center
+ if ((screenSize.width / 2 - x) <= 0)
+ {
+ if ((x - width) >= 0)
+ x -= width;
+ else
+ x = 0;
+ }
+ else
+ {
+ if ((x + cWidth + width) <= screenSize.width)
+ x += cWidth;
+ else
+ x = screenSize.width - width;
+ }
+
+ y = screenSize.height - height;
+ }
+ else if (cWidth > width || cHeight > height)
+ {
+ // If right side of component is cut off
+ if ((x + width) > screenSize.width)
+ x = screenSize.width - width;
+ // If left side of component is cut off
+ else if (x < 0)
+ x = 0;
+ else
+ x += (cWidth - width) / 2;
+
+ y += (cHeight - height) / 2;
+ }
+ else
+ {
+ // If right side of component is cut off
+ if ((x + width) > screenSize.width)
+ x = screenSize.width - width;
+ // If left side of component is cut off
+ else if (x < 0 || (x - (width - cWidth) / 2) < 0)
+ x = 0;
+ else
+ x -= (width - cWidth) / 2;
+
+ if ((y - (height - cHeight) / 2) > 0)
+ y -= (height - cHeight) / 2;
+ else
+ y = 0;
+ }
+ }
+
+ setLocation(x, y);
+ }
+
+ /**
+ * A BltBufferStrategy for windows.
+ */
+ private class WindowBltBufferStrategy extends BltBufferStrategy
+ {
+ /**
+ * Creates a block transfer strategy for this window.
+ *
+ * @param numBuffers the number of buffers in this strategy
+ * @param accelerated true if the buffer should be accelerated,
+ * false otherwise
+ */
+ WindowBltBufferStrategy(int numBuffers, boolean accelerated)
+ {
+ super(numBuffers,
+ new BufferCapabilities(new ImageCapabilities(accelerated),
+ new ImageCapabilities(accelerated),
+ BufferCapabilities.FlipContents.COPIED));
+ }
+ }
+
+ /**
+ * A FlipBufferStrategy for windows.
+ */
+ private class WindowFlipBufferStrategy extends FlipBufferStrategy
+ {
+ /**
+ * Creates a flip buffer strategy for this window.
+ *
+ * @param numBuffers the number of buffers in this strategy
+ *
+ * @throws AWTException if the requested number of buffers is not
+ * supported
+ */
+ WindowFlipBufferStrategy(int numBuffers)
+ throws AWTException
+ {
+ super(numBuffers,
+ new BufferCapabilities(new ImageCapabilities(true),
+ new ImageCapabilities(true),
+ BufferCapabilities.FlipContents.COPIED));
+ }
+ }
+
+ /**
+ * Creates a buffering strategy that manages how this window is
+ * repainted. This method attempts to create the optimum strategy
+ * based on the desired number of buffers. Hardware or software
+ * acceleration may be used.
+ *
+ * createBufferStrategy attempts different levels of optimization,
+ * but guarantees that some strategy with the requested number of
+ * buffers will be created even if it is not optimal. First it
+ * attempts to create a page flipping strategy, then an accelerated
+ * blitting strategy, then an unaccelerated blitting strategy.
+ *
+ * Calling this method causes any existing buffer strategy to be
+ * destroyed.
+ *
+ * @param numBuffers the number of buffers in this strategy
+ *
+ * @throws IllegalArgumentException if requested number of buffers
+ * is less than one
+ * @throws IllegalStateException if this window is not displayable
+ *
+ * @since 1.4
+ */
+ public void createBufferStrategy(int numBuffers)
+ {
+ if (numBuffers < 1)
+ throw new IllegalArgumentException("Window.createBufferStrategy: number"
+ + " of buffers is less than one");
+
+ if (!isDisplayable())
+ throw new IllegalStateException("Window.createBufferStrategy: window is"
+ + " not displayable");
+
+ BufferStrategy newStrategy = null;
+
+ // try a flipping strategy
+ try
+ {
+ newStrategy = new WindowFlipBufferStrategy(numBuffers);
+ }
+ catch (AWTException e)
+ {
+ }
+
+ // fall back to an accelerated blitting strategy
+ if (newStrategy == null)
+ newStrategy = new WindowBltBufferStrategy(numBuffers, true);
+
+ bufferStrategy = newStrategy;
+ }
+
+ /**
+ * Creates a buffering strategy that manages how this window is
+ * repainted. This method attempts to create a strategy based on
+ * the specified capabilities and throws an exception if the
+ * requested strategy is not supported.
+ *
+ * Calling this method causes any existing buffer strategy to be
+ * destroyed.
+ *
+ * @param numBuffers the number of buffers in this strategy
+ * @param caps the requested buffering capabilities
+ *
+ * @throws AWTException if the requested capabilities are not
+ * supported
+ * @throws IllegalArgumentException if requested number of buffers
+ * is less than one or if caps is null
+ *
+ * @since 1.4
+ */
+ public void createBufferStrategy(int numBuffers, BufferCapabilities caps)
+ throws AWTException
+ {
+ if (numBuffers < 1)
+ throw new IllegalArgumentException("Window.createBufferStrategy: number"
+ + " of buffers is less than one");
+
+ if (caps == null)
+ throw new IllegalArgumentException("Window.createBufferStrategy:"
+ + " capabilities object is null");
+
+ // a flipping strategy was requested
+ if (caps.isPageFlipping())
+ bufferStrategy = new WindowFlipBufferStrategy(numBuffers);
+ else
+ bufferStrategy = new WindowBltBufferStrategy(numBuffers, true);
+ }
+
+ /**
+ * Returns the buffer strategy used by the window.
+ *
+ * @return the buffer strategy.
+ * @since 1.4
+ */
+ public BufferStrategy getBufferStrategy()
+ {
+ return bufferStrategy;
+ }
+
+ /**
+ * @since 1.2
+ *
+ * @deprecated replaced by Component.applyComponentOrientation.
+ */
+ public void applyResourceBundle(ResourceBundle rb)
+ {
+ applyComponentOrientation(ComponentOrientation.getOrientation(rb));
+ }
+
+ /**
+ * @since 1.2
+ *
+ * @deprecated
+ */
+ public void applyResourceBundle(String rbName)
+ {
+ ResourceBundle rb = ResourceBundle.getBundle(rbName, Locale.getDefault(),
+ ClassLoader.getSystemClassLoader());
+ if (rb != null)
+ applyResourceBundle(rb);
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this <code>Window</code>.
+ * The context is created, if necessary.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ /* Create the context if this is the first request */
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleAWTWindow();
+ return accessibleContext;
+ }
+
+ /**
+ * Get graphics configuration. The implementation for Window will
+ * not ask any parent containers, since Window is a toplevel
+ * window and not actually embedded in the parent component.
+ */
+ public GraphicsConfiguration getGraphicsConfiguration()
+ {
+ GraphicsConfiguration conf = graphicsConfig;
+ if (conf == null)
+ {
+ conf = GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice().getDefaultConfiguration();
+ graphicsConfig = conf;
+ }
+ return conf;
+ }
+
+ protected void processWindowFocusEvent(WindowEvent event)
+ {
+ if (windowFocusListener != null)
+ {
+ switch (event.getID ())
+ {
+ case WindowEvent.WINDOW_GAINED_FOCUS:
+ windowFocusListener.windowGainedFocus (event);
+ break;
+
+ case WindowEvent.WINDOW_LOST_FOCUS:
+ windowFocusListener.windowLostFocus (event);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ /**
+ * @since 1.4
+ */
+ protected void processWindowStateEvent(WindowEvent event)
+ {
+ if (windowStateListener != null
+ && event.getID () == WindowEvent.WINDOW_STATE_CHANGED)
+ windowStateListener.windowStateChanged (event);
+ }
+
+ /**
+ * Returns whether this <code>Window</code> can get the focus or not.
+ *
+ * @since 1.4
+ */
+ public final boolean isFocusableWindow ()
+ {
+ if (getFocusableWindowState () == false)
+ return false;
+
+ if (this instanceof Dialog
+ || this instanceof Frame)
+ return true;
+
+ // FIXME: Implement more possible cases for returning true.
+
+ return false;
+ }
+
+ /**
+ * Returns the value of the focusableWindowState property.
+ *
+ * @since 1.4
+ */
+ public boolean getFocusableWindowState ()
+ {
+ return focusableWindowState;
+ }
+
+ /**
+ * Sets the value of the focusableWindowState property.
+ *
+ * @since 1.4
+ */
+ public void setFocusableWindowState (boolean focusableWindowState)
+ {
+ this.focusableWindowState = focusableWindowState;
+ }
+
+ /**
+ * Check whether this Container is a focus cycle root.
+ * Returns always <code>true</code> as Windows are the
+ * root of the focus cycle.
+ *
+ * @return Always <code>true</code>.
+ *
+ * @since 1.4
+ */
+ public final boolean isFocusCycleRoot()
+ {
+ return true;
+ }
+
+ /**
+ * Set whether or not this Container is the root of a focus
+ * traversal cycle. Windows are the root of the focus cycle
+ * and therefore this method does nothing.
+ *
+ * @param focusCycleRoot ignored.
+ *
+ * @since 1.4
+ */
+ public final void setFocusCycleRoot(boolean focusCycleRoot)
+ {
+ // calls to the method are ignored
+ }
+
+ /**
+ * Returns the root container that owns the focus cycle where this
+ * component resides. Windows have no ancestors and this method
+ * returns always <code>null</code>.
+ *
+ * @return Always <code>null</code>.
+ * @since 1.4
+ */
+ public final Container getFocusCycleRootAncestor()
+ {
+ return null;
+ }
+
+ /**
+ * Returns whether the Windows is an always-on-top window,
+ * meaning whether the window can be obscured by other windows or not.
+ *
+ * @return <code>true</code> if the windows is always-on-top,
+ * <code>false</code> otherwise.
+ * @since 1.5
+ */
+ public final boolean isAlwaysOnTop()
+ {
+ return alwaysOnTop;
+ }
+
+ /**
+ * Sets the always-on-top state of this window (if supported).
+ *
+ * Setting a window to always-on-top means it will not be obscured
+ * by any other windows (with the exception of other always-on-top
+ * windows). Not all platforms may support this.
+ *
+ * If an window's always-on-top status is changed to false, the window
+ * will remain at the front but not be anchored there.
+ *
+ * Calling toBack() on an always-on-top window will change its
+ * always-on-top status to false.
+ *
+ * @since 1.5
+ */
+ public final void setAlwaysOnTop(boolean alwaysOnTop)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission( new AWTPermission("setWindowAlwaysOnTop") );
+
+ if( this.alwaysOnTop == alwaysOnTop )
+ return;
+
+ if( alwaysOnTop )
+ toFront();
+
+ firePropertyChange("alwaysOnTop", this.alwaysOnTop, alwaysOnTop );
+ this.alwaysOnTop = alwaysOnTop;
+
+ if (peer != null)
+ ( (WindowPeer) peer).updateAlwaysOnTop();
+ else
+ System.out.println("Null peer?!");
+ }
+
+ /**
+ * Generate a unique name for this window.
+ *
+ * @return A unique name for this window.
+ */
+ String generateName()
+ {
+ return "win" + getUniqueLong();
+ }
+
+ /**
+ * Overridden to handle WindowEvents.
+ *
+ * @return <code>true</code> when the specified event type is enabled,
+ * <code>false</code> otherwise
+ */
+ boolean eventTypeEnabled(int type)
+ {
+ boolean enabled = false;
+ switch (type)
+ {
+ case WindowEvent.WINDOW_OPENED:
+ case WindowEvent.WINDOW_CLOSED:
+ case WindowEvent.WINDOW_CLOSING:
+ case WindowEvent.WINDOW_ICONIFIED:
+ case WindowEvent.WINDOW_DEICONIFIED:
+ case WindowEvent.WINDOW_ACTIVATED:
+ case WindowEvent.WINDOW_DEACTIVATED:
+ enabled = ((eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0)
+ || windowListener != null;
+ break;
+ case WindowEvent.WINDOW_GAINED_FOCUS:
+ case WindowEvent.WINDOW_LOST_FOCUS:
+ enabled = ((eventMask & AWTEvent.WINDOW_FOCUS_EVENT_MASK) != 0)
+ || windowFocusListener != null;
+ break;
+ case WindowEvent.WINDOW_STATE_CHANGED:
+ enabled = ((eventMask & AWTEvent.WINDOW_STATE_EVENT_MASK) != 0)
+ || windowStateListener != null;
+ break;
+ default:
+ enabled = super.eventTypeEnabled(type);
+ }
+ return enabled;
+ }
+
+ private static synchronized long getUniqueLong()
+ {
+ return next_window_number++;
+ }
+}
diff --git a/libjava/classpath/java/awt/color/CMMException.java b/libjava/classpath/java/awt/color/CMMException.java
new file mode 100644
index 000000000..ab328ec84
--- /dev/null
+++ b/libjava/classpath/java/awt/color/CMMException.java
@@ -0,0 +1,63 @@
+/* CMMException.java -- error in the native CMM
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.color;
+
+/**
+ * Thrown when there is an error in the native CMM.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @status updated to 1.4
+ */
+public class CMMException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 5775558044142994965L;
+
+ /**
+ * Create a new instance with a specified detailed error message.
+ *
+ * @param message the message
+ */
+ public CMMException(String message)
+ {
+ super(message);
+ }
+} // class CMMException
diff --git a/libjava/classpath/java/awt/color/ColorSpace.java b/libjava/classpath/java/awt/color/ColorSpace.java
new file mode 100644
index 000000000..79369da71
--- /dev/null
+++ b/libjava/classpath/java/awt/color/ColorSpace.java
@@ -0,0 +1,183 @@
+/* ColorSpace.java -- transforms between color spaces
+ Copyright (C) 2000, 2002 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.color;
+
+import java.io.Serializable;
+
+/**
+ * NEEDS DOCUMENTATION
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ * @since 1.2
+ */
+public abstract class ColorSpace implements Serializable
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = -409452704308689724L;
+
+ public static final int TYPE_XYZ = 0;
+ public static final int TYPE_Lab = 1;
+ public static final int TYPE_Luv = 2;
+ public static final int TYPE_YCbCr = 3;
+ public static final int TYPE_Yxy = 4;
+ public static final int TYPE_RGB = 5;
+ public static final int TYPE_GRAY = 6;
+ public static final int TYPE_HSV = 7;
+ public static final int TYPE_HLS = 8;
+ public static final int TYPE_CMYK = 9;
+ // mysterious gap in the enumeration sequenece
+ public static final int TYPE_CMY = 11;
+ public static final int TYPE_2CLR = 12;
+ public static final int TYPE_3CLR = 13;
+ public static final int TYPE_4CLR = 14;
+ public static final int TYPE_5CLR = 15;
+ public static final int TYPE_6CLR = 16;
+ public static final int TYPE_7CLR = 17;
+ public static final int TYPE_8CLR = 18;
+ public static final int TYPE_9CLR = 19;
+ public static final int TYPE_ACLR = 20;
+ public static final int TYPE_BCLR = 21;
+ public static final int TYPE_CCLR = 22;
+ public static final int TYPE_DCLR = 23;
+ public static final int TYPE_ECLR = 24;
+ public static final int TYPE_FCLR = 25;
+
+ public static final int CS_sRGB = 1000;
+ public static final int CS_LINEAR_RGB = 1004;
+ public static final int CS_CIEXYZ = 1001;
+ public static final int CS_PYCC = 1002;
+ public static final int CS_GRAY = 1003;
+
+ private static final int CS_BASE = CS_sRGB;
+ private static final int CS_END = CS_LINEAR_RGB + 1;
+ private static final int CS_COUNT = CS_END - CS_BASE;
+
+ // Instances are lazily instantiated
+ private static final ColorSpace[] INSTANCES = new ColorSpace[CS_COUNT];
+
+ /**
+ * @serial
+ */
+ // Visible in subclass.
+ final int type;
+
+ /**
+ * @serial
+ */
+ // Visible in subclass.
+ final int numComponents;
+
+ protected ColorSpace(int type, int numcomponents)
+ {
+ this.type = type;
+ numComponents = numcomponents;
+ }
+
+ public static ColorSpace getInstance(int colorspace)
+ {
+ if ((colorspace >= CS_BASE) && (colorspace < CS_END))
+ {
+ int instanceIndex = colorspace - CS_BASE;
+ if (INSTANCES[instanceIndex] == null)
+ {
+ ICC_Profile profile = new ICC_Profile(colorspace);
+ INSTANCES[instanceIndex] = new ICC_ColorSpace(profile);
+ }
+ return INSTANCES[instanceIndex];
+ }
+ throw new IllegalArgumentException("unknown/unsupported colorspace");
+ }
+
+ public boolean isCS_sRGB()
+ {
+ return type == CS_sRGB;
+ }
+
+ /**
+ * Transforms a color value assumed to be in this ColorSpace into a value in
+ * the default CS_sRGB color space.
+ *
+ * @exception ArrayIndexOutOfBoundsException If array length is not at least
+ * the number of components in this ColorSpace.
+ */
+ public abstract float[] toRGB(float[] colorvalue);
+
+ public abstract float[] fromRGB(float[] rgbvalue);
+
+ public abstract float[] toCIEXYZ(float[] colorvalue);
+
+ public abstract float[] fromCIEXYZ(float[] colorvalue);
+
+ public int getType()
+ {
+ return type;
+ }
+
+ public int getNumComponents()
+ {
+ return numComponents;
+ }
+
+ public String getName(int idx)
+ {
+ return "type " + type;
+ }
+
+ /**
+ * @since 1.4
+ */
+ public float getMinValue(int idx)
+ {
+ if (idx < 0 || idx >= numComponents)
+ throw new IllegalArgumentException();
+ return 0;
+ }
+
+ /**
+ * @since 1.4
+ */
+ public float getMaxValue(int idx)
+ {
+ if (idx < 0 || idx >= numComponents)
+ throw new IllegalArgumentException();
+ return 1;
+ }
+} // class ColorSpace
diff --git a/libjava/classpath/java/awt/color/ICC_ColorSpace.java b/libjava/classpath/java/awt/color/ICC_ColorSpace.java
new file mode 100644
index 000000000..ac636fb26
--- /dev/null
+++ b/libjava/classpath/java/awt/color/ICC_ColorSpace.java
@@ -0,0 +1,314 @@
+/* ICC_ColorSpace.java -- the canonical color space implementation
+ Copyright (C) 2000, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.color;
+
+import gnu.java.awt.color.CieXyzConverter;
+import gnu.java.awt.color.ClutProfileConverter;
+import gnu.java.awt.color.ColorSpaceConverter;
+import gnu.java.awt.color.GrayProfileConverter;
+import gnu.java.awt.color.GrayScaleConverter;
+import gnu.java.awt.color.LinearRGBConverter;
+import gnu.java.awt.color.PyccConverter;
+import gnu.java.awt.color.RgbProfileConverter;
+import gnu.java.awt.color.SrgbConverter;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+
+/**
+ * ICC_ColorSpace - an implementation of ColorSpace
+ *
+ * While an ICC_Profile class abstracts the data in an ICC profile file
+ * an ICC_ColorSpace performs the color space conversions defined by
+ * an ICC_Profile instance.
+ *
+ * Typically, an ICC_Profile will either be created using getInstance,
+ * either from the built-in colorspaces, or from an ICC profile file.
+ * Then a ICC_Colorspace will be used to perform transforms from the
+ * device colorspace to and from the profile color space.
+ *
+ * The PCS used by ColorSpace is CIE XYZ relative a D50 white point.
+ * (Profiles using a CIE Lab PCS will have their input and output converted
+ * to D50 CIE XYZ accordingly.
+ *
+ * Note that a valid profile may not contain transforms in both directions,
+ * in which case the output may be undefined.
+ * All built-in colorspaces have bidirectional transforms, but developers
+ * using an ICC profile file may want to check the profile class using
+ * the ICC_Profile.getProfileClass() method. Input class profiles are
+ * guaranteed to have transforms to the PCS, output class profiles are
+ * guaranteed to have transforms from the PCS to device space.
+ *
+ * @author Sven de Marothy
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ * @since 1.2
+ */
+public class ICC_ColorSpace extends ColorSpace
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 3455889114070431483L;
+
+ /**
+ * @serial
+ */
+ private ICC_Profile thisProfile;
+
+ /**
+ * @serial
+ */
+ private float[] minVal;
+
+ /**
+ * @serial
+ */
+ private float[] maxVal;
+
+ /**
+ * @serial
+ */
+ private float[] diffMinMax;
+
+ /**
+ * @serial
+ */
+ private float[] invDiffMinMax;
+
+ /**
+ * @serial
+ */
+ private boolean needScaleInit;
+
+ /**
+ * Tells us if the PCS is CIE LAB (must be CIEXYZ otherwise)
+ */
+ private transient int type;
+ private transient int nComponents;
+ private transient ColorSpaceConverter converter;
+
+ /**
+ * Constructs a new ICC_ColorSpace from an ICC_Profile object.
+ *
+ * @exception IllegalArgumentException If profile is inappropriate for
+ * representing a ColorSpace.
+ */
+ public ICC_ColorSpace(ICC_Profile profile)
+ {
+ super(profile.getColorSpaceType(), profile.getNumComponents());
+
+ converter = getConverter(profile);
+ thisProfile = profile;
+ nComponents = profile.getNumComponents();
+ type = profile.getColorSpaceType();
+ makeArrays();
+ }
+
+ /**
+ * Return the profile
+ */
+ public ICC_Profile getProfile()
+ {
+ return thisProfile;
+ }
+
+ /**
+ * Transforms a color value assumed to be in this ColorSpace into a value in
+ * the default CS_sRGB color space.
+ *
+ * @exception ArrayIndexOutOfBoundsException If array length is not at least
+ * the number of components in this ColorSpace.
+ */
+ public float[] toRGB(float[] colorvalue)
+ {
+ return converter.toRGB(colorvalue);
+ }
+
+ /**
+ * Transforms a color value assumed to be in the default CS_sRGB color space
+ * into this ColorSpace.
+ *
+ * @exception ArrayIndexOutOfBoundsException If array length is not at
+ * least 3.
+ */
+ public float[] fromRGB(float[] rgbvalue)
+ {
+ return converter.fromRGB(rgbvalue);
+ }
+
+ /**
+ * Transforms a color value assumed to be in this ColorSpace into the
+ * CS_CIEXYZ conversion color space.
+ *
+ * @exception ArrayIndexOutOfBoundsException If array length is not at
+ * least the number of components in this ColorSpace.
+ */
+ public float[] toCIEXYZ(float[] colorvalue)
+ {
+ return converter.toCIEXYZ(colorvalue);
+ }
+
+ /**
+ * Transforms a color value assumed to be in the CS_CIEXYZ conversion color
+ * space into this ColorSpace.
+ *
+ * @exception ArrayIndexOutOfBoundsException If array length is not at
+ * least 3.
+ */
+ public float[] fromCIEXYZ(float[] colorvalue)
+ {
+ return converter.fromCIEXYZ(colorvalue);
+ }
+
+ public boolean isCS_sRGB()
+ {
+ return converter instanceof SrgbConverter;
+ }
+
+ /**
+ * Returns the minimum normalized color component value for the specified
+ * component.
+ *
+ * @exception IllegalArgumentException If component is less than 0 or greater
+ * than numComponents - 1.
+ *
+ * @since 1.4
+ */
+ public float getMinValue(int idx)
+ {
+ // FIXME: Not 100% certain of this.
+ if (type == ColorSpace.TYPE_Lab && (idx == 1 || idx == 2))
+ return -128f;
+
+ if (idx < 0 || idx >= nComponents)
+ throw new IllegalArgumentException();
+ return 0;
+ }
+
+ /**
+ * Returns the maximum normalized color component value for the specified
+ * component.
+ *
+ * @exception IllegalArgumentException If component is less than 0 or greater
+ * than numComponents - 1.
+ *
+ * @since 1.4
+ */
+ public float getMaxValue(int idx)
+ {
+ if (type == ColorSpace.TYPE_XYZ && idx >= 0 && idx <= 2)
+ return 1 + 32767 / 32768f;
+ else if (type == ColorSpace.TYPE_Lab)
+ {
+ if (idx == 0)
+ return 100;
+ if (idx == 1 || idx == 2)
+ return 127;
+ }
+ if (idx < 0 || idx >= nComponents)
+ throw new IllegalArgumentException();
+ return 1;
+ }
+
+ /**
+ * Returns a colorspace converter suitable for a given profile
+ */
+ private ColorSpaceConverter getConverter(ICC_Profile profile)
+ {
+ ColorSpaceConverter converter;
+ switch (profile.isPredefined())
+ {
+ case CS_sRGB:
+ converter = new SrgbConverter();
+ break;
+ case CS_CIEXYZ:
+ converter = new CieXyzConverter();
+ break;
+ case CS_GRAY:
+ converter = new GrayScaleConverter();
+ break;
+ case CS_LINEAR_RGB:
+ converter = new LinearRGBConverter();
+ break;
+ case CS_PYCC:
+ converter = new PyccConverter();
+ break;
+ default:
+ if (profile instanceof ICC_ProfileRGB)
+ converter = new RgbProfileConverter((ICC_ProfileRGB) profile);
+ else if (profile instanceof ICC_ProfileGray)
+ converter = new GrayProfileConverter((ICC_ProfileGray) profile);
+ else
+ converter = new ClutProfileConverter(profile);
+ break;
+ }
+ return converter;
+ }
+
+ /**
+ * Serialization compatibility requires these variable to be set,
+ * although we don't use them. Perhaps we should?
+ */
+ private void makeArrays()
+ {
+ minVal = new float[nComponents];
+ maxVal = new float[nComponents];
+
+ invDiffMinMax = diffMinMax = null;
+ for (int i = 0; i < nComponents; i++)
+ {
+ minVal[i] = getMinValue(i);
+ maxVal[i] = getMaxValue(i);
+ }
+ needScaleInit = true;
+ }
+
+ /**
+ * Deserializes the object
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ // set up objects
+ converter = getConverter(thisProfile);
+ nComponents = thisProfile.getNumComponents();
+ type = thisProfile.getColorSpaceType();
+ }
+} // class ICC_ColorSpace
diff --git a/libjava/classpath/java/awt/color/ICC_Profile.java b/libjava/classpath/java/awt/color/ICC_Profile.java
new file mode 100644
index 000000000..0eef22e49
--- /dev/null
+++ b/libjava/classpath/java/awt/color/ICC_Profile.java
@@ -0,0 +1,1249 @@
+/* ICC_Profile.java -- color space profiling
+ Copyright (C) 2000, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.color;
+
+import gnu.java.awt.color.ProfileHeader;
+import gnu.java.awt.color.TagEntry;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamException;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+/**
+ * ICC Profile - represents an ICC Color profile.
+ * The ICC profile format is a standard file format which maps the transform
+ * from a device color space to a standard Profile Color Space (PCS), which
+ * can either be CIE L*a*b or CIE XYZ.
+ * (With the exception of device link profiles which map from one device space
+ * to another)
+ *
+ * ICC profiles calibrated to specific input/output devices are used when color
+ * fidelity is of importance.
+ *
+ * An instance of ICC_Profile can be created using the getInstance() methods,
+ * either using one of the predefined color spaces enumerated in ColorSpace,
+ * or from an ICC profile file, or from an input stream.
+ *
+ * An ICC_ColorSpace object can then be created to transform color values
+ * through the profile.
+ *
+ * The ICC_Profile class implements the version 2 format specified by
+ * International Color Consortium Specification ICC.1:1998-09,
+ * and its addendum ICC.1A:1999-04, April 1999
+ * (available at www.color.org)
+ *
+ * @author Sven de Marothy
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ * @since 1.2
+ */
+public class ICC_Profile implements Serializable
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = -3938515861990936766L;
+
+ /**
+ * ICC Profile classes
+ */
+ public static final int CLASS_INPUT = 0;
+ public static final int CLASS_DISPLAY = 1;
+ public static final int CLASS_OUTPUT = 2;
+ public static final int CLASS_DEVICELINK = 3;
+ public static final int CLASS_COLORSPACECONVERSION = 4;
+ public static final int CLASS_ABSTRACT = 5;
+ public static final int CLASS_NAMEDCOLOR = 6;
+
+ /**
+ * ICC Profile class signatures
+ */
+ public static final int icSigInputClass = 0x73636e72; // 'scnr'
+ public static final int icSigDisplayClass = 0x6d6e7472; // 'mntr'
+ public static final int icSigOutputClass = 0x70727472; // 'prtr'
+ public static final int icSigLinkClass = 0x6c696e6b; // 'link'
+ public static final int icSigColorSpaceClass = 0x73706163; // 'spac'
+ public static final int icSigAbstractClass = 0x61627374; // 'abst'
+ public static final int icSigNamedColorClass = 0x6e6d636c; // 'nmcl'
+
+ /**
+ * Color space signatures
+ */
+ public static final int icSigXYZData = 0x58595A20; // 'XYZ '
+ public static final int icSigLabData = 0x4C616220; // 'Lab '
+ public static final int icSigLuvData = 0x4C757620; // 'Luv '
+ public static final int icSigYCbCrData = 0x59436272; // 'YCbr'
+ public static final int icSigYxyData = 0x59787920; // 'Yxy '
+ public static final int icSigRgbData = 0x52474220; // 'RGB '
+ public static final int icSigGrayData = 0x47524159; // 'GRAY'
+ public static final int icSigHsvData = 0x48535620; // 'HSV '
+ public static final int icSigHlsData = 0x484C5320; // 'HLS '
+ public static final int icSigCmykData = 0x434D594B; // 'CMYK'
+ public static final int icSigCmyData = 0x434D5920; // 'CMY '
+ public static final int icSigSpace2CLR = 0x32434C52; // '2CLR'
+ public static final int icSigSpace3CLR = 0x33434C52; // '3CLR'
+ public static final int icSigSpace4CLR = 0x34434C52; // '4CLR'
+ public static final int icSigSpace5CLR = 0x35434C52; // '5CLR'
+ public static final int icSigSpace6CLR = 0x36434C52; // '6CLR'
+ public static final int icSigSpace7CLR = 0x37434C52; // '7CLR'
+ public static final int icSigSpace8CLR = 0x38434C52; // '8CLR'
+ public static final int icSigSpace9CLR = 0x39434C52; // '9CLR'
+ public static final int icSigSpaceACLR = 0x41434C52; // 'ACLR'
+ public static final int icSigSpaceBCLR = 0x42434C52; // 'BCLR'
+ public static final int icSigSpaceCCLR = 0x43434C52; // 'CCLR'
+ public static final int icSigSpaceDCLR = 0x44434C52; // 'DCLR'
+ public static final int icSigSpaceECLR = 0x45434C52; // 'ECLR'
+ public static final int icSigSpaceFCLR = 0x46434C52; // 'FCLR'
+
+ /**
+ * Rendering intents
+ */
+ public static final int icPerceptual = 0;
+ public static final int icRelativeColorimetric = 1;
+ public static final int icSaturation = 2;
+ public static final int icAbsoluteColorimetric = 3;
+
+ /**
+ * Tag signatures
+ */
+ public static final int icSigAToB0Tag = 0x41324230; // 'A2B0'
+ public static final int icSigAToB1Tag = 0x41324231; // 'A2B1'
+ public static final int icSigAToB2Tag = 0x41324232; // 'A2B2'
+ public static final int icSigBlueColorantTag = 0x6258595A; // 'bXYZ'
+ public static final int icSigBlueTRCTag = 0x62545243; // 'bTRC'
+ public static final int icSigBToA0Tag = 0x42324130; // 'B2A0'
+ public static final int icSigBToA1Tag = 0x42324131; // 'B2A1'
+ public static final int icSigBToA2Tag = 0x42324132; // 'B2A2'
+ public static final int icSigCalibrationDateTimeTag = 0x63616C74; // 'calt'
+ public static final int icSigCharTargetTag = 0x74617267; // 'targ'
+ public static final int icSigCopyrightTag = 0x63707274; // 'cprt'
+ public static final int icSigCrdInfoTag = 0x63726469; // 'crdi'
+ public static final int icSigDeviceMfgDescTag = 0x646D6E64; // 'dmnd'
+ public static final int icSigDeviceModelDescTag = 0x646D6464; // 'dmdd'
+ public static final int icSigDeviceSettingsTag = 0x64657673; // 'devs'
+ public static final int icSigGamutTag = 0x67616D74; // 'gamt'
+ public static final int icSigGrayTRCTag = 0x6b545243; // 'kTRC'
+ public static final int icSigGreenColorantTag = 0x6758595A; // 'gXYZ'
+ public static final int icSigGreenTRCTag = 0x67545243; // 'gTRC'
+ public static final int icSigLuminanceTag = 0x6C756d69; // 'lumi'
+ public static final int icSigMeasurementTag = 0x6D656173; // 'meas'
+ public static final int icSigMediaBlackPointTag = 0x626B7074; // 'bkpt'
+ public static final int icSigMediaWhitePointTag = 0x77747074; // 'wtpt'
+ public static final int icSigNamedColor2Tag = 0x6E636C32; // 'ncl2'
+ public static final int icSigOutputResponseTag = 0x72657370; // 'resp'
+ public static final int icSigPreview0Tag = 0x70726530; // 'pre0'
+ public static final int icSigPreview1Tag = 0x70726531; // 'pre1'
+ public static final int icSigPreview2Tag = 0x70726532; // 'pre2'
+ public static final int icSigProfileDescriptionTag = 0x64657363; // 'desc'
+ public static final int icSigProfileSequenceDescTag = 0x70736571; // 'pseq'
+ public static final int icSigPs2CRD0Tag = 0x70736430; // 'psd0'
+ public static final int icSigPs2CRD1Tag = 0x70736431; // 'psd1'
+ public static final int icSigPs2CRD2Tag = 0x70736432; // 'psd2'
+ public static final int icSigPs2CRD3Tag = 0x70736433; // 'psd3'
+ public static final int icSigPs2CSATag = 0x70733273; // 'ps2s'
+ public static final int icSigPs2RenderingIntentTag = 0x70733269; // 'ps2i'
+ public static final int icSigRedColorantTag = 0x7258595A; // 'rXYZ'
+ public static final int icSigRedTRCTag = 0x72545243; // 'rTRC'
+ public static final int icSigScreeningDescTag = 0x73637264; // 'scrd'
+ public static final int icSigScreeningTag = 0x7363726E; // 'scrn'
+ public static final int icSigTechnologyTag = 0x74656368; // 'tech'
+ public static final int icSigUcrBgTag = 0x62666420; // 'bfd '
+ public static final int icSigViewingCondDescTag = 0x76756564; // 'vued'
+ public static final int icSigViewingConditionsTag = 0x76696577; // 'view'
+ public static final int icSigChromaticityTag = 0x6368726D; // 'chrm'
+
+ /**
+ * Non-ICC tag 'head' for use in retrieving the header with getData()
+ */
+ public static final int icSigHead = 0x68656164;
+
+ /**
+ * Header offsets
+ */
+ public static final int icHdrSize = 0;
+ public static final int icHdrCmmId = 4;
+ public static final int icHdrVersion = 8;
+ public static final int icHdrDeviceClass = 12;
+ public static final int icHdrColorSpace = 16;
+ public static final int icHdrPcs = 20;
+ public static final int icHdrDate = 24;
+ public static final int icHdrMagic = 36;
+ public static final int icHdrPlatform = 40;
+ public static final int icHdrFlags = 44;
+ public static final int icHdrManufacturer = 48;
+ public static final int icHdrModel = 52;
+ public static final int icHdrAttributes = 56;
+ public static final int icHdrRenderingIntent = 64;
+ public static final int icHdrIlluminant = 68;
+ public static final int icHdrCreator = 80;
+
+ /**
+ *
+ */
+ public static final int icTagType = 0;
+ public static final int icTagReserved = 4;
+ public static final int icCurveCount = 8;
+ public static final int icCurveData = 12;
+ public static final int icXYZNumberX = 8;
+
+ /**
+ * offset of the Tag table
+ */
+ private static final int tagTableOffset = 128;
+
+ /**
+ * @serial
+ */
+ private static final int iccProfileSerializedDataVersion = 1;
+
+ /**
+ * Constants related to generating profiles for
+ * built-in colorspace profiles
+ */
+ /**
+ * Copyright notice to stick into built-in-profile files.
+ */
+ private static final String copyrightNotice = "Generated by GNU Classpath.";
+
+ /**
+ * Resolution of the TRC to use for predefined profiles.
+ * 1024 should suffice.
+ */
+ private static final int TRC_POINTS = 1024;
+
+ /**
+ * CIE 1931 D50 white point (in Lab coordinates)
+ */
+ private static final float[] D50 = { 0.96422f, 1.00f, 0.82521f };
+
+ /**
+ * Color space profile ID
+ * Set to the predefined profile class (e.g. CS_sRGB) if a predefined
+ * color space is used, set to -1 otherwise.
+ * (or if the profile has been modified)
+ */
+ private transient int profileID;
+
+ /**
+ * The profile header data
+ */
+ private transient ProfileHeader header;
+
+ /**
+ * A hashtable containing the profile tags as TagEntry objects
+ */
+ private transient Hashtable tagTable;
+
+ /**
+ * Contructor for predefined colorspaces
+ */
+ ICC_Profile(int profileID)
+ {
+ header = null;
+ tagTable = null;
+ createProfile(profileID);
+ }
+
+ /**
+ * Constructs an ICC_Profile from a header and a table of loaded tags.
+ */
+ ICC_Profile(ProfileHeader h, Hashtable tags) throws IllegalArgumentException
+ {
+ header = h;
+ tagTable = tags;
+ profileID = -1; // Not a predefined color space
+ }
+
+ /**
+ * Constructs an ICC_Profile from a byte array of data.
+ */
+ ICC_Profile(byte[] data) throws IllegalArgumentException
+ {
+ // get header and verify it
+ header = new ProfileHeader(data);
+ header.verifyHeader(data.length);
+ tagTable = createTagTable(data);
+ profileID = -1; // Not a predefined color space
+ }
+
+ /**
+ * Free up the used memory.
+ */
+ protected void finalize()
+ {
+ }
+
+ /**
+ * Returns an ICC_Profile instance from a byte array of profile data.
+ *
+ * An instance of the specialized classes ICC_ProfileRGB or ICC_ProfileGray
+ * may be returned if appropriate.
+ *
+ * @param data - the profile data
+ * @return An ICC_Profile object
+ *
+ * @throws IllegalArgumentException if the profile data is an invalid
+ * v2 profile.
+ */
+ public static ICC_Profile getInstance(byte[] data)
+ {
+ ProfileHeader header = new ProfileHeader(data);
+
+ // verify it as a correct ICC header, including size
+ header.verifyHeader(data.length);
+
+ Hashtable tags = createTagTable(data);
+
+ if (isRGBProfile(header, tags))
+ return new ICC_ProfileRGB(data);
+ if (isGrayProfile(header, tags))
+ return new ICC_ProfileGray(data);
+
+ return new ICC_Profile(header, tags);
+ }
+
+ /**
+ * Returns an predefined ICC_Profile instance.
+ *
+ * This will construct an ICC_Profile instance from one of the predefined
+ * color spaces in the ColorSpace class. (e.g. CS_sRGB, CS_GRAY, etc)
+ *
+ * An instance of the specialized classes ICC_ProfileRGB or ICC_ProfileGray
+ * may be returned if appropriate.
+ *
+ * @return An ICC_Profile object
+ */
+ public static ICC_Profile getInstance(int cspace)
+ {
+ if (cspace == ColorSpace.CS_sRGB || cspace == ColorSpace.CS_LINEAR_RGB)
+ return new ICC_ProfileRGB(cspace);
+ if (cspace == ColorSpace.CS_GRAY)
+ return new ICC_ProfileGray(cspace);
+ return new ICC_Profile(cspace);
+ }
+
+ /**
+ * Returns an ICC_Profile instance from an ICC Profile file.
+ *
+ * An instance of the specialized classes ICC_ProfileRGB or ICC_ProfileGray
+ * may be returned if appropriate.
+ *
+ * @param filename - the file name of the profile file.
+ * @return An ICC_Profile object
+ *
+ * @throws IllegalArgumentException if the profile data is an invalid
+ * v2 profile.
+ * @throws IOException if the file could not be read.
+ */
+ public static ICC_Profile getInstance(String filename)
+ throws IOException
+ {
+ return getInstance(new FileInputStream(filename));
+ }
+
+ /**
+ * Returns an ICC_Profile instance from an InputStream.
+ *
+ * This method can be used for reading ICC profiles embedded in files
+ * which support this. (JPEG and SVG for instance).
+ *
+ * The stream is treated in the following way: The profile header
+ * (128 bytes) is read first, and the header is validated. If the profile
+ * header is valid, it will then attempt to read the rest of the profile
+ * from the stream. The stream is not closed after reading.
+ *
+ * An instance of the specialized classes ICC_ProfileRGB or ICC_ProfileGray
+ * may be returned if appropriate.
+ *
+ * @param in - the input stream to read the profile from.
+ * @return An ICC_Profile object
+ *
+ * @throws IllegalArgumentException if the profile data is an invalid
+ * v2 profile.
+ * @throws IOException if the stream could not be read.
+ */
+ public static ICC_Profile getInstance(InputStream in)
+ throws IOException
+ {
+ // read the header
+ byte[] headerData = new byte[ProfileHeader.HEADERSIZE];
+ if (in.read(headerData) != ProfileHeader.HEADERSIZE)
+ throw new IllegalArgumentException("Invalid profile header");
+
+ ProfileHeader header = new ProfileHeader(headerData);
+
+ // verify it as a correct ICC header, but do not verify the
+ // size as we are reading from a stream.
+ header.verifyHeader(-1);
+
+ // get the size
+ byte[] data = new byte[header.getSize()];
+ System.arraycopy(headerData, 0, data, 0, ProfileHeader.HEADERSIZE);
+
+ // read the rest
+ int totalBytes = header.getSize() - ProfileHeader.HEADERSIZE;
+ int bytesLeft = totalBytes;
+ while (bytesLeft > 0)
+ {
+ int read = in.read(data,
+ ProfileHeader.HEADERSIZE + (totalBytes - bytesLeft),
+ bytesLeft);
+ bytesLeft -= read;
+ }
+
+ return getInstance(data);
+ }
+
+ /**
+ * Returns the major version number
+ */
+ public int getMajorVersion()
+ {
+ return header.getMajorVersion();
+ }
+
+ /**
+ * Returns the minor version number.
+ *
+ * Only the least-significant byte contains data, in BCD form:
+ * the least-significant nibble is the BCD bug fix revision,
+ * the most-significant nibble is the BCD minor revision number.
+ *
+ * (E.g. For a v2.1.0 profile this will return <code>0x10</code>)
+ */
+ public int getMinorVersion()
+ {
+ return header.getMinorVersion();
+ }
+
+ /**
+ * Returns the device class of this profile,
+ *
+ * (E.g. CLASS_INPUT for a scanner profile,
+ * CLASS_OUTPUT for a printer)
+ */
+ public int getProfileClass()
+ {
+ return header.getProfileClass();
+ }
+
+ /**
+ * Returns the color space of this profile, in terms
+ * of the color space constants defined in ColorSpace.
+ * (For example, it may be a ColorSpace.TYPE_RGB)
+ */
+ public int getColorSpaceType()
+ {
+ return header.getColorSpace();
+ }
+
+ /**
+ * Returns the color space of this profile's Profile Connection Space (OCS)
+ *
+ * In terms of the color space constants defined in ColorSpace.
+ * This may be TYPE_XYZ or TYPE_Lab
+ */
+ public int getPCSType()
+ {
+ return header.getProfileColorSpace();
+ }
+
+ /**
+ * Writes the profile data to an ICC profile file.
+ * @param filename - The name of the file to write
+ * @throws IOException if the write failed.
+ */
+ public void write(String filename) throws IOException
+ {
+ FileOutputStream out = new FileOutputStream(filename);
+ write(out);
+ out.flush();
+ out.close();
+ }
+
+ /**
+ * Writes the profile data in ICC profile file-format to a stream.
+ * This is useful for embedding ICC profiles in file formats which
+ * support this (such as JPEG and SVG).
+ *
+ * The stream is not closed after writing.
+ * @param out - The outputstream to which the profile data should be written
+ * @throws IOException if the write failed.
+ */
+ public void write(OutputStream out) throws IOException
+ {
+ out.write(getData());
+ }
+
+ /**
+ * Returns the data corresponding to this ICC_Profile as a byte array.
+ *
+ * @return The data in a byte array,
+ * where the first element corresponds to first byte of the profile file.
+ */
+ public byte[] getData()
+ {
+ int size = getSize();
+ byte[] data = new byte[size];
+
+ // Header
+ System.arraycopy(header.getData(size), 0, data, 0, ProfileHeader.HEADERSIZE);
+ // # of tags
+ byte[] tt = getTagTable();
+ System.arraycopy(tt, 0, data, ProfileHeader.HEADERSIZE, tt.length);
+
+ Enumeration e = tagTable.elements();
+ while (e.hasMoreElements())
+ {
+ TagEntry tag = (TagEntry) e.nextElement();
+ System.arraycopy(tag.getData(), 0,
+ data, tag.getOffset(), tag.getSize());
+ }
+ return data;
+ }
+
+ /**
+ * Returns the ICC profile tag data
+ * The non ICC-tag icSigHead is also permitted to request the header data.
+ *
+ * @param tagSignature The ICC signature of the requested tag
+ * @return A byte array containing the tag data
+ */
+ public byte[] getData(int tagSignature)
+ {
+ if (tagSignature == icSigHead)
+ return header.getData(getSize());
+
+ TagEntry t = (TagEntry) tagTable.get(TagEntry.tagHashKey(tagSignature));
+ if (t == null)
+ return null;
+ return t.getData();
+ }
+
+ /**
+ * Sets the ICC profile tag data.
+ *
+ * Note that an ICC profile can only contain one tag of each type, if
+ * a tag already exists with the given signature, it is replaced.
+ *
+ * @param tagSignature - The signature of the tag to set
+ * @param data - A byte array containing the tag data
+ */
+ public void setData(int tagSignature, byte[] data)
+ {
+ profileID = -1; // Not a predefined color space if modified.
+
+ if (tagSignature == icSigHead)
+ header = new ProfileHeader(data);
+ else
+ {
+ TagEntry t = new TagEntry(tagSignature, data);
+ tagTable.put(t.hashKey(), t);
+ }
+ }
+
+ /**
+ * Get the number of components in the profile's device color space.
+ */
+ public int getNumComponents()
+ {
+ int[] lookup =
+ {
+ ColorSpace.TYPE_RGB, 3, ColorSpace.TYPE_CMY, 3,
+ ColorSpace.TYPE_CMYK, 4, ColorSpace.TYPE_GRAY, 1,
+ ColorSpace.TYPE_YCbCr, 3, ColorSpace.TYPE_XYZ, 3,
+ ColorSpace.TYPE_Lab, 3, ColorSpace.TYPE_HSV, 3,
+ ColorSpace.TYPE_2CLR, 2, ColorSpace.TYPE_Luv, 3,
+ ColorSpace.TYPE_Yxy, 3, ColorSpace.TYPE_HLS, 3,
+ ColorSpace.TYPE_3CLR, 3, ColorSpace.TYPE_4CLR, 4,
+ ColorSpace.TYPE_5CLR, 5, ColorSpace.TYPE_6CLR, 6,
+ ColorSpace.TYPE_7CLR, 7, ColorSpace.TYPE_8CLR, 8,
+ ColorSpace.TYPE_9CLR, 9, ColorSpace.TYPE_ACLR, 10,
+ ColorSpace.TYPE_BCLR, 11, ColorSpace.TYPE_CCLR, 12,
+ ColorSpace.TYPE_DCLR, 13, ColorSpace.TYPE_ECLR, 14,
+ ColorSpace.TYPE_FCLR, 15
+ };
+ for (int i = 0; i < lookup.length; i += 2)
+ if (header.getColorSpace() == lookup[i])
+ return lookup[i + 1];
+ return 3; // should never happen.
+ }
+
+ /**
+ * After deserializing we must determine if the class we want
+ * is really one of the more specialized ICC_ProfileRGB or
+ * ICC_ProfileGray classes.
+ */
+ protected Object readResolve() throws ObjectStreamException
+ {
+ if (isRGBProfile(header, tagTable))
+ return new ICC_ProfileRGB(getData());
+ if (isGrayProfile(header, tagTable))
+ return new ICC_ProfileGray(getData());
+ return this;
+ }
+
+ /**
+ * Deserializes an instance
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ String predef = (String) s.readObject();
+ byte[] data = (byte[]) s.readObject();
+
+ if (data != null)
+ {
+ header = new ProfileHeader(data);
+ tagTable = createTagTable(data);
+ profileID = -1; // Not a predefined color space
+ }
+
+ if (predef != null)
+ {
+ predef = predef.intern();
+ if (predef.equals("CS_sRGB"))
+ createProfile(ColorSpace.CS_sRGB);
+ if (predef.equals("CS_LINEAR_RGB"))
+ createProfile(ColorSpace.CS_LINEAR_RGB);
+ if (predef.equals("CS_CIEXYZ"))
+ createProfile(ColorSpace.CS_CIEXYZ);
+ if (predef.equals("CS_GRAY"))
+ createProfile(ColorSpace.CS_GRAY);
+ if (predef.equals("CS_PYCC"))
+ createProfile(ColorSpace.CS_PYCC);
+ }
+ }
+
+ /**
+ * Serializes an instance
+ * The format is a String and a byte array,
+ * The string is non-null if the instance is one of the built-in profiles.
+ * Otherwise the byte array is non-null and represents the profile data.
+ */
+ private void writeObject(ObjectOutputStream s) throws IOException
+ {
+ s.defaultWriteObject();
+ if (profileID == ColorSpace.CS_sRGB)
+ s.writeObject("CS_sRGB");
+ else if (profileID == ColorSpace.CS_LINEAR_RGB)
+ s.writeObject("CS_LINEAR_RGB");
+ else if (profileID == ColorSpace.CS_CIEXYZ)
+ s.writeObject("CS_CIEXYZ");
+ else if (profileID == ColorSpace.CS_GRAY)
+ s.writeObject("CS_GRAY");
+ else if (profileID == ColorSpace.CS_PYCC)
+ s.writeObject("CS_PYCC");
+ else
+ {
+ s.writeObject(null); // null string
+ s.writeObject(getData()); // data
+ return;
+ }
+ s.writeObject(null); // null data
+ }
+
+ /**
+ * Sorts a ICC profile byte array into TagEntry objects stored in
+ * a hash table.
+ */
+ private static Hashtable createTagTable(byte[] data)
+ throws IllegalArgumentException
+ {
+ ByteBuffer buf = ByteBuffer.wrap(data);
+ int nTags = buf.getInt(tagTableOffset);
+
+ Hashtable tagTable = new Hashtable();
+ for (int i = 0; i < nTags; i++)
+ {
+ TagEntry te = new TagEntry(buf.getInt(tagTableOffset
+ + i * TagEntry.entrySize + 4),
+ buf.getInt(tagTableOffset
+ + i * TagEntry.entrySize + 8),
+ buf.getInt(tagTableOffset
+ + i * TagEntry.entrySize + 12),
+ data);
+
+ if (tagTable.put(te.hashKey(), te) != null)
+ throw new IllegalArgumentException("Duplicate tag in profile:" + te);
+ }
+ return tagTable;
+ }
+
+ /**
+ * Returns the total size of the padded, stored data
+ * Note: Tags must be stored on 4-byte aligned offsets.
+ */
+ private int getSize()
+ {
+ int totalSize = ProfileHeader.HEADERSIZE; // size of header
+
+ int tagTableSize = 4 + tagTable.size() * TagEntry.entrySize; // size of tag table
+ if ((tagTableSize & 0x0003) != 0)
+ tagTableSize += 4 - (tagTableSize & 0x0003); // pad
+ totalSize += tagTableSize;
+
+ Enumeration e = tagTable.elements();
+ while (e.hasMoreElements())
+ { // tag data
+ int tagSize = ((TagEntry) e.nextElement()).getSize();
+ if ((tagSize & 0x0003) != 0)
+ tagSize += 4 - (tagSize & 0x0003); // pad
+ totalSize += tagSize;
+ }
+ return totalSize;
+ }
+
+ /**
+ * Generates the tag index table
+ */
+ private byte[] getTagTable()
+ {
+ int tagTableSize = 4 + tagTable.size() * TagEntry.entrySize;
+ if ((tagTableSize & 0x0003) != 0)
+ tagTableSize += 4 - (tagTableSize & 0x0003); // pad
+
+ int offset = 4;
+ int tagOffset = ProfileHeader.HEADERSIZE + tagTableSize;
+ ByteBuffer buf = ByteBuffer.allocate(tagTableSize);
+ buf.putInt(tagTable.size()); // number of tags
+
+ Enumeration e = tagTable.elements();
+ while (e.hasMoreElements())
+ {
+ TagEntry tag = (TagEntry) e.nextElement();
+ buf.putInt(offset, tag.getSignature());
+ buf.putInt(offset + 4, tagOffset);
+ buf.putInt(offset + 8, tag.getSize());
+ tag.setOffset(tagOffset);
+ int tagSize = tag.getSize();
+ if ((tagSize & 0x0003) != 0)
+ tagSize += 4 - (tagSize & 0x0003); // pad
+ tagOffset += tagSize;
+ offset += 12;
+ }
+ return buf.array();
+ }
+
+ /**
+ * Returns if the criteria for an ICC_ProfileRGB are met.
+ * This means:
+ * Color space is TYPE_RGB
+ * (r,g,b)ColorantTags included
+ * (r,g,b)TRCTags included
+ * mediaWhitePointTag included
+ */
+ private static boolean isRGBProfile(ProfileHeader header, Hashtable tags)
+ {
+ if (header.getColorSpace() != ColorSpace.TYPE_RGB)
+ return false;
+ if (tags.get(TagEntry.tagHashKey(icSigRedColorantTag)) == null)
+ return false;
+ if (tags.get(TagEntry.tagHashKey(icSigGreenColorantTag)) == null)
+ return false;
+ if (tags.get(TagEntry.tagHashKey(icSigBlueColorantTag)) == null)
+ return false;
+ if (tags.get(TagEntry.tagHashKey(icSigRedTRCTag)) == null)
+ return false;
+ if (tags.get(TagEntry.tagHashKey(icSigGreenTRCTag)) == null)
+ return false;
+ if (tags.get(TagEntry.tagHashKey(icSigBlueTRCTag)) == null)
+ return false;
+ return (tags.get(TagEntry.tagHashKey(icSigMediaWhitePointTag)) != null);
+ }
+
+ /**
+ * Returns if the criteria for an ICC_ProfileGray are met.
+ * This means:
+ * Colorspace is TYPE_GRAY
+ * grayTRCTag included
+ * mediaWhitePointTag included
+ */
+ private static boolean isGrayProfile(ProfileHeader header, Hashtable tags)
+ {
+ if (header.getColorSpace() != ColorSpace.TYPE_GRAY)
+ return false;
+ if (tags.get(TagEntry.tagHashKey(icSigGrayTRCTag)) == null)
+ return false;
+ return (tags.get(TagEntry.tagHashKey(icSigMediaWhitePointTag)) != null);
+ }
+
+ /**
+ * Returns curve data for a 'curv'-type tag
+ * If it's a gamma curve, a single entry will be returned with the
+ * gamma value (including 1.0 for linear response)
+ * Otherwise the TRC table is returned.
+ *
+ * (Package private - used by ICC_ProfileRGB and ICC_ProfileGray)
+ */
+ short[] getCurve(int signature)
+ {
+ byte[] data = getData(signature);
+ short[] curve;
+
+ // can't find tag?
+ if (data == null)
+ return null;
+
+ // not an curve type tag?
+ ByteBuffer buf = ByteBuffer.wrap(data);
+ if (buf.getInt(0) != 0x63757276) // 'curv' type
+ return null;
+ int count = buf.getInt(8);
+ if (count == 0)
+ {
+ curve = new short[1];
+ curve[0] = 0x0100; // 1.00 in u8fixed8
+ return curve;
+ }
+ if (count == 1)
+ {
+ curve = new short[1];
+ curve[0] = buf.getShort(12); // other u8fixed8 gamma
+ return curve;
+ }
+ curve = new short[count];
+ for (int i = 0; i < count; i++)
+ curve[i] = buf.getShort(12 + i * 2);
+ return curve;
+ }
+
+ /**
+ * Returns XYZ tristimulus values for an 'XYZ ' type tag
+ * @return the XYZ values, or null if the tag was not an 'XYZ ' type tag.
+ *
+ * (Package private - used by ICC_ProfileXYZ and ICC_ProfileGray)
+ */
+ float[] getXYZData(int signature)
+ {
+ byte[] data = getData(signature);
+
+ // can't find tag?
+ if (data == null)
+ return null;
+
+ // not an XYZData type tag?
+ ByteBuffer buf = ByteBuffer.wrap(data);
+ if (buf.getInt(0) != icSigXYZData) // 'XYZ ' type
+ return null;
+
+ float[] point = new float[3];
+
+ // get the X,Y,Z tristimulus values
+ point[0] = ((float) buf.getInt(8)) / 65536f;
+ point[1] = ((float) buf.getInt(12)) / 65536f;
+ point[2] = ((float) buf.getInt(16)) / 65536f;
+ return point;
+ }
+
+ /**
+ * Returns the profile ID if it's a predefined profile
+ * Or -1 for a profile loaded from an ICC profile
+ *
+ * (Package private - used by ICC_ColorSpace)
+ */
+ int isPredefined()
+ {
+ return profileID;
+ }
+
+ /**
+ * Creates a tag of XYZ-value type.
+ */
+ private byte[] makeXYZData(float[] values)
+ {
+ ByteBuffer buf = ByteBuffer.allocate(20);
+ buf.putInt(0, icSigXYZData); // 'XYZ '
+ buf.putInt(4, 0);
+ buf.putInt(8, (int) (values[0] * 65536.0));
+ buf.putInt(12, (int) (values[1] * 65536.0));
+ buf.putInt(16, (int) (values[2] * 65536.0));
+ return buf.array();
+ }
+
+ /**
+ * Creates a tag of text type
+ */
+ private byte[] makeTextTag(String text)
+ {
+ int length = text.length();
+ ByteBuffer buf = ByteBuffer.allocate(8 + length + 1);
+ byte[] data;
+ try
+ {
+ data = text.getBytes("US-ASCII");
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ data = new byte[length]; // shouldn't happen
+ }
+
+ buf.putInt(0, (int) 0x74657874); // 'text'
+ buf.putInt(4, 0);
+ for (int i = 0; i < length; i++)
+ buf.put(8 + i, data[i]);
+ buf.put(8 + length, (byte) 0); // null-terminate
+ return buf.array();
+ }
+
+ /**
+ * Creates a tag of textDescriptionType
+ */
+ private byte[] makeDescTag(String text)
+ {
+ int length = text.length();
+ ByteBuffer buf = ByteBuffer.allocate(90 + length + 1);
+ buf.putInt(0, (int) 0x64657363); // 'desc'
+ buf.putInt(4, 0); // reserved
+ buf.putInt(8, length + 1); // ASCII length, including null termination
+ byte[] data;
+
+ try
+ {
+ data = text.getBytes("US-ASCII");
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ data = new byte[length]; // shouldn't happen
+ }
+
+ for (int i = 0; i < length; i++)
+ buf.put(12 + i, data[i]);
+ buf.put(12 + length, (byte) 0); // null-terminate
+
+ for (int i = 0; i < 39; i++)
+ buf.putShort(13 + length + (i * 2), (short) 0); // 78 bytes we can ignore
+
+ return buf.array();
+ }
+
+ /**
+ * Creates a tag of TRC type (linear curve)
+ */
+ private byte[] makeTRC()
+ {
+ ByteBuffer buf = ByteBuffer.allocate(12);
+ buf.putInt(0, 0x63757276); // 'curv' type
+ buf.putInt(4, 0); // reserved
+ buf.putInt(8, 0);
+ return buf.array();
+ }
+
+ /**
+ * Creates a tag of TRC type (single gamma value)
+ */
+ private byte[] makeTRC(float gamma)
+ {
+ short gammaValue = (short) (gamma * 256f);
+ ByteBuffer buf = ByteBuffer.allocate(14);
+ buf.putInt(0, 0x63757276); // 'curv' type
+ buf.putInt(4, 0); // reserved
+ buf.putInt(8, 1);
+ buf.putShort(12, gammaValue); // 1.00 in u8fixed8
+ return buf.array();
+ }
+
+ /**
+ * Creates a tag of TRC type (TRC curve points)
+ */
+ private byte[] makeTRC(float[] trc)
+ {
+ ByteBuffer buf = ByteBuffer.allocate(12 + 2 * trc.length);
+ buf.putInt(0, 0x63757276); // 'curv' type
+ buf.putInt(4, 0); // reserved
+ buf.putInt(8, trc.length); // number of points
+
+ // put the curve values
+ for (int i = 0; i < trc.length; i++)
+ buf.putShort(12 + i * 2, (short) (trc[i] * 65535f));
+
+ return buf.array();
+ }
+
+ /**
+ * Creates an identity color lookup table.
+ */
+ private byte[] makeIdentityClut()
+ {
+ final int nIn = 3;
+ final int nOut = 3;
+ final int nInEntries = 256;
+ final int nOutEntries = 256;
+ final int gridpoints = 16;
+
+ // gridpoints**nIn
+ final int clutSize = 2 * nOut * gridpoints * gridpoints * gridpoints;
+ final int totalSize = clutSize + 2 * nInEntries * nIn
+ + 2 * nOutEntries * nOut + 52;
+
+ ByteBuffer buf = ByteBuffer.allocate(totalSize);
+ buf.putInt(0, 0x6D667432); // 'mft2'
+ buf.putInt(4, 0); // reserved
+ buf.put(8, (byte) nIn); // number input channels
+ buf.put(9, (byte) nOut); // number output channels
+ buf.put(10, (byte) gridpoints); // number gridpoints
+ buf.put(11, (byte) 0); // padding
+
+ // identity matrix
+ buf.putInt(12, 65536); // = 1 in s15.16 fixed point
+ buf.putInt(16, 0);
+ buf.putInt(20, 0);
+ buf.putInt(24, 0);
+ buf.putInt(28, 65536);
+ buf.putInt(32, 0);
+ buf.putInt(36, 0);
+ buf.putInt(40, 0);
+ buf.putInt(44, 65536);
+
+ buf.putShort(48, (short) nInEntries); // input table entries
+ buf.putShort(50, (short) nOutEntries); // output table entries
+
+ // write the linear input channels, unsigned 16.16 fixed point,
+ // from 0.0 to FF.FF
+ for (int channel = 0; channel < 3; channel++)
+ for (int i = 0; i < nInEntries; i++)
+ {
+ short n = (short) ((i << 8) | i); // assumes 256 entries
+ buf.putShort(52 + (channel * nInEntries + i) * 2, n);
+ }
+ int clutOffset = 52 + nInEntries * nIn * 2;
+
+ for (int x = 0; x < gridpoints; x++)
+ for (int y = 0; y < gridpoints; y++)
+ for (int z = 0; z < gridpoints; z++)
+ {
+ int offset = clutOffset + z * 2 * nOut + y * gridpoints * 2 * nOut
+ + x * gridpoints * gridpoints * 2 * nOut;
+ double xf = ((double) x) / ((double) gridpoints - 1.0);
+ double yf = ((double) y) / ((double) gridpoints - 1.0);
+ double zf = ((double) z) / ((double) gridpoints - 1.0);
+ buf.putShort(offset, (short) (xf * 65535.0));
+ buf.putShort(offset + 2, (short) (yf * 65535.0));
+ buf.putShort(offset + 4, (short) (zf * 65535.0));
+ }
+
+ for (int channel = 0; channel < 3; channel++)
+ for (int i = 0; i < nOutEntries; i++)
+ {
+ short n = (short) ((i << 8) | i); // assumes 256 entries
+ buf.putShort(clutOffset + clutSize + (channel * nOutEntries + i) * 2,
+ n);
+ }
+
+ return buf.array();
+ }
+
+ /**
+ * Creates profile data corresponding to the built-in colorspaces.
+ */
+ private void createProfile(int colorSpace) throws IllegalArgumentException
+ {
+ this.profileID = colorSpace;
+ header = new ProfileHeader();
+ tagTable = new Hashtable();
+
+ switch (colorSpace)
+ {
+ case ColorSpace.CS_sRGB:
+ createRGBProfile();
+ return;
+ case ColorSpace.CS_LINEAR_RGB:
+ createLinearRGBProfile();
+ return;
+ case ColorSpace.CS_CIEXYZ:
+ createCIEProfile();
+ return;
+ case ColorSpace.CS_GRAY:
+ createGrayProfile();
+ return;
+ case ColorSpace.CS_PYCC:
+ createPyccProfile();
+ return;
+ default:
+ throw new IllegalArgumentException("Not a predefined color space!");
+ }
+ }
+
+ /**
+ * Creates an ICC_Profile representing the sRGB color space
+ */
+ private void createRGBProfile()
+ {
+ header.setColorSpace( ColorSpace.TYPE_RGB );
+ header.setProfileColorSpace( ColorSpace.TYPE_XYZ );
+ ICC_ColorSpace cs = new ICC_ColorSpace(this);
+
+ float[] r = { 1f, 0f, 0f };
+ float[] g = { 0f, 1f, 0f };
+ float[] b = { 0f, 0f, 1f };
+ float[] black = { 0f, 0f, 0f };
+
+ // CIE 1931 D50 white point (in Lab coordinates)
+ float[] white = D50;
+
+ // Get tristimulus values (matrix elements)
+ r = cs.toCIEXYZ(r);
+ g = cs.toCIEXYZ(g);
+ b = cs.toCIEXYZ(b);
+
+ // Generate the sRGB TRC curve, this is the linear->nonlinear
+ // RGB transform.
+ cs = new ICC_ColorSpace(getInstance(ICC_ColorSpace.CS_LINEAR_RGB));
+ float[] points = new float[TRC_POINTS];
+ float[] in = new float[3];
+ for (int i = 0; i < TRC_POINTS; i++)
+ {
+ in[0] = in[1] = in[2] = ((float) i) / ((float) TRC_POINTS - 1);
+ in = cs.fromRGB(in);
+ // Note this value is the same for all components.
+ points[i] = in[0];
+ }
+
+ setData(icSigRedColorantTag, makeXYZData(r));
+ setData(icSigGreenColorantTag, makeXYZData(g));
+ setData(icSigBlueColorantTag, makeXYZData(b));
+ setData(icSigMediaWhitePointTag, makeXYZData(white));
+ setData(icSigMediaBlackPointTag, makeXYZData(black));
+ setData(icSigRedTRCTag, makeTRC(points));
+ setData(icSigGreenTRCTag, makeTRC(points));
+ setData(icSigBlueTRCTag, makeTRC(points));
+ setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
+ setData(icSigProfileDescriptionTag, makeDescTag("Generic sRGB"));
+ this.profileID = ColorSpace.CS_sRGB;
+ }
+
+ /**
+ * Creates an linear sRGB profile
+ */
+ private void createLinearRGBProfile()
+ {
+ header.setColorSpace(ColorSpace.TYPE_RGB);
+ header.setProfileColorSpace(ColorSpace.TYPE_XYZ);
+ ICC_ColorSpace cs = new ICC_ColorSpace(this);
+
+ float[] r = { 1f, 0f, 0f };
+ float[] g = { 0f, 1f, 0f };
+ float[] b = { 0f, 0f, 1f };
+ float[] black = { 0f, 0f, 0f };
+
+ float[] white = D50;
+
+ // Get tristimulus values (matrix elements)
+ r = cs.toCIEXYZ(r);
+ g = cs.toCIEXYZ(g);
+ b = cs.toCIEXYZ(b);
+
+ setData(icSigRedColorantTag, makeXYZData(r));
+ setData(icSigGreenColorantTag, makeXYZData(g));
+ setData(icSigBlueColorantTag, makeXYZData(b));
+
+ setData(icSigMediaWhitePointTag, makeXYZData(white));
+ setData(icSigMediaBlackPointTag, makeXYZData(black));
+
+ setData(icSigRedTRCTag, makeTRC());
+ setData(icSigGreenTRCTag, makeTRC());
+ setData(icSigBlueTRCTag, makeTRC());
+ setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
+ setData(icSigProfileDescriptionTag, makeDescTag("Linear RGB"));
+ this.profileID = ColorSpace.CS_LINEAR_RGB;
+ }
+
+ /**
+ * Creates an CIE XYZ identity profile
+ */
+ private void createCIEProfile()
+ {
+ header.setColorSpace( ColorSpace.TYPE_XYZ );
+ header.setProfileColorSpace( ColorSpace.TYPE_XYZ );
+ header.setProfileClass( CLASS_COLORSPACECONVERSION );
+ ICC_ColorSpace cs = new ICC_ColorSpace(this);
+
+ float[] white = D50;
+
+ setData(icSigMediaWhitePointTag, makeXYZData(white));
+ setData(icSigAToB0Tag, makeIdentityClut());
+ setData(icSigBToA0Tag, makeIdentityClut());
+ setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
+ setData(icSigProfileDescriptionTag, makeDescTag("CIE XYZ identity profile"));
+ this.profileID = ColorSpace.CS_CIEXYZ;
+ }
+
+ /**
+ * Creates a linear gray ICC_Profile
+ */
+ private void createGrayProfile()
+ {
+ header.setColorSpace(ColorSpace.TYPE_GRAY);
+ header.setProfileColorSpace(ColorSpace.TYPE_XYZ);
+
+ // CIE 1931 D50 white point (in Lab coordinates)
+ float[] white = D50;
+
+ setData(icSigMediaWhitePointTag, makeXYZData(white));
+ setData(icSigGrayTRCTag, makeTRC(1.0f));
+ setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
+ setData(icSigProfileDescriptionTag, makeDescTag("Linear grayscale"));
+ this.profileID = ColorSpace.CS_GRAY;
+ }
+
+ /**
+ * XXX Implement me
+ */
+ private void createPyccProfile()
+ {
+ header.setColorSpace(ColorSpace.TYPE_3CLR);
+ header.setProfileColorSpace(ColorSpace.TYPE_XYZ);
+
+ // Create CLUTs here. :-)
+
+ setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
+ setData(icSigProfileDescriptionTag, makeDescTag("Photo YCC"));
+ this.profileID = ColorSpace.CS_PYCC;
+ }
+} // class ICC_Profile
diff --git a/libjava/classpath/java/awt/color/ICC_ProfileGray.java b/libjava/classpath/java/awt/color/ICC_ProfileGray.java
new file mode 100644
index 000000000..f85533cec
--- /dev/null
+++ b/libjava/classpath/java/awt/color/ICC_ProfileGray.java
@@ -0,0 +1,133 @@
+/* ICC_ProfileGray.java -- the ICC profile for a Gray colorspace
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.color;
+
+/**
+ * ICC_ProfileGray - a special case of ICC_Profiles.
+ *
+ * The ICC_Profile.getInstance() method will return an instance of the
+ * ICC_ProfileGray subclass when all the following conditions are met:
+ * The device color space of the profile is TYPE_GRAY.
+ * The profile contains a gray TRCTag.
+ * The profile contains a mediaWhitePointTag.
+ *
+ * As per the ICC specification, the color space conversion can then
+ * be done through the following method:
+ * linearGray = grayTRC[deviceGray]
+ *
+ * Note that if the profile contains a CLUT for the color space conversion,
+ * it should be used instead, and the TRC information ignored.
+ *
+ * @author Sven de Marothy
+ * @since 1.2
+ */
+public class ICC_ProfileGray extends ICC_Profile
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = -1124721290732002649L;
+ private transient float[] whitePoint;
+
+ /**
+ * Package-private constructor used by ICC_ColorSpace for creating an
+ * ICC_ProfileGray from a predefined ColorSpace (CS_GRAY)
+ */
+ ICC_ProfileGray(int cspace)
+ {
+ super(cspace);
+ whitePoint = getXYZData(icSigMediaWhitePointTag);
+ }
+
+ /**
+ * Package-private constructor used by ICC_ColorSpace for creating an
+ * ICC_ProfileGray from profile data.
+ */
+ ICC_ProfileGray(byte[] data)
+ {
+ super(data);
+ whitePoint = getXYZData(icSigMediaWhitePointTag);
+ }
+
+
+ /**
+ * Returns the media white point of the profile.
+ */
+ public float[] getMediaWhitePoint()
+ {
+ float[] wp = new float[3];
+ wp[0] = whitePoint[0];
+ wp[1] = whitePoint[1];
+ wp[2] = whitePoint[2];
+ return wp;
+ }
+
+ /**
+ * Returns the TRC gamma value.
+ * @throws ProfileDataException if the TRC is described by a lookup
+ * table and not a gamma value.
+ */
+ public float getGamma()
+ {
+ short[] data = getCurve(icSigGrayTRCTag);
+ if (data == null)
+ throw new IllegalArgumentException("Couldn't read Gray TRC data.");
+ if (data.length != 1)
+ throw new ProfileDataException("TRC is a table, not a gamma value.");
+
+ // convert the unsigned 7.8 fixed-point gamma to a float.
+ double gamma = (double) (data[0] & (0xFFFF)) / 256.0;
+ return (float) gamma;
+ }
+
+ /**
+ * Returns the TRC lookup table.
+ * @throws ProfileDataException if the TRC is described by a gamma value
+ * and not a lookup table.
+ */
+ public short[] getTRC()
+ {
+ short[] data = getCurve(icSigGrayTRCTag);
+ if (data == null)
+ throw new IllegalArgumentException("Couldn't read Gray TRC data.");
+ if (data.length <= 1)
+ throw new ProfileDataException("Gamma value, not a TRC table.");
+ return data;
+ }
+} // class ICC_ProfileGray
diff --git a/libjava/classpath/java/awt/color/ICC_ProfileRGB.java b/libjava/classpath/java/awt/color/ICC_ProfileRGB.java
new file mode 100644
index 000000000..cfdbf6e54
--- /dev/null
+++ b/libjava/classpath/java/awt/color/ICC_ProfileRGB.java
@@ -0,0 +1,227 @@
+/* ICC_ProfileRGB.java -- the ICC profile for a RGB colorspace
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.color;
+
+/**
+ * ICC_ProfileRGB - a special case of ICC_Profiles.
+ *
+ * The ICC_Profile.getInstance() method will return an instance of the
+ * ICC_ProfileRGB subclass when all the following conditions are met:
+ * The device color space of the profile is TYPE_RGB.
+ * The profile contains red, green and blue ColorantTags.
+ * The profile contains red, green and blue TRCTags.
+ * The profile contains a mediaWhitePointTag included.
+ *
+ * As per the ICC specification, the color space conversion can then
+ * be done through the following method:
+ * linearR = redTRC[deviceR]
+ * linearG = greenTRC[deviceG]
+ * linearB = blueTRC[deviceB]
+ * TRC curves are either a single gamma value, or a 1-dimensional lookup table.
+ *
+ * Followed by the matrix transform:
+ * PCS = M*linear
+ *
+ * Where PCS is the vector of profile color space (must be XYZ) coordinates,
+ * linear is the vector of linear RGB coordinates, and the matrix M is
+ * constructed from the ColorantTags, where the columns are red, green and
+ * blue respectively, and the rows are X, Y and Z.
+ *
+ * Note that if the profile contains a CLUT for the color space conversion,
+ * it should be used instead, and the TRC information ignored.
+ *
+ * @author Sven de Marothy
+ * @since 1.2
+ */
+public class ICC_ProfileRGB extends ICC_Profile
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 8505067385152579334L;
+
+ public static final int REDCOMPONENT = 0;
+
+ public static final int GREENCOMPONENT = 1;
+
+ public static final int BLUECOMPONENT = 2;
+
+ private transient float[][] matrix;
+
+ private transient float[] gamma;
+
+ private transient float[] whitePoint;
+
+
+ /**
+ * Package-private constructor used by ICC_ColorSpace for creating an
+ * ICC_ProfileRGB from a predefined ColorSpace (CS_LINEAR_RGB and CS_sRGB)
+ */
+ ICC_ProfileRGB(int cspace)
+ {
+ super(cspace);
+ matrix = createMatrix();
+ whitePoint = getXYZData(icSigMediaWhitePointTag);
+ }
+
+ /**
+ * Package-private constructor used by ICC_ColorSpace for creating an
+ * ICC_ProfileRGB from profile data.
+ */
+ ICC_ProfileRGB(byte[] data)
+ {
+ super(data);
+ matrix = createMatrix();
+ whitePoint = getXYZData(icSigMediaWhitePointTag);
+ }
+
+ /**
+ * Returns the media white point of the profile.
+ */
+ public float[] getMediaWhitePoint()
+ {
+ float[] wp = new float[3];
+ wp[0] = whitePoint[0];
+ wp[1] = whitePoint[1];
+ wp[2] = whitePoint[2];
+ return wp;
+ }
+
+ /**
+ * Returns the colorant matrix of the conversion.
+ */
+ public float[][] getMatrix()
+ {
+ float[][] mat = new float[3][3];
+ for (int i = 0; i < 3; i++)
+ for (int j = 0; j < 3; j++)
+ mat[i][j] = matrix[i][j];
+ return mat;
+ }
+
+ /**
+ * Returns the gamma value of a component
+ * @throws ProfileDataException if the TRC is described by a lookup
+ * table and not a gamma value.
+ */
+ public float getGamma(int component)
+ {
+ short[] data;
+ switch (component)
+ {
+ case REDCOMPONENT:
+ data = getCurve(icSigRedTRCTag);
+ break;
+ case GREENCOMPONENT:
+ data = getCurve(icSigGreenTRCTag);
+ break;
+ case BLUECOMPONENT:
+ data = getCurve(icSigBlueTRCTag);
+ break;
+ default:
+ throw new IllegalArgumentException("Not a valid component");
+ }
+ if (data == null)
+ throw new IllegalArgumentException("Error reading TRC");
+
+ if (data.length != 1)
+ throw new ProfileDataException("Not a single-gamma TRC");
+
+ // convert the unsigned 7.8 fixed-point gamma to a float.
+ float gamma = (float) (((int) data[0] & 0xFF00) >> 8);
+ double fraction = ((int) data[0] & 0x00FF) / 256.0;
+ gamma += (float) fraction;
+ return gamma;
+ }
+
+ /**
+ * Returns the TRC lookup table for a component
+ * @throws ProfileDataException if the TRC is described by a gamma
+ * value and not a lookup table.
+ */
+ public short[] getTRC(int component)
+ {
+ short[] data;
+ switch (component)
+ {
+ case REDCOMPONENT:
+ data = getCurve(icSigRedTRCTag);
+ break;
+ case GREENCOMPONENT:
+ data = getCurve(icSigGreenTRCTag);
+ break;
+ case BLUECOMPONENT:
+ data = getCurve(icSigBlueTRCTag);
+ break;
+ default:
+ throw new IllegalArgumentException("Not a valid component");
+ }
+ if (data == null)
+ throw new IllegalArgumentException("Error reading TRC");
+
+ if (data.length <= 1)
+ throw new ProfileDataException("Gamma value, not a TRC table.");
+
+ return data;
+ }
+
+ /**
+ * Creates the colorspace conversion matrix from the RGB tristimulus
+ * values.
+ */
+ private float[][] createMatrix() throws IllegalArgumentException
+ {
+ float[][] mat = new float[3][3];
+ float[] r;
+ float[] g;
+ float[] b;
+ r = getXYZData(icSigRedColorantTag);
+ g = getXYZData(icSigGreenColorantTag);
+ b = getXYZData(icSigBlueColorantTag);
+ if (r == null || g == null || b == null)
+ throw new IllegalArgumentException("Error reading colorant tags!");
+ for (int i = 0; i < 3; i++)
+ {
+ mat[i][0] = r[i];
+ mat[i][1] = g[i];
+ mat[i][2] = b[i];
+ }
+ return mat;
+ }
+} // class ICC_ProfileRGB
diff --git a/libjava/classpath/java/awt/color/ProfileDataException.java b/libjava/classpath/java/awt/color/ProfileDataException.java
new file mode 100644
index 000000000..1af23b183
--- /dev/null
+++ b/libjava/classpath/java/awt/color/ProfileDataException.java
@@ -0,0 +1,64 @@
+/* ProfileDataException.java -- error in processing an ICC_Profile
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.color;
+
+/**
+ * Thrown when there is an error accessing or processing an
+ * <code>ICC_Profile</code>.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @status updated to 1.4
+ */
+public class ProfileDataException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 7286140888240322498L;
+
+ /**
+ * Create a new instance with a specified detailed error message.
+ *
+ * @param message the message
+ */
+ public ProfileDataException(String message)
+ {
+ super(message);
+ }
+} // class ProfileDataException
diff --git a/libjava/classpath/java/awt/color/package.html b/libjava/classpath/java/awt/color/package.html
new file mode 100644
index 000000000..9a08577c1
--- /dev/null
+++ b/libjava/classpath/java/awt/color/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt.color package.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - java.awt.color</title></head>
+
+<body>
+<p>Classes to represent color spaces and profiles.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/datatransfer/Clipboard.java b/libjava/classpath/java/awt/datatransfer/Clipboard.java
new file mode 100644
index 000000000..d0a1d3a3f
--- /dev/null
+++ b/libjava/classpath/java/awt/datatransfer/Clipboard.java
@@ -0,0 +1,213 @@
+/* Clipboard.java -- Class for transferring data via cut and paste.
+ Copyright (C) 1999, 2001, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.datatransfer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+/**
+ * This class allows data to be transferred using a cut and paste type
+ * mechanism.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Mark J. Wielaard (mark@klomp.org)
+ */
+public class Clipboard
+{
+ /**
+ * The data currently on this clipboard. For use by
+ * subclasses. Also returned by the public method getContents().
+ */
+ protected Transferable contents;
+
+ /**
+ * The owner of this clipboard.
+ */
+ protected ClipboardOwner owner;
+
+ // The clipboard name
+ private final String name;
+
+ // The flavor listeners (most likely small).
+ private final ArrayList listeners = new ArrayList(3);
+
+ /**
+ * Initializes a new instance of <code>Clipboard</code> with the
+ * specified name.
+ *
+ * @param name The clipboard name.
+ */
+ public Clipboard(String name)
+ {
+ this.name = name;
+ }
+
+ /**
+ * Returns the name of the clipboard.
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Returns the contents of the clipboard.
+ *
+ * @param requestor The object requesting the contents. This
+ * implementation ignores this parameter.
+ *
+ * @exception IllegalStateException If the clipboard is currently unavailable
+ */
+ public synchronized Transferable getContents(Object requestor)
+ {
+ return contents;
+ }
+
+ /**
+ * Sets the content and owner of this clipboard. If the given owner
+ * is different from the current owner then <code>lostOwnership()</code>
+ * is called on the current owner with the old contents of the given
+ * clipboard.
+ *
+ * @param contents The new clipboard contents.
+ * @param owner The new clipboard owner
+ *
+ * @exception IllegalStateException If the clipboard is currently unavailable
+ */
+ public synchronized void setContents(Transferable contents,
+ ClipboardOwner owner)
+ {
+ Transferable oldContents = getContents(null);
+ this.contents = contents;
+ if (this.owner != owner)
+ {
+ ClipboardOwner oldOwner = this.owner;
+ this.owner = owner;
+ if (oldOwner != null)
+ oldOwner.lostOwnership(this, oldContents);
+ }
+
+ FlavorListener[] fs = getFlavorListeners();
+ if (fs.length > 0)
+ {
+ // We are a bit optimistic here. We assume DataFlavors will be
+ // given in the same order. If the number of flavors is
+ // different or the order of the DataFlavors in the list then
+ // fire a change event.
+ boolean newFlavors = ((contents != null && oldContents == null)
+ || (contents == null && oldContents != null));
+ if (!newFlavors && contents != null && oldContents != null)
+ {
+ DataFlavor[] df1 = contents.getTransferDataFlavors();
+ DataFlavor[] df2 = oldContents.getTransferDataFlavors();
+ newFlavors = df1.length != df2.length;
+
+ for (int i = 0; !newFlavors && i < df1.length; i++)
+ newFlavors = !df1[i].equals(df2[i]);
+ }
+
+ if (newFlavors)
+ {
+ FlavorEvent e = new FlavorEvent(this);
+ for (int i = 0; i < fs.length; i++)
+ fs[i].flavorsChanged(e);
+ }
+ }
+ }
+
+ public DataFlavor[] getAvailableDataFlavors()
+ {
+ Transferable c = getContents(null);
+ if (c == null)
+ return new DataFlavor[0];
+ else
+ return c.getTransferDataFlavors();
+ }
+
+ public boolean isDataFlavorAvailable(DataFlavor flavor)
+ {
+ DataFlavor[] fs = getAvailableDataFlavors();
+ for (int i = 0; i < fs.length; i++)
+ if (flavor.equals(fs[i]))
+ return true;
+
+ return false;
+ }
+
+ public Object getData(DataFlavor flavor)
+ throws UnsupportedFlavorException, IOException
+ {
+ Transferable c = getContents(null);
+ if (c == null)
+ throw new UnsupportedFlavorException(flavor);
+ else
+ return c.getTransferData(flavor);
+ }
+
+ public void addFlavorListener(FlavorListener listener)
+ {
+ if (listener == null)
+ return;
+
+ synchronized(listeners)
+ {
+ listeners.add(listener);
+ }
+ }
+
+ public void removeFlavorListener(FlavorListener listener)
+ {
+ if (listener == null)
+ return;
+
+ synchronized(listeners)
+ {
+ listeners.remove(listener);
+ }
+ }
+
+ public FlavorListener[] getFlavorListeners()
+ {
+ synchronized(listeners)
+ {
+ return (FlavorListener[])
+ listeners.toArray(new FlavorListener[listeners.size()]);
+ }
+ }
+}
diff --git a/libjava/classpath/java/awt/datatransfer/ClipboardOwner.java b/libjava/classpath/java/awt/datatransfer/ClipboardOwner.java
new file mode 100644
index 000000000..b98059a0e
--- /dev/null
+++ b/libjava/classpath/java/awt/datatransfer/ClipboardOwner.java
@@ -0,0 +1,56 @@
+/* ClipboardOwner.java -- Interface for clipboard providers
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.datatransfer;
+
+/**
+ * This interface is for classes that will own a clipboard object.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface ClipboardOwner
+{
+ /**
+ * This method is called to notify this object that it no longer
+ * has ownership of the specified <code>Clipboard</code>.
+ *
+ * @param clipboard The clipboard for which ownership was lost.
+ * @param contents The contents of the clipboard which are no longer owned.
+ */
+ void lostOwnership (Clipboard clipboard, Transferable contents);
+}
diff --git a/libjava/classpath/java/awt/datatransfer/DataFlavor.java b/libjava/classpath/java/awt/datatransfer/DataFlavor.java
new file mode 100644
index 000000000..e54770434
--- /dev/null
+++ b/libjava/classpath/java/awt/datatransfer/DataFlavor.java
@@ -0,0 +1,1026 @@
+/* DataFlavor.java -- A type of data to transfer via the clipboard.
+ Copyright (C) 1999, 2001, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.datatransfer;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.OptionalDataException;
+import java.io.Reader;
+import java.io.Serializable;
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.rmi.Remote;
+
+/**
+ * This class represents a particular data format used for transferring
+ * data via the clipboard.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class DataFlavor implements java.io.Externalizable, Cloneable
+{
+ static final long serialVersionUID = 8367026044764648243L;
+
+ // FIXME: Serialization: Need to write methods for.
+
+ /**
+ * This is the data flavor used for tranferring plain text. The MIME
+ * type is "text/plain; charset=unicode". The representation class
+ * is <code>java.io.InputStream</code>.
+ *
+ * @deprecated The charset unicode is platform specific and InputStream
+ * deals with bytes not chars. Use <code>getRederForText()</code>.
+ */
+ public static final DataFlavor plainTextFlavor =
+ new DataFlavor("text/plain; charset=unicode; class=java.io.InputStream",
+ "plain unicode text");
+
+ /**
+ * This is the data flavor used for transferring Java strings. The
+ * MIME type is "application/x-java-serialized-object" and the
+ * representation class is <code>java.lang.String</code>.
+ */
+ public static final DataFlavor stringFlavor =
+ new DataFlavor(java.lang.String.class, "Java Unicode String");
+
+ /**
+ * This is a data flavor used for transferring lists of files. The
+ * representation type is a <code>java.util.List</code>, with each
+ * element of the list being a <code>java.io.File</code>.
+ */
+ public static final DataFlavor javaFileListFlavor =
+ new DataFlavor("application/x-java-file-list; class=java.util.List",
+ "Java File List");
+
+ /**
+ * This is an image flavor used for transferring images. The
+ * representation type is a <code>java.awt.Image</code>.
+ */
+ public static final DataFlavor imageFlavor =
+ new DataFlavor(java.awt.Image.class, "Java Image");
+
+ /**
+ * This is the MIME type used for transferring a serialized object.
+ * The representation class is the type of object be deserialized.
+ */
+ public static final String javaSerializedObjectMimeType =
+ "application/x-java-serialized-object";
+
+ /**
+ * This is the MIME type used to transfer a Java object reference within
+ * the same JVM. The representation class is the class of the object
+ * being transferred.
+ */
+ public static final String javaJVMLocalObjectMimeType =
+ "application/x-java-jvm-local-objectref";
+
+ /**
+ * This is the MIME type used to transfer a link to a remote object.
+ * The representation class is the type of object being linked to.
+ */
+ public static final String javaRemoteObjectMimeType =
+ "application/x-java-remote-object";
+
+ /*
+ * Instance Variables
+ */
+
+ // The MIME type for this flavor
+ private MimeType mimeType;
+
+ // The representation class for this flavor
+ private Class<?> representationClass;
+
+ // The human readable name of this flavor
+ private String humanPresentableName;
+
+ /*
+ * Static Methods
+ */
+
+ /**
+ * This method attempts to load the named class. The following class
+ * loaders are searched in order: the bootstrap class loader, the
+ * system class loader, the context class loader (if it exists), and
+ * the specified fallback class loader.
+ *
+ * @param className The name of the class to load.
+ * @param classLoader The class loader to use if all others fail, which
+ * may be <code>null</code>.
+ *
+ * @exception ClassNotFoundException If the class cannot be loaded.
+ */
+ protected static final Class<?> tryToLoadClass(String className,
+ ClassLoader classLoader)
+ throws ClassNotFoundException
+ {
+ // Bootstrap
+ try
+ {
+ return Class.forName(className);
+ }
+ catch(ClassNotFoundException cnfe)
+ {
+ // Ignored.
+ }
+
+ // System
+ try
+ {
+ ClassLoader loader = ClassLoader.getSystemClassLoader();
+ return Class.forName(className, true, loader);
+ }
+ catch(ClassNotFoundException cnfe)
+ {
+ // Ignored.
+ }
+
+ // Context
+ try
+ {
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ return Class.forName(className, true, loader);
+ }
+ catch(ClassNotFoundException cnfe)
+ {
+ // Ignored.
+ }
+
+ if (classLoader != null)
+ return Class.forName(className, true, classLoader);
+
+ throw new ClassNotFoundException(className);
+ }
+
+ /**
+ * XXX - Currently returns <code>plainTextFlavor</code>.
+ */
+ public static final DataFlavor getTextPlainUnicodeFlavor()
+ {
+ return plainTextFlavor;
+ }
+
+ /**
+ * Selects the best supported text flavor on this implementation.
+ * Returns <code>null</code> when none of the given flavors is liked.
+ *
+ * The <code>DataFlavor</code> returned the first data flavor in the
+ * array that has either a representation class which is (a subclass of)
+ * <code>Reader</code> or <code>String</code>, or has a representation
+ * class which is (a subclass of) <code>InputStream</code> and has a
+ * primary MIME type of "text" and has an supported encoding.
+ */
+ public static final DataFlavor
+ selectBestTextFlavor(DataFlavor[] availableFlavors)
+ {
+ for(int i = 0; i < availableFlavors.length; i++)
+ {
+ DataFlavor df = availableFlavors[i];
+ Class c = df.representationClass;
+
+ // A Reader or String is good.
+ if ((Reader.class.isAssignableFrom(c))
+ || (String.class.isAssignableFrom(c)))
+ return df;
+
+ // A InputStream is good if the mime primary type is "text"
+ if ((InputStream.class.isAssignableFrom(c))
+ && ("text".equals(df.getPrimaryType())))
+ {
+ String encoding = availableFlavors[i].getParameter("charset");
+ if (encoding == null)
+ encoding = "us-ascii";
+ Reader r = null;
+ try
+ {
+ // Try to construct a dummy reader with the found encoding
+ r = new InputStreamReader
+ (new ByteArrayInputStream(new byte[0]), encoding);
+ }
+ catch(UnsupportedEncodingException uee) { /* ignore */ }
+
+ if (r != null)
+ return df;
+ }
+ }
+
+ // Nothing found
+ return null;
+ }
+
+
+ /*
+ * Constructors
+ */
+
+ /**
+ * Empty public constructor needed for externalization.
+ * Should not be used for normal instantiation.
+ */
+ public DataFlavor()
+ {
+ // Used for deserialization only, nothing to do here.
+ }
+
+ /**
+ * Initializes a new instance of <code>DataFlavor</code>. The class
+ * and human readable name are specified, the MIME type will be
+ * "application/x-java-serialized-object". If the human readable name
+ * is not specified (<code>null</code>) then the human readable name
+ * will be the same as the MIME type.
+ *
+ * @param representationClass The representation class for this object.
+ * @param humanPresentableName The display name of the object.
+ */
+ public DataFlavor(Class<?> representationClass, String humanPresentableName)
+ {
+ if (representationClass == null)
+ throw new NullPointerException("representationClass must not be null");
+ try
+ {
+ mimeType = new MimeType(javaSerializedObjectMimeType);
+ }
+ catch (MimeTypeParseException ex)
+ {
+ // Must not happen as we use a constant string.
+ assert false;
+ }
+ if (humanPresentableName == null)
+ humanPresentableName = javaSerializedObjectMimeType;
+ this.humanPresentableName = humanPresentableName;
+ this.representationClass = representationClass;
+ }
+
+ /**
+ * Initializes a new instance of <code>DataFlavor</code> with the
+ * specified MIME type and description. If the MIME type has a
+ * "class=&lt;rep class&gt;" parameter then the representation class will
+ * be the class name specified. Otherwise the class defaults to
+ * <code>java.io.InputStream</code>. If the human readable name
+ * is not specified (<code>null</code>) then the human readable name
+ * will be the same as the MIME type.
+ *
+ * @param mimeType The MIME type for this flavor.
+ * @param humanPresentableName The display name of this flavor.
+ * @param classLoader The class loader for finding classes if the default
+ * class loaders do not work.
+ *
+ * @exception IllegalArgumentException If the representation class
+ * specified cannot be loaded.
+ * @exception ClassNotFoundException If the class is not loaded.
+ */
+ public DataFlavor(String mimeType, String humanPresentableName,
+ ClassLoader classLoader)
+ throws ClassNotFoundException
+ {
+ init(mimeType, humanPresentableName, classLoader);
+ }
+
+ /**
+ * Initializes a new instance of <code>DataFlavor</code> with the
+ * specified MIME type and description. If the MIME type has a
+ * "class=&lt;rep class&gt;" parameter then the representation class will
+ * be the class name specified. Otherwise the class defaults to
+ * <code>java.io.InputStream</code>. If the human readable name
+ * is not specified (<code>null</code>) then the human readable name
+ * will be the same as the MIME type. This is the same as calling
+ * <code>new DataFlavor(mimeType, humanPresentableName, null)</code>.
+ *
+ * @param mimeType The MIME type for this flavor.
+ * @param humanPresentableName The display name of this flavor.
+ *
+ * @exception IllegalArgumentException If the representation class
+ * specified cannot be loaded.
+ */
+ public DataFlavor(String mimeType, String humanPresentableName)
+ {
+ try
+ {
+ init(mimeType, humanPresentableName, getClass().getClassLoader());
+ }
+ catch (ClassNotFoundException ex)
+ {
+ IllegalArgumentException iae =
+ new IllegalArgumentException("Class not found: " + ex.getMessage());
+ iae.initCause(ex);
+ throw iae;
+ }
+ }
+
+ /**
+ * Initializes a new instance of <code>DataFlavor</code> with the specified
+ * MIME type. This type can have a "class=" parameter to specify the
+ * representation class, and then the class must exist or an exception will
+ * be thrown. If there is no "class=" parameter then the representation class
+ * will be <code>java.io.InputStream</code>. This is the same as calling
+ * <code>new DataFlavor(mimeType, null)</code>.
+ *
+ * @param mimeType The MIME type for this flavor.
+ *
+ * @exception IllegalArgumentException If a class is not specified in
+ * the MIME type.
+ * @exception ClassNotFoundException If the class cannot be loaded.
+ */
+ public DataFlavor(String mimeType) throws ClassNotFoundException
+ {
+ init(mimeType, null, getClass().getClassLoader());
+ }
+
+ /**
+ * Called by various constructors to initialize this object.
+ *
+ * @param mime the mime string
+ * @param humanPresentableName the human presentable name
+ * @param loader the class loader to use for loading the representation
+ * class
+ */
+ private void init(String mime, String humanPresentableName,
+ ClassLoader loader)
+ throws ClassNotFoundException
+ {
+ if (mime == null)
+ throw new NullPointerException("The mime type must not be null");
+ try
+ {
+ mimeType = new MimeType(mime);
+ }
+ catch (MimeTypeParseException ex)
+ {
+ IllegalArgumentException iae =
+ new IllegalArgumentException("Invalid mime type");
+ iae.initCause(ex);
+ throw iae;
+ }
+ String className = mimeType.getParameter("class");
+ if (className == null)
+ {
+ if (mimeType.getBaseType().equals(javaSerializedObjectMimeType))
+ throw new IllegalArgumentException("Serialized object type must have"
+ + " a representation class parameter");
+ else
+ representationClass = java.io.InputStream.class;
+ }
+ else
+ representationClass = tryToLoadClass(className, loader);
+ mimeType.addParameter("class", representationClass.getName());
+
+ if (humanPresentableName == null)
+ {
+ humanPresentableName = mimeType.getParameter("humanPresentableName");
+ if (humanPresentableName == null)
+ humanPresentableName = mimeType.getBaseType();
+ }
+ this.humanPresentableName = humanPresentableName;
+ }
+
+ /**
+ * Returns the MIME type of this flavor.
+ *
+ * @return The MIME type for this flavor.
+ */
+ public String getMimeType()
+ {
+ return(mimeType.toString());
+ }
+
+ /**
+ * Returns the representation class for this flavor.
+ *
+ * @return The representation class for this flavor.
+ */
+ public Class<?> getRepresentationClass()
+ {
+ return(representationClass);
+ }
+
+ /**
+ * Returns the human presentable name for this flavor.
+ *
+ * @return The human presentable name for this flavor.
+ */
+ public String getHumanPresentableName()
+ {
+ return(humanPresentableName);
+ }
+
+ /**
+ * Returns the primary MIME type for this flavor.
+ *
+ * @return The primary MIME type for this flavor.
+ */
+ public String getPrimaryType()
+ {
+ return(mimeType.getPrimaryType());
+ }
+
+ /**
+ * Returns the MIME subtype for this flavor.
+ *
+ * @return The MIME subtype for this flavor.
+ */
+ public String getSubType()
+ {
+ return mimeType.getSubType();
+ }
+
+ /**
+ * Returns the value of the named MIME type parameter, or <code>null</code>
+ * if the parameter does not exist.
+ *
+ * @param paramName The name of the paramter.
+ *
+ * @return The value of the parameter.
+ */
+ public String getParameter(String paramName)
+ {
+ if ("humanPresentableName".equals(paramName))
+ return getHumanPresentableName();
+
+ return mimeType.getParameter(paramName);
+ }
+
+ /**
+ * Sets the human presentable name to the specified value.
+ *
+ * @param humanPresentableName The new display name.
+ */
+ public void setHumanPresentableName(String humanPresentableName)
+ {
+ this.humanPresentableName = humanPresentableName;
+ }
+
+ /**
+ * Tests the MIME type of this object for equality against the specified
+ * MIME type. Ignores parameters.
+ *
+ * @param mimeType The MIME type to test against.
+ *
+ * @return <code>true</code> if the MIME type is equal to this object's
+ * MIME type (ignoring parameters), <code>false</code> otherwise.
+ *
+ * @exception NullPointerException If mimeType is null.
+ */
+ public boolean isMimeTypeEqual(String mimeType)
+ {
+ if (mimeType == null)
+ throw new NullPointerException("mimeType must not be null");
+ boolean equal = false;
+ try
+ {
+ if (this.mimeType != null)
+ {
+ MimeType other = new MimeType(mimeType);
+ equal = this.mimeType.matches(other);
+ }
+ }
+ catch (MimeTypeParseException ex)
+ {
+ // Return false in this case.
+ }
+ return equal;
+ }
+
+ /**
+ * Tests the MIME type of this object for equality against the specified
+ * data flavor's MIME type
+ *
+ * @param flavor The flavor to test against.
+ *
+ * @return <code>true</code> if the flavor's MIME type is equal to this
+ * object's MIME type, <code>false</code> otherwise.
+ */
+ public final boolean isMimeTypeEqual(DataFlavor flavor)
+ {
+ return isMimeTypeEqual(flavor.getMimeType());
+ }
+
+ /**
+ * Tests whether or not this flavor represents a serialized object.
+ *
+ * @return <code>true</code> if this flavor represents a serialized
+ * object, <code>false</code> otherwise.
+ */
+ public boolean isMimeTypeSerializedObject()
+ {
+ return isMimeTypeEqual(javaSerializedObjectMimeType);
+ }
+
+ /**
+ * Tests whether or not this flavor has a representation class of
+ * <code>java.io.InputStream</code>.
+ *
+ * @return <code>true</code> if the representation class of this flavor
+ * is <code>java.io.InputStream</code>, <code>false</code> otherwise.
+ */
+ public boolean isRepresentationClassInputStream()
+ {
+ return InputStream.class.isAssignableFrom(representationClass);
+ }
+
+ /**
+ * Tests whether the representation class for this flavor is
+ * serializable.
+ *
+ * @return <code>true</code> if the representation class is serializable,
+ * <code>false</code> otherwise.
+ */
+ public boolean isRepresentationClassSerializable()
+ {
+ return Serializable.class.isAssignableFrom(representationClass);
+ }
+
+ /**
+ * Tests whether the representation class for his flavor is remote.
+ *
+ * @return <code>true</code> if the representation class is remote,
+ * <code>false</code> otherwise.
+ */
+ public boolean isRepresentationClassRemote()
+ {
+ return Remote.class.isAssignableFrom (representationClass);
+ }
+
+ /**
+ * Tests whether or not this flavor represents a serialized object.
+ *
+ * @return <code>true</code> if this flavor represents a serialized
+ * object, <code>false</code> otherwise.
+ */
+ public boolean isFlavorSerializedObjectType()
+ {
+ return isRepresentationClassSerializable()
+ && isMimeTypeEqual(javaSerializedObjectMimeType);
+ }
+
+ /**
+ * Tests whether or not this flavor represents a remote object.
+ *
+ * @return <code>true</code> if this flavor represents a remote object,
+ * <code>false</code> otherwise.
+ */
+ public boolean isFlavorRemoteObjectType()
+ {
+ return isRepresentationClassRemote()
+ && isRepresentationClassSerializable()
+ && isMimeTypeEqual(javaRemoteObjectMimeType);
+ }
+
+ /**
+ * Tests whether or not this flavor represents a list of files.
+ *
+ * @return <code>true</code> if this flavor represents a list of files,
+ * <code>false</code> otherwise.
+ */
+ public boolean isFlavorJavaFileListType()
+ {
+ if (getPrimaryType().equals(javaFileListFlavor.getPrimaryType())
+ && getSubType().equals(javaFileListFlavor.getSubType())
+ && javaFileListFlavor.representationClass
+ .isAssignableFrom(representationClass))
+ return true;
+
+ return false ;
+ }
+
+ /**
+ * Returns a copy of this object.
+ *
+ * @return A copy of this object.
+ *
+ * @exception CloneNotSupportedException If the object's class does not support
+ * the Cloneable interface. Subclasses that override the clone method can also
+ * throw this exception to indicate that an instance cannot be cloned.
+ */
+ public Object clone () throws CloneNotSupportedException
+ {
+ // FIXME - This cannot be right.
+ try
+ {
+ return super.clone();
+ }
+ catch(Exception e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * This method test the specified <code>DataFlavor</code> for equality
+ * against this object. This will be true if the MIME type and
+ * representation class are the equal. If the primary type is 'text'
+ * then also the value of the charset parameter is compared. In such a
+ * case when the charset parameter isn't given then the charset is
+ * assumed to be equal to the default charset of the platform. All
+ * other parameters are ignored.
+ *
+ * @param flavor The <code>DataFlavor</code> to test against.
+ *
+ * @return <code>true</code> if the flavor is equal to this object,
+ * <code>false</code> otherwise.
+ */
+ public boolean equals(DataFlavor flavor)
+ {
+ if (flavor == null)
+ return false;
+
+ String primary = getPrimaryType();
+ if (! primary.equals(flavor.getPrimaryType()))
+ return false;
+
+ String sub = getSubType();
+ if (! sub.equals(flavor.getSubType()))
+ return false;
+
+ if (! this.representationClass.equals(flavor.representationClass))
+ return false;
+
+ if (primary.equals("text"))
+ if (! isRepresentationClassCharBuffer()
+ && ! isRepresentationClassReader()
+ && representationClass != java.lang.String.class
+ && ! (representationClass.isArray()
+ && representationClass.getComponentType() == Character.TYPE))
+ {
+ String charset = getParameter("charset");
+ String otherset = flavor.getParameter("charset");
+ String defaultset = Charset.defaultCharset().name();
+
+ if (charset == null || charset.equals(defaultset))
+ return (otherset == null || otherset.equals(defaultset));
+
+ return charset.equals(otherset);
+ }
+
+ return true;
+ }
+
+ /**
+ * This method test the specified <code>Object</code> for equality
+ * against this object. This will be true if the following conditions
+ * are met:
+ * <p>
+ * <ul>
+ * <li>The object is not <code>null</code>.</li>
+ * <li>The object is an instance of <code>DataFlavor</code>.</li>
+ * <li>The object's MIME type and representation class are equal to
+ * this object's.</li>
+ * </ul>
+ *
+ * @param obj The <code>Object</code> to test against.
+ *
+ * @return <code>true</code> if the flavor is equal to this object,
+ * <code>false</code> otherwise.
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof DataFlavor))
+ return false;
+
+ return equals((DataFlavor) obj);
+ }
+
+ /**
+ * Tests whether or not the specified string is equal to the MIME type
+ * of this object.
+ *
+ * @param str The string to test against.
+ *
+ * @return <code>true</code> if the string is equal to this object's MIME
+ * type, <code>false</code> otherwise.
+ *
+ * @deprecated Not compatible with <code>hashCode()</code>.
+ * Use <code>isMimeTypeEqual()</code>
+ */
+ public boolean equals(String str)
+ {
+ return isMimeTypeEqual(str);
+ }
+
+ /**
+ * Returns the hash code for this data flavor.
+ * The hash code is based on the (lower case) mime type and the
+ * representation class.
+ */
+ public int hashCode()
+ {
+ return mimeType.toString().hashCode() ^ representationClass.hashCode();
+ }
+
+ /**
+ * Returns <code>true</code> when the given <code>DataFlavor</code>
+ * matches this one.
+ */
+ public boolean match(DataFlavor dataFlavor)
+ {
+ // XXX - How is this different from equals?
+ return equals(dataFlavor);
+ }
+
+ /**
+ * This method exists for backward compatibility. It simply returns
+ * the same name/value pair passed in.
+ *
+ * @param name The parameter name.
+ * @param value The parameter value.
+ *
+ * @return The name/value pair.
+ *
+ * @deprecated
+ */
+ protected String normalizeMimeTypeParameter(String name, String value)
+ {
+ return name + "=" + value;
+ }
+
+ /**
+ * This method exists for backward compatibility. It simply returns
+ * the MIME type string unchanged.
+ *
+ * @param type The MIME type.
+ *
+ * @return The MIME type.
+ *
+ * @deprecated
+ */
+ protected String normalizeMimeType(String type)
+ {
+ return type;
+ }
+
+ /**
+ * Serialize this class.
+ *
+ * @param stream The <code>ObjectOutput</code> stream to serialize to.
+ *
+ * @exception IOException If an error occurs.
+ */
+ public void writeExternal(ObjectOutput stream)
+ throws IOException
+ {
+ if (mimeType != null)
+ {
+ mimeType.addParameter("humanPresentableName", humanPresentableName);
+ stream.writeObject(mimeType);
+ mimeType.removeParameter("humanPresentableName");
+ }
+ else
+ stream.writeObject(null);
+ stream.writeObject(representationClass);
+ }
+
+
+ /**
+ * De-serialize this class.
+ *
+ * @param stream The <code>ObjectInput</code> stream to deserialize from.
+ *
+ * @exception IOException If an error ocurs.
+ * @exception ClassNotFoundException If the class for an object being restored
+ * cannot be found.
+ */
+ public void readExternal(ObjectInput stream)
+ throws IOException, ClassNotFoundException
+ {
+ mimeType = (MimeType) stream.readObject();
+ String className = null;
+ if (mimeType != null)
+ {
+ humanPresentableName =
+ mimeType.getParameter("humanPresentableName");
+ mimeType.removeParameter("humanPresentableName");
+ className = mimeType.getParameter("class");
+ if (className == null)
+ throw new IOException("No class in mime type");
+ }
+ try
+ {
+ representationClass = (Class) stream.readObject();
+ }
+ catch (OptionalDataException ex)
+ {
+ if (ex.eof && ex.length == 0)
+ {
+ if (className != null)
+ representationClass = tryToLoadClass(className,
+ getClass().getClassLoader());
+ }
+ else
+ throw ex;
+ }
+ }
+
+ /**
+ * Returns a string representation of this DataFlavor. Including the
+ * representation class name, MIME type and human presentable name.
+ */
+ public String toString()
+ {
+ return (getClass().getName()
+ + "[representationClass=" + getRepresentationClass().getName()
+ + ",mimeType=" + getMimeType()
+ + ",humanPresentableName=" + getHumanPresentableName()
+ + "]");
+ }
+
+ /**
+ * XXX - Currently returns <code>java.io.InputStream</code>.
+ *
+ * @since 1.3
+ */
+ public final Class<?> getDefaultRepresentationClass()
+ {
+ return java.io.InputStream.class;
+ }
+
+ /**
+ * XXX - Currently returns <code>java.io.InputStream</code>.
+ */
+ public final String getDefaultRepresentationClassAsString()
+ {
+ return getDefaultRepresentationClass().getName();
+ }
+
+ /**
+ * Creates a <code>Reader</code> for a given <code>Transferable</code>.
+ *
+ * If the representation class is a (subclass of) <code>Reader</code>
+ * then an instance of the representation class is returned. If the
+ * representatation class is a <code>String</code> then a
+ * <code>StringReader</code> is returned. And if the representation class
+ * is a (subclass of) <code>InputStream</code> and the primary MIME type
+ * is "text" then a <code>InputStreamReader</code> for the correct charset
+ * encoding is returned.
+ *
+ * @param transferable The <code>Transferable</code> for which a text
+ * <code>Reader</code> is requested.
+ *
+ * @exception IllegalArgumentException If the representation class is not one
+ * of the seven listed above or the Transferable has null data.
+ * @exception NullPointerException If the Transferable is null.
+ * @exception UnsupportedFlavorException when the transferable doesn't
+ * support this <code>DataFlavor</code>. Or if the representable class
+ * isn't a (subclass of) <code>Reader</code>, <code>String</code>,
+ * <code>InputStream</code> and/or the primary MIME type isn't "text".
+ * @exception IOException when any IOException occurs.
+ * @exception UnsupportedEncodingException if the "charset" isn't supported
+ * on this platform.
+ */
+ public Reader getReaderForText(Transferable transferable)
+ throws UnsupportedFlavorException, IOException
+ {
+ if (!transferable.isDataFlavorSupported(this))
+ throw new UnsupportedFlavorException(this);
+
+ if (Reader.class.isAssignableFrom(representationClass))
+ return (Reader)transferable.getTransferData(this);
+
+ if (String.class.isAssignableFrom(representationClass))
+ return new StringReader((String)transferable.getTransferData(this));
+
+ if (InputStream.class.isAssignableFrom(representationClass)
+ && "text".equals(getPrimaryType()))
+ {
+ InputStream in = (InputStream)transferable.getTransferData(this);
+ String encoding = getParameter("charset");
+ if (encoding == null)
+ encoding = "us-ascii";
+ return new InputStreamReader(in, encoding);
+ }
+
+ throw new UnsupportedFlavorException(this);
+ }
+
+ /**
+ * Returns whether the representation class for this DataFlavor is
+ * @see java.nio.ByteBuffer or a subclass thereof.
+ *
+ * @since 1.4
+ */
+ public boolean isRepresentationClassByteBuffer()
+ {
+ return ByteBuffer.class.isAssignableFrom(representationClass);
+ }
+
+ /**
+ * Returns whether the representation class for this DataFlavor is
+ * @see java.nio.CharBuffer or a subclass thereof.
+ *
+ * @since 1.4
+ */
+ public boolean isRepresentationClassCharBuffer()
+ {
+ return CharBuffer.class.isAssignableFrom(representationClass);
+ }
+
+ /**
+ * Returns whether the representation class for this DataFlavor is
+ * @see java.io.Reader or a subclass thereof.
+ *
+ * @since 1.4
+ */
+ public boolean isRepresentationClassReader()
+ {
+ return Reader.class.isAssignableFrom(representationClass);
+ }
+
+ /**
+ * Returns whether this <code>DataFlavor</code> is a valid text flavor for
+ * this implementation of the Java platform. Only flavors equivalent to
+ * <code>DataFlavor.stringFlavor</code> and <code>DataFlavor</code>s with
+ * a primary MIME type of "text" can be valid text flavors.
+ * <p>
+ * If this flavor supports the charset parameter, it must be equivalent to
+ * <code>DataFlavor.stringFlavor</code>, or its representation must be
+ * <code>java.io.Reader</code>, <code>java.lang.String</code>,
+ * <code>java.nio.CharBuffer</code>, <code>java.io.InputStream</code> or
+ * <code>java.nio.ByteBuffer</code>,
+ * If the representation is <code>java.io.InputStream</code> or
+ * <code>java.nio.ByteBuffer</code>, then this flavor's <code>charset</code>
+ * parameter must be supported by this implementation of the Java platform.
+ * If a charset is not specified, then the platform default charset, which
+ * is always supported, is assumed.
+ * <p>
+ * If this flavor does not support the charset parameter, its
+ * representation must be <code>java.io.InputStream</code>,
+ * <code>java.nio.ByteBuffer</code>.
+ * <p>
+ * See <code>selectBestTextFlavor</code> for a list of text flavors which
+ * support the charset parameter.
+ *
+ * @return <code>true</code> if this <code>DataFlavor</code> is a valid
+ * text flavor as described above; <code>false</code> otherwise
+ * @see #selectBestTextFlavor
+ * @since 1.4
+ */
+ public boolean isFlavorTextType() {
+ // FIXME: I'm not 100% sure if this implementation does the same like sun's does
+ if(equals(DataFlavor.stringFlavor) || getPrimaryType().equals("text"))
+ {
+ String charset = getParameter("charset");
+ Class c = getRepresentationClass();
+ if(charset != null)
+ {
+ if(Reader.class.isAssignableFrom(c)
+ || CharBuffer.class.isAssignableFrom(c)
+ || String.class.isAssignableFrom(c))
+ {
+ return true;
+ }
+ else if(InputStream.class.isAssignableFrom(c)
+ || ByteBuffer.class.isAssignableFrom(c))
+ {
+ return Charset.isSupported(charset);
+ }
+ }
+ else if(InputStream.class.isAssignableFrom(c)
+ || ByteBuffer.class.isAssignableFrom(c))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+} // class DataFlavor
diff --git a/libjava/classpath/java/awt/datatransfer/FlavorEvent.java b/libjava/classpath/java/awt/datatransfer/FlavorEvent.java
new file mode 100644
index 000000000..8a292f850
--- /dev/null
+++ b/libjava/classpath/java/awt/datatransfer/FlavorEvent.java
@@ -0,0 +1,57 @@
+/* FlavorEvent -- Event indicating a ClipBoard has different flavors available.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.datatransfer;
+
+import java.util.EventObject;
+
+/**
+ * Event indicating a Clipboard has different flavors available.
+ * Fired by a ClipBoard for registered FlavorListeners.
+ *
+ * @author Mark J. Wielaard (mark@klomp.org)
+ *
+ * @since 1.5
+ */
+public class FlavorEvent extends EventObject
+{
+ public FlavorEvent(Clipboard board)
+ {
+ super(board);
+ }
+}
diff --git a/libjava/classpath/java/awt/datatransfer/FlavorListener.java b/libjava/classpath/java/awt/datatransfer/FlavorListener.java
new file mode 100644
index 000000000..eb388aa84
--- /dev/null
+++ b/libjava/classpath/java/awt/datatransfer/FlavorListener.java
@@ -0,0 +1,54 @@
+/* FlavorListener -- Interface for tagging an interest in FlavorEvents.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.datatransfer;
+
+import java.util.EventListener;
+
+/**
+ * Interface for tagging an interest in FlavorEvents by a class. The
+ * flavorsChanged() method will be called with a FlavorEvent pointing
+ * to the Clipboard which has content in different Flavors available.
+ *
+ * @author Mark J. Wielaard (mark@klomp.org)
+ */
+public interface FlavorListener
+ extends EventListener
+{
+ void flavorsChanged(FlavorEvent event);
+}
diff --git a/libjava/classpath/java/awt/datatransfer/FlavorMap.java b/libjava/classpath/java/awt/datatransfer/FlavorMap.java
new file mode 100644
index 000000000..8842c8e55
--- /dev/null
+++ b/libjava/classpath/java/awt/datatransfer/FlavorMap.java
@@ -0,0 +1,75 @@
+/* FlavorMap.java -- Maps between flavor names and MIME types.
+ Copyright (C) 1999, 2001 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.datatransfer;
+
+import java.util.Map;
+
+/**
+ * This interface maps between native platform type names and DataFlavors.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface FlavorMap
+{
+ /**
+ * Maps the specified <code>DataFlavor</code> objects to the native
+ * data type name. The returned <code>Map</code> has keys that are
+ * the data flavors and values that are strings. The returned map
+ * may be modified. This can be useful for implementing nested mappings.
+ *
+ * @param flavors An array of data flavors to map
+ * or null for all data flavors.
+ *
+ * @return A <code>Map</code> of native data types.
+ */
+ Map<DataFlavor, String> getNativesForFlavors (DataFlavor[] flavors);
+
+ /**
+ * Maps the specified native type names to <code>DataFlavor</code>'s.
+ * The returned <code>Map</code> has keys that are strings and values
+ * that are <code>DataFlavor</code>'s. The returned map may be
+ * modified. This can be useful for implementing nested mappings.
+ *
+ * @param natives An array of native types to map
+ * or null for all native types.
+ *
+ * @return A <code>Map</code> of data flavors.
+ */
+ Map<String, DataFlavor> getFlavorsForNatives (String[] natives);
+}
diff --git a/libjava/classpath/java/awt/datatransfer/FlavorTable.java b/libjava/classpath/java/awt/datatransfer/FlavorTable.java
new file mode 100644
index 000000000..f6c43af83
--- /dev/null
+++ b/libjava/classpath/java/awt/datatransfer/FlavorTable.java
@@ -0,0 +1,73 @@
+/* FlavorTable.java -- A relaxed mapping between flavors
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.datatransfer;
+
+import java.util.List;
+
+/**
+ * A FlavorMap which no longer requires a 1-to-1 mapping between flavors. Any
+ * native can map to multiple flavors, and any flavor can map to multiple
+ * natives; although the mappings are usually symmetric.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public interface FlavorTable extends FlavorMap
+{
+ /**
+ * Returns a list of String natives corresponding to the given flavor. The
+ * list should be sorted from best to worst. The list must be modifiable
+ * without affecting this table.
+ *
+ * @param flavor the flavor to look up, or null to return all natives
+ * @return the sorted list of natives
+ */
+ List<String> getNativesForFlavor(DataFlavor flavor);
+
+ /**
+ * Returns a list of flavors corresponding to the given String native. The
+ * list should be sorted from best to worst. The list must be modifiable
+ * without affecting this table.
+ *
+ * @param name the native name to look up, or null to return all flavors
+ * @return the sorted list of flavors
+ */
+ List<DataFlavor> getFlavorsForNative(String name);
+}
diff --git a/libjava/classpath/java/awt/datatransfer/MimeType.java b/libjava/classpath/java/awt/datatransfer/MimeType.java
new file mode 100644
index 000000000..143e8700b
--- /dev/null
+++ b/libjava/classpath/java/awt/datatransfer/MimeType.java
@@ -0,0 +1,283 @@
+/* MimeType.java -- A helper class for mime handling in DataFlavor
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.datatransfer;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+/**
+ * A helper class for mime handling in DataFlavor.
+ *
+ * A Mauve test for DataFlavor.writeExternal() shows that a non-public
+ * class java.awt.datatransfer.MimeType gets serialized. This class
+ * is mainly here for serialization compatibility. Of course,
+ * now that we have it here, we can just as well implement some
+ * mime handling facility here.
+ */
+class MimeType
+ implements Externalizable
+{
+
+ /**
+ * The primary type.
+ */
+ private String primaryType;
+
+ /**
+ * The subtype.
+ */
+ private String subType;
+
+ /**
+ * Additional parameters to be appended to the mime string.
+ */
+ private HashMap parameters;
+
+ /**
+ * This is only here for deserialization.
+ */
+ public MimeType()
+ {
+ parameters = new HashMap();
+ }
+
+ /**
+ * Creates a new MimeType object.
+ *
+ * @param mime the mime type
+ */
+ MimeType(String mime)
+ throws MimeTypeParseException
+ {
+ this();
+ parse(mime);
+ }
+
+ /**
+ * Adds a mime parameter.
+ *
+ * @param param the parameter key
+ * @param value the parameter value
+ */
+ void addParameter(String param, String value)
+ {
+ parameters.put(param, value);
+ }
+
+ /**
+ * Removes the parameter with the specified key.
+ *
+ * @param param the parameter to remove
+ */
+ void removeParameter(String param)
+ {
+ parameters.remove(param);
+ }
+
+ /**
+ * Returns the parameter for the <code>key</code>.
+ *
+ * @param key the parameter key
+ *
+ * @return the parameter for the <code>key</code>
+ */
+ String getParameter(String key)
+ {
+ return (String) parameters.get(key);
+ }
+
+ /**
+ * Returns the primary type.
+ *
+ * @return the primary type
+ */
+ String getPrimaryType()
+ {
+ return primaryType;
+ }
+
+ String getSubType()
+ {
+ return subType;
+ }
+
+ /**
+ * Returns the base type of this mime type. This is the primary
+ * type plus the subtype, separated by '/'.
+ *
+ * @return the base type of this mime type
+ */
+ String getBaseType()
+ {
+ return primaryType + '/' + subType;
+ }
+
+ /**
+ * Returns <code>true</code> if this mime type and another mime type
+ * match. This will be true when their primary types are equal, and their
+ * subtypes are equal (or when either subtype is * ).
+ *
+ * @param other the other mime type
+ *
+ * @return <code>true</code> if the mime types match, <code>false</code>
+ * otherwise
+ */
+ boolean matches(MimeType other)
+ {
+ boolean match = false;
+ if (other != null)
+ {
+ match = primaryType.equals(other.primaryType)
+ && (subType.equals("*") || other.subType.equals("*")
+ || subType.equals(other.subType));
+ }
+ return match;
+ }
+
+ /**
+ * Serializes the mime type.
+ *
+ * @param in the input stream to read from
+ *
+ * @throws ClassNotFoundException not thrown here
+ * @throws IOException when something goes wrong on the input stream,
+ * or when the mime type can't be parsed
+ */
+ public void readExternal(ObjectInput in)
+ throws ClassNotFoundException, IOException
+ {
+ String mime = in.readUTF();
+ parameters.clear();
+ try
+ {
+ parse(mime);
+ }
+ catch (MimeTypeParseException ex)
+ {
+ IOException ioEx = new IOException();
+ ioEx.initCause(ex);
+ throw ioEx;
+ }
+ }
+
+ /**
+ * Serializes this mime type.
+ *
+ * @param out the output stream
+ *
+ * @throws IOException when something goes wrong on the output stream
+ */
+ public void writeExternal(ObjectOutput out)
+ throws IOException
+ {
+ out.writeUTF(toString());
+ }
+
+ /**
+ * Creates a string representation of this mime type.
+ *
+ * @return a string representation of this mime type
+ */
+ public String toString()
+ {
+ CPStringBuilder s = new CPStringBuilder();
+ s.append(primaryType);
+ s.append('/');
+ s.append(subType);
+ if (parameters.size() > 0)
+ {
+ Set entries = parameters.entrySet();
+ for (Iterator i = entries.iterator(); i.hasNext();)
+ {
+ s.append("; ");
+ Map.Entry entry = (Map.Entry) i.next();
+ s.append(entry.getKey());
+ s.append('=');
+ s.append(entry.getValue());
+ }
+ }
+ return s.toString();
+ }
+
+ /**
+ * Parses the specified mime type string and initializes the fields
+ * of this object.
+ *
+ * @param mime the mime type string
+ */
+ private void parse(String mime)
+ throws MimeTypeParseException
+ {
+ // FIXME: Maybe implement more sophisticated mime string parsing according
+ // to RFC 2045 and 2046.
+ StringTokenizer tokenizer = new StringTokenizer(mime);
+ try
+ {
+ primaryType = tokenizer.nextToken("/");
+ subType = tokenizer.nextToken("/;");
+ }
+ catch (NoSuchElementException ex)
+ {
+ throw new MimeTypeParseException("Expected / separator");
+ }
+
+ // Add any parameters.
+ while (tokenizer.hasMoreTokens())
+ {
+ String keyValuePair = tokenizer.nextToken(";");
+ int i = keyValuePair.indexOf('=');
+ if (i == -1)
+ throw new MimeTypeParseException("Expected = as parameter separator");
+ String key = keyValuePair.substring(0, i).trim();
+ String value = keyValuePair.substring(i + 1).trim();
+ parameters.put(key, value);
+ }
+ }
+
+}
diff --git a/libjava/classpath/java/awt/datatransfer/MimeTypeParseException.java b/libjava/classpath/java/awt/datatransfer/MimeTypeParseException.java
new file mode 100644
index 000000000..6113ab760
--- /dev/null
+++ b/libjava/classpath/java/awt/datatransfer/MimeTypeParseException.java
@@ -0,0 +1,70 @@
+/* MimeTypeParseException.java -- thrown when MIME string couldn't be parsed
+ Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.datatransfer;
+
+/**
+ * MIME string couldn't be parsed correctly.
+ *
+ * @author Mark Wielaard (mark@klomp.org)
+ * @status updated to 1.4
+ */
+public class MimeTypeParseException extends Exception
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -5604407764691570741L;
+
+ /**
+ * Create a new instance without any message.
+ */
+ public MimeTypeParseException()
+ {
+ }
+
+ /**
+ * Create a new instance with a specified detailed error message.
+ *
+ * @param message the message
+ */
+ public MimeTypeParseException(String message)
+ {
+ super(message);
+ }
+} // class MimeTypeParseException
diff --git a/libjava/classpath/java/awt/datatransfer/StringSelection.java b/libjava/classpath/java/awt/datatransfer/StringSelection.java
new file mode 100644
index 000000000..4b64cda57
--- /dev/null
+++ b/libjava/classpath/java/awt/datatransfer/StringSelection.java
@@ -0,0 +1,157 @@
+/* StringSelection.java -- Clipboard handler for text.
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.datatransfer;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+/**
+ * This class transfers a string as plain text using the clipboard.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class StringSelection implements Transferable, ClipboardOwner
+{
+
+/*
+ * Class Variables
+ */
+
+// List of flavors we support
+// XXX: DataFlavor.plainTextFlavor is deprecated.
+static final DataFlavor[] supported_flavors
+ = { DataFlavor.stringFlavor,
+ DataFlavor.plainTextFlavor };
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+// This is the data to transfer
+private String data;
+
+ /**
+ * Transfer the specfied string as text.
+ *
+ * @param data the data for the string selection
+ */
+ public StringSelection(String data)
+ {
+ this.data = data;
+ }
+
+/**
+ * Returns a list of supported data flavors.
+ *
+ * @return A list of supported data flavors.
+ */
+public DataFlavor[]
+getTransferDataFlavors()
+{
+ return(supported_flavors);
+}
+
+/*************************************************************************/
+
+/**
+ * Tests whether or not the specified data flavor is supported.
+ *
+ * @param flavor The data flavor to test.
+ *
+ * @return <code>true</code> if the data flavor is supported,
+ * <code>false</code> otherwise.
+ */
+public boolean
+isDataFlavorSupported(DataFlavor flavor)
+{
+ for (int i = 0; i < supported_flavors.length; i++)
+ if (supported_flavors[i].equals(flavor))
+ return(true);
+
+ return(false);
+}
+
+/*************************************************************************/
+
+/**
+ * This method returns the data in the requested format.
+ *
+ * @param flavor The desired data flavor.
+ *
+ * @return The transferred data.
+ *
+ * @exception UnsupportedFlavorException If the specified flavor is not
+ * supported.
+ * @exception IOException If any other error occurs.
+ */
+public Object
+getTransferData(DataFlavor flavor) throws UnsupportedFlavorException,
+ IOException
+{
+ if (!isDataFlavorSupported(flavor))
+ throw new UnsupportedFlavorException(flavor);
+
+ if (DataFlavor.plainTextFlavor == flavor)
+ /* The behavior of this method for DataFlavor.plainTextFlavor and
+ equivalent DataFlavors is inconsistent with the definition of
+ DataFlavor.plainTextFlavor. We choose to do like Sun's implementation
+ and return a Reader instead of an InputString. */
+ /* return(new StringBufferInputStream(data)); */
+ return(new StringReader(data));
+ else // DataFlavor.stringFlavor
+ return data;
+}
+
+/*************************************************************************/
+
+/**
+ * Called when ownership of the clipboard object is lost.
+ *
+ * @param clipboard The affected clipboard.
+ * @param contents The clipboard contents.
+ */
+public void
+lostOwnership(Clipboard clipboard, Transferable contents)
+{
+ // FIXME: What does this do?
+}
+
+} // class StringSelection
diff --git a/libjava/classpath/java/awt/datatransfer/SystemFlavorMap.java b/libjava/classpath/java/awt/datatransfer/SystemFlavorMap.java
new file mode 100644
index 000000000..65c14c1ba
--- /dev/null
+++ b/libjava/classpath/java/awt/datatransfer/SystemFlavorMap.java
@@ -0,0 +1,561 @@
+/* SystemFlavorMap.java -- Maps between native flavor names and MIME types.
+ Copyright (C) 2001, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.datatransfer;
+
+import java.awt.Toolkit;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.WeakHashMap;
+
+/**
+ * This class maps between native platform type names and DataFlavors.
+ *
+ * XXX - The current implementation does no mapping at all.
+ *
+ * @author Mark Wielaard (mark@klomp.org)
+ *
+ * @since 1.2
+ */
+public final class SystemFlavorMap implements FlavorMap, FlavorTable
+{
+ /**
+ * The map which maps the thread's <code>ClassLoaders</code> to
+ * <code>SystemFlavorMaps</code>.
+ */
+ private static final Map systemFlavorMaps = new WeakHashMap();
+
+ /**
+ * Constant which is used to prefix encode Java MIME types.
+ */
+ private static final String GNU_JAVA_MIME_PREFIX = "gnu.java:";
+
+ /**
+ * This map maps native <code>String</code>s to lists of
+ * <code>DataFlavor</code>s
+ */
+ private HashMap<String,List<DataFlavor>> nativeToFlavorMap =
+ new HashMap<String,List<DataFlavor>>();
+
+ /**
+ * This map maps <code>DataFlavor</code>s to lists of native
+ * <code>String</code>s
+ */
+ private HashMap<DataFlavor, List<String>> flavorToNativeMap =
+ new HashMap<DataFlavor, List<String>>();
+
+ /**
+ * Private constructor.
+ */
+ private SystemFlavorMap ()
+ {
+ AccessController.doPrivileged
+ (new PrivilegedAction<Object>()
+ {
+ public Object run()
+ {
+ try
+ {
+ // Load installed flavormap.properties first.
+ String sep = File.separator;
+ File propsFile =
+ new File(System.getProperty("gnu.classpath.home.url")
+ + sep + "accessibility.properties");
+ InputStream in = new FileInputStream(propsFile);
+ Properties props = new Properties();
+ props.load(in);
+ in.close();
+
+ String augmented = Toolkit.getProperty("AWT.DnD.flavorMapFileURL",
+ null);
+ if (augmented != null)
+ {
+ URL url = new URL(augmented);
+ in = url.openStream();
+ props.load(in);
+ }
+ setupMapping(props);
+ }
+ catch (IOException ex)
+ {
+ // Can't do anything about it.
+ }
+ return null;
+ }
+ });
+ }
+
+ /**
+ * Sets up the mapping from native to mime types and vice versa as specified
+ * in the flavormap.properties file.
+ *
+ * This is package private to avoid an accessor method.
+ *
+ * @param props the properties file
+ */
+ void setupMapping(Properties props)
+ {
+ Enumeration propNames = props.propertyNames();
+ while (propNames.hasMoreElements())
+ {
+ try
+ {
+ String nat = (String) propNames.nextElement();
+ String mime = (String) props.getProperty(nat);
+ // Check valid mime type.
+ MimeType type = new MimeType(mime);
+ DataFlavor flav = new DataFlavor(mime);
+
+ List<DataFlavor> flavs = nativeToFlavorMap.get(nat);
+ if (flavs == null)
+ {
+ flavs = new ArrayList<DataFlavor>();
+ nativeToFlavorMap.put(nat, flavs);
+ }
+ List<String> nats = flavorToNativeMap.get(flav);
+ if (nats == null)
+ {
+ nats = new ArrayList<String>();
+ flavorToNativeMap.put(flav, nats);
+ }
+ flavs.add(flav);
+ nats.add(nat);
+ }
+ catch (ClassNotFoundException ex)
+ {
+ // Skip.
+ }
+ catch (MimeTypeParseException ex)
+ {
+ // Skip.
+ }
+ }
+ }
+
+ /**
+ * Maps the specified <code>DataFlavor</code> objects to the native
+ * data type name. The returned <code>Map</code> has keys that are
+ * the data flavors and values that are strings. The returned map
+ * may be modified. This can be useful for implementing nested mappings.
+ *
+ * @param flavors An array of data flavors to map
+ * or null for all data flavors.
+ *
+ * @return A <code>Map</code> of native data types to data flavors.
+ */
+ public Map<DataFlavor, String> getNativesForFlavors (DataFlavor[] flavors)
+ {
+ return new HashMap<DataFlavor, String>();
+ }
+
+ /**
+ * Maps the specified native type names to <code>DataFlavor</code>'s.
+ * The returned <code>Map</code> has keys that are strings and values
+ * that are <code>DataFlavor</code>'s. The returned map may be
+ * modified. This can be useful for implementing nested mappings.
+ *
+ * @param natives An array of native types to map
+ * or null for all native types.
+ *
+ * @return A <code>Map</code> of data flavors to native type names.
+ */
+ public Map<String, DataFlavor> getFlavorsForNatives (String[] natives)
+ {
+ return new HashMap<String, DataFlavor>();
+ }
+
+ /**
+ * Returns the (System)FlavorMap for the current thread's
+ * ClassLoader.
+ */
+ public static FlavorMap getDefaultFlavorMap ()
+ {
+ ClassLoader classLoader = Thread.currentThread()
+ .getContextClassLoader();
+
+ //if ContextClassLoader not set, use system default
+ if (classLoader == null)
+ {
+ classLoader = ClassLoader.getSystemClassLoader();
+ }
+
+ synchronized(systemFlavorMaps)
+ {
+ FlavorMap map = (FlavorMap)
+ systemFlavorMaps.get(classLoader);
+ if (map == null)
+ {
+ map = new SystemFlavorMap();
+ systemFlavorMaps.put(classLoader, map);
+ }
+ return map;
+ }
+ }
+
+ /**
+ * Encodes a MIME type for use as a <code>String</code> native. The format
+ * of an encoded representation of a MIME type is implementation-dependent.
+ * The only restrictions are:
+ * <ul>
+ * <li>The encoded representation is <code>null</code> if and only if the
+ * MIME type <code>String</code> is <code>null</code>.</li>
+ * <li>The encoded representations for two non-<code>null</code> MIME type
+ * <code>String</code>s are equal if and only if these <code>String</code>s
+ * are equal according to <code>String.equals(Object)</code>.</li>
+ * </ul>
+ * <p>
+ * The present implementation of this method returns the specified MIME
+ * type <code>String</code> prefixed with <code>gnu.java:</code>.
+ *
+ * @param mime the MIME type to encode
+ * @return the encoded <code>String</code>, or <code>null</code> if
+ * mimeType is <code>null</code>
+ */
+ public static String encodeJavaMIMEType (String mime)
+ {
+ if (mime != null)
+ return GNU_JAVA_MIME_PREFIX + mime;
+ else
+ return null;
+ }
+
+ /**
+ * Encodes a <code>DataFlavor</code> for use as a <code>String</code>
+ * native. The format of an encoded <code>DataFlavor</code> is
+ * implementation-dependent. The only restrictions are:
+ * <ul>
+ * <li>The encoded representation is <code>null</code> if and only if the
+ * specified <code>DataFlavor</code> is <code>null</code> or its MIME type
+ * <code>String</code> is <code>null</code>.</li>
+ * <li>The encoded representations for two non-<code>null</code>
+ * <code>DataFlavor</code>s with non-<code>null</code> MIME type
+ * <code>String</code>s are equal if and only if the MIME type
+ * <code>String</code>s of these <code>DataFlavor</code>s are equal
+ * according to <code>String.equals(Object)</code>.</li>
+ * </ul>
+ * <p>
+ * The present implementation of this method returns the MIME type
+ * <code>String</code> of the specified <code>DataFlavor</code> prefixed
+ * with <code>gnu.java:</code>.
+ *
+ * @param df the <code>DataFlavor</code> to encode
+ * @return the encoded <code>String</code>, or <code>null</code> if
+ * flav is <code>null</code> or has a <code>null</code> MIME type
+ */
+ public static String encodeDataFlavor (DataFlavor df)
+ {
+ if (df != null)
+ {
+ return encodeJavaMIMEType(df.getMimeType());
+ }
+ else
+ return null;
+ }
+
+ /**
+ * Returns true if the native type name can be represented as
+ * a java mime type. Returns <code>false</code> if parameter is
+ * <code>null</code>.
+ */
+ public static boolean isJavaMIMEType (String name)
+ {
+ return (name != null && name.startsWith(GNU_JAVA_MIME_PREFIX));
+ }
+
+ /**
+ * Decodes a <code>String</code> native for use as a Java MIME type.
+ *
+ * @param name the <code>String</code> to decode
+ * @return the decoded Java MIME type, or <code>null</code> if nat
+ * is not an encoded <code>String</code> native
+ */
+ public static String decodeJavaMIMEType (String name)
+ {
+ if (isJavaMIMEType(name))
+ {
+ return name.substring(GNU_JAVA_MIME_PREFIX.length());
+ }
+ else
+ return null;
+ }
+
+ /**
+ * Returns the data flavor given the native type name
+ * or null when no such data flavor exists.
+ */
+ public static DataFlavor decodeDataFlavor (String name)
+ throws ClassNotFoundException
+ {
+ String javaMIMEType = decodeJavaMIMEType (name);
+
+ if (javaMIMEType != null)
+ return new DataFlavor (javaMIMEType);
+ else
+ return null;
+ }
+
+ /**
+ * Returns a List of <code>DataFlavors</code> to which the specified
+ * <code>String</code> native can be translated by the data transfer
+ * subsystem. The <code>List</code> will be sorted from best
+ * <code>DataFlavor</code> to worst. That is, the first <code>DataFlavor
+ * </code> will best reflect data in the specified native to a Java
+ * application.
+ * <p>
+ * If the specified native is previously unknown to the data transfer
+ * subsystem, and that native has been properly encoded, then invoking
+ * this method will establish a mapping in both directions between the
+ * specified native and a DataFlavor whose MIME type is a decoded
+ * version of the native.
+ */
+ public List<DataFlavor> getFlavorsForNative(String nat)
+ {
+ List<DataFlavor> ret = new ArrayList<DataFlavor>();
+ if (nat == null)
+ {
+ Collection<List<DataFlavor>> all = nativeToFlavorMap.values();
+ for (List<DataFlavor> list : all)
+ {
+ for (DataFlavor flav : list)
+ {
+ if (! ret.contains(flav))
+ ret.add(flav);
+ }
+ }
+ }
+ else
+ {
+ List<DataFlavor> list = nativeToFlavorMap.get(nat);
+ if (list != null)
+ ret.addAll(list);
+ }
+ return ret;
+ }
+
+ public List<String> getNativesForFlavor (DataFlavor flav)
+ {
+ List<String> ret = new ArrayList<String>();
+ if (flav == null)
+ {
+ Collection<List<String>> all = flavorToNativeMap.values();
+ for (List<String> list : all)
+ {
+ for (String nat : list)
+ {
+ if (! ret.contains(nat))
+ ret.add(nat);
+ }
+ }
+ }
+ else
+ {
+ List<String> list = flavorToNativeMap.get(flav);
+ if (list != null)
+ ret.addAll(list);
+ }
+ return ret;
+ }
+
+ /**
+ * Adds a mapping from a single <code>String</code> native to a single
+ * <code>DataFlavor</code>. Unlike <code>getFlavorsForNative</code>, the
+ * mapping will only be established in one direction, and the native will
+ * not be encoded. To establish a two-way mapping, call
+ * <code>addUnencodedNativeForFlavor</code> as well. The new mapping will
+ * be of lower priority than any existing mapping.
+ * This method has no effect if a mapping from the specified
+ * <code>String</code> native to the specified or equal
+ * <code>DataFlavor</code> already exists.
+ *
+ * @param nativeStr the <code>String</code> native key for the mapping
+ * @param flavor the <code>DataFlavor</code> value for the mapping
+ * @throws NullPointerException if nat or flav is <code>null</code>
+ *
+ * @see #addUnencodedNativeForFlavor
+ * @since 1.4
+ */
+ public synchronized void addFlavorForUnencodedNative(String nativeStr,
+ DataFlavor flavor)
+ {
+ if ((nativeStr == null) || (flavor == null))
+ throw new NullPointerException();
+ List<DataFlavor> flavors = nativeToFlavorMap.get(nativeStr);
+ if (flavors == null)
+ {
+ flavors = new ArrayList<DataFlavor>();
+ nativeToFlavorMap.put(nativeStr, flavors);
+ }
+ else
+ {
+ if (! flavors.contains(flavor))
+ flavors.add(flavor);
+ }
+ }
+
+ /**
+ * Adds a mapping from the specified <code>DataFlavor</code> (and all
+ * <code>DataFlavor</code>s equal to the specified <code>DataFlavor</code>)
+ * to the specified <code>String</code> native.
+ * Unlike <code>getNativesForFlavor</code>, the mapping will only be
+ * established in one direction, and the native will not be encoded. To
+ * establish a two-way mapping, call
+ * <code>addFlavorForUnencodedNative</code> as well. The new mapping will
+ * be of lower priority than any existing mapping.
+ * This method has no effect if a mapping from the specified or equal
+ * <code>DataFlavor</code> to the specified <code>String</code> native
+ * already exists.
+ *
+ * @param flavor the <code>DataFlavor</code> key for the mapping
+ * @param nativeStr the <code>String</code> native value for the mapping
+ * @throws NullPointerException if flav or nat is <code>null</code>
+ *
+ * @see #addFlavorForUnencodedNative
+ * @since 1.4
+ */
+ public synchronized void addUnencodedNativeForFlavor(DataFlavor flavor,
+ String nativeStr)
+ {
+ if ((nativeStr == null) || (flavor == null))
+ throw new NullPointerException();
+ List<String> natives = flavorToNativeMap.get(flavor);
+ if (natives == null)
+ {
+ natives = new ArrayList<String>();
+ flavorToNativeMap.put(flavor, natives);
+ }
+ else
+ {
+ if (! natives.contains(nativeStr))
+ natives.add(nativeStr);
+ }
+ }
+
+ /**
+ * Discards the current mappings for the specified <code>DataFlavor</code>
+ * and all <code>DataFlavor</code>s equal to the specified
+ * <code>DataFlavor</code>, and creates new mappings to the
+ * specified <code>String</code> natives.
+ * Unlike <code>getNativesForFlavor</code>, the mappings will only be
+ * established in one direction, and the natives will not be encoded. To
+ * establish two-way mappings, call <code>setFlavorsForNative</code>
+ * as well. The first native in the array will represent the highest
+ * priority mapping. Subsequent natives will represent mappings of
+ * decreasing priority.
+ * <p>
+ * If the array contains several elements that reference equal
+ * <code>String</code> natives, this method will establish new mappings
+ * for the first of those elements and ignore the rest of them.
+ * <p>
+ * It is recommended that client code not reset mappings established by the
+ * data transfer subsystem. This method should only be used for
+ * application-level mappings.
+ *
+ * @param flavor the <code>DataFlavor</code> key for the mappings
+ * @param natives the <code>String</code> native values for the mappings
+ * @throws NullPointerException if flav or natives is <code>null</code>
+ * or if natives contains <code>null</code> elements
+ *
+ * @see #setFlavorsForNative
+ * @since 1.4
+ */
+ public synchronized void setNativesForFlavor(DataFlavor flavor,
+ String[] natives)
+ {
+ if ((natives == null) || (flavor == null))
+ throw new NullPointerException();
+
+ flavorToNativeMap.remove(flavor);
+ for (int i = 0; i < natives.length; i++)
+ {
+ addUnencodedNativeForFlavor(flavor, natives[i]);
+ }
+ }
+
+ /**
+ * Discards the current mappings for the specified <code>String</code>
+ * native, and creates new mappings to the specified
+ * <code>DataFlavor</code>s. Unlike <code>getFlavorsForNative</code>, the
+ * mappings will only be established in one direction, and the natives need
+ * not be encoded. To establish two-way mappings, call
+ * <code>setNativesForFlavor</code> as well. The first
+ * <code>DataFlavor</code> in the array will represent the highest priority
+ * mapping. Subsequent <code>DataFlavor</code>s will represent mappings of
+ * decreasing priority.
+ * <p>
+ * If the array contains several elements that reference equal
+ * <code>DataFlavor</code>s, this method will establish new mappings
+ * for the first of those elements and ignore the rest of them.
+ * <p>
+ * It is recommended that client code not reset mappings established by the
+ * data transfer subsystem. This method should only be used for
+ * application-level mappings.
+ *
+ * @param nativeStr the <code>String</code> native key for the mappings
+ * @param flavors the <code>DataFlavor</code> values for the mappings
+ * @throws NullPointerException if nat or flavors is <code>null</code>
+ * or if flavors contains <code>null</code> elements
+ *
+ * @see #setNativesForFlavor
+ * @since 1.4
+ */
+ public synchronized void setFlavorsForNative(String nativeStr,
+ DataFlavor[] flavors)
+ {
+ if ((nativeStr == null) || (flavors == null))
+ throw new NullPointerException();
+
+ nativeToFlavorMap.remove(nativeStr);
+ for (int i = 0; i < flavors.length; i++)
+ {
+ addFlavorForUnencodedNative(nativeStr, flavors[i]);
+ }
+ }
+
+} // class SystemFlavorMap
diff --git a/libjava/classpath/java/awt/datatransfer/Transferable.java b/libjava/classpath/java/awt/datatransfer/Transferable.java
new file mode 100644
index 000000000..99239fcc6
--- /dev/null
+++ b/libjava/classpath/java/awt/datatransfer/Transferable.java
@@ -0,0 +1,82 @@
+/* Transferable.java -- Data transfer source
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.datatransfer;
+
+import java.io.IOException;
+
+/**
+ * This interface is implemented by classes that can transfer data.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface Transferable
+{
+ /**
+ * This method returns a list of available data flavors for the data being
+ * transferred. The array returned will be sorted from most preferred
+ * flavor at the beginning to least preferred at the end.
+ *
+ * @return adA list of data flavors for this data
+ */
+ DataFlavor[] getTransferDataFlavors();
+
+ /**
+ * Tests whether or not this data can be delivered in the specified data
+ * flavor.
+ *
+ * @param flavor the data flavor to test
+ * @return true if the data flavor is supported
+ */
+ boolean isDataFlavorSupported(DataFlavor flavor);
+
+ /**
+ * Returns the data in the specified <code>DataFlavor</code>.
+ *
+ * @param flavor the data flavor to return
+ * @return the data in the appropriate flavor
+ * @throws UnsupportedFlavorException if the flavor is not supported
+ * @throws IOException if the data is not available
+ * @see DataFlavor#getRepresentationClass
+ */
+ Object getTransferData(DataFlavor flavor)
+ throws UnsupportedFlavorException, IOException;
+
+} // interface Transferable
diff --git a/libjava/classpath/java/awt/datatransfer/UnsupportedFlavorException.java b/libjava/classpath/java/awt/datatransfer/UnsupportedFlavorException.java
new file mode 100644
index 000000000..0ca17b2e9
--- /dev/null
+++ b/libjava/classpath/java/awt/datatransfer/UnsupportedFlavorException.java
@@ -0,0 +1,65 @@
+/* UnsupportedFlavorException.java -- ata flavor is not valid
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.datatransfer;
+
+/**
+ * The data flavor requested is not supported for the transfer data.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see Transferable#getTransferData(DataFlavor)
+ * @status updated to 1.4
+ */
+public class UnsupportedFlavorException extends Exception
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 5383814944251665601L;
+
+ /**
+ * Initializes a new instance of <code>UnsupportedDataFlavor</code>
+ * for the specified data flavor.
+ *
+ * @param flavor the data flavor that is not supported
+ */
+ public UnsupportedFlavorException(DataFlavor flavor)
+ {
+ super(flavor == null ? null : flavor.getHumanPresentableName());
+ }
+} // class UnsupportedFlavorException
diff --git a/libjava/classpath/java/awt/datatransfer/package.html b/libjava/classpath/java/awt/datatransfer/package.html
new file mode 100644
index 000000000..5ab860cdc
--- /dev/null
+++ b/libjava/classpath/java/awt/datatransfer/package.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt.datatransfer package.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - java.awt.datatransfer</title></head>
+
+<body>
+<p>Classes to represent different flavors of data for transferring native
+and system types through for example a clipboard.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/dnd/Autoscroll.java b/libjava/classpath/java/awt/dnd/Autoscroll.java
new file mode 100644
index 000000000..094063ce1
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/Autoscroll.java
@@ -0,0 +1,69 @@
+/* Autoscroll.java --
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import java.awt.Insets;
+import java.awt.Point;
+
+/**
+ * During DnD operations it is possible that a user may wish to drop the
+ * subject of the operation on a region of a scrollable GUI control that
+ * is not currently visible to the user.
+ *
+ * @author Michael Koch (konqueror@gmx.de)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface Autoscroll
+{
+ /**
+ * This method returns the Insets describing the autoscrolling region or
+ * border relative to the geometry of the implementing Component
+ */
+ Insets getAutoscrollInsets ();
+
+ /**
+ * Notify the Component to autoscroll
+ *
+ * @param location A Point indicating the location of the cursor that
+ * triggered this operation
+ */
+ void autoscroll (Point location);
+
+} // interface Autoscroll
diff --git a/libjava/classpath/java/awt/dnd/DnDConstants.java b/libjava/classpath/java/awt/dnd/DnDConstants.java
new file mode 100644
index 000000000..85c9c0528
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DnDConstants.java
@@ -0,0 +1,77 @@
+/* DnDConstants.java -- constants for drag-and-drop operations
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+/**
+ * This class contains various constants used in drag-and-drop operations.
+ * Why it is not an interface is beyond me.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public final class DnDConstants
+{
+ /** No action takes place. */
+ public static final int ACTION_NONE = 0;
+
+ /** The copy action. */
+ public static final int ACTION_COPY = 1;
+
+ /** The move action. */
+ public static final int ACTION_MOVE = 2;
+
+ /** Either a copy or a move. */
+ public static final int ACTION_COPY_OR_MOVE = 3;
+
+ /**
+ * A link action. This does not copy or move, but creates a reference back
+ * to the original. However, since platforms differ on how a reference should
+ * behave, this action is not recommended for common use.
+ */
+ public static final int ACTION_LINK = 1073741824;
+
+ /** A synonym for {@link #ACTION_LINK}. */
+ public static final int ACTION_REFERENCE = ACTION_LINK;
+
+ private DnDConstants()
+ {
+ // Do nothing here.
+ }
+}
diff --git a/libjava/classpath/java/awt/dnd/DnDEventMulticaster.java b/libjava/classpath/java/awt/dnd/DnDEventMulticaster.java
new file mode 100644
index 000000000..30594c2c7
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DnDEventMulticaster.java
@@ -0,0 +1,74 @@
+/* DnDEventMulticaster.java -- helper class for listener chains in java.awt.dnd
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import java.awt.AWTEventMulticaster;
+import java.util.EventListener;
+
+class DnDEventMulticaster extends AWTEventMulticaster
+{
+ protected DnDEventMulticaster (EventListener a, EventListener b)
+ {
+ super (a, b);
+ }
+
+ public static DragSourceListener add (DragSourceListener a,
+ DragSourceListener b)
+ {
+ return (DragSourceListener) addInternal (a, b);
+ }
+
+ public static DragSourceMotionListener add (DragSourceMotionListener a,
+ DragSourceMotionListener b)
+ {
+ return (DragSourceMotionListener) addInternal (a, b);
+ }
+
+ public static DragSourceListener remove (DragSourceListener a,
+ DragSourceListener b)
+ {
+ return (DragSourceListener) removeInternal (a, b);
+ }
+
+ public static DragSourceMotionListener remove (DragSourceMotionListener a,
+ DragSourceMotionListener b)
+ {
+ return (DragSourceMotionListener) removeInternal (a, b);
+ }
+}
diff --git a/libjava/classpath/java/awt/dnd/DragGestureEvent.java b/libjava/classpath/java/awt/dnd/DragGestureEvent.java
new file mode 100644
index 000000000..e127a7dc1
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DragGestureEvent.java
@@ -0,0 +1,219 @@
+/* DragGestureEvent.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.datatransfer.Transferable;
+import java.awt.event.InputEvent;
+import java.util.EventObject;
+import java.util.Iterator;
+import java.util.List;
+
+public class DragGestureEvent extends EventObject
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 9080172649166731306L;
+
+ private DragSource dragSource;
+ private Component component;
+ private final Point origin;
+ private final int action;
+ private List<InputEvent> events;
+ private DragGestureRecognizer dgr;
+
+ /**
+ * Constructs a new DragGestureEvent.
+ * @param dgr - DragGestureRecognizer firing this event
+ * @param action - user's preferred action
+ * @param origin - origin of the drag
+ * @param events - List of events that make up the gesture
+ * @throws IllegalArgumentException - if input parameters are null
+ */
+ public DragGestureEvent(DragGestureRecognizer dgr, int action, Point origin,
+ List<? extends InputEvent> events)
+ {
+ super(dgr);
+ if (origin == null || events == null || dgr == null)
+ throw new IllegalArgumentException();
+
+ this.origin = origin;
+ this.action = action;
+ this.events = (List<InputEvent>) events;
+ this.dgr = dgr;
+ this.component = dgr.getComponent();
+ this.dragSource = dgr.getDragSource();
+ }
+
+ /**
+ * Returns the source casted as a DragGestureRecognizer.
+ *
+ * @return the source casted as a DragGestureRecognizer.
+ */
+ public DragGestureRecognizer getSourceAsDragGestureRecognizer()
+ {
+ return (DragGestureRecognizer) getSource();
+ }
+
+ /**
+ * Returns the Component corresponding to this.
+ *
+ * @return the Component corresponding to this.
+ */
+ public Component getComponent()
+ {
+ return component;
+ }
+
+ /**
+ * Gets the DragSource corresponding to this.
+ *
+ * @return the DragSource corresponding to this.
+ */
+ public DragSource getDragSource()
+ {
+ return dragSource;
+ }
+
+ /**
+ * Returns the origin of the drag.
+ *
+ * @return the origin of the drag.
+ */
+ public Point getDragOrigin()
+ {
+ return origin;
+ }
+
+ /**
+ * Gets an iterator representation of the List of events.
+ *
+ * @return an iterator representation of the List of events.
+ */
+ public Iterator<InputEvent> iterator()
+ {
+ return events.iterator();
+ }
+
+ /**
+ * Gets an array representation of the List of events.
+ *
+ * @return an array representation of the List of events.
+ */
+ public Object[] toArray()
+ {
+ return events.toArray();
+ }
+
+ /**
+ * Gets an array representation of the List of events.
+ *
+ * @param array - the array to store the events in.
+ * @return an array representation of the List of events.
+ */
+ public Object[] toArray(Object[] array)
+ {
+ return events.toArray(array);
+ }
+
+ /**
+ * Gets the user's preferred action.
+ *
+ * @return the user's preferred action.
+ */
+ public int getDragAction()
+ {
+ return action;
+ }
+
+ /**
+ * Get the event that triggered this gesture.
+ *
+ * @return the event that triggered this gesture.
+ */
+ public InputEvent getTriggerEvent()
+ {
+ return dgr.getTriggerEvent();
+ }
+
+ /**
+ * Starts the drag given the initial Cursor to display, the Transferable
+ * object, and the DragSourceListener to use.
+ *
+ * @exception InvalidDnDOperationException If the Drag and Drop system is
+ * unable to initiate a drag operation, or if the user attempts to start
+ * a drag while an existing drag operation is still executing.
+ */
+ public void startDrag(Cursor dragCursor, Transferable trans)
+ {
+ startDrag(dragCursor, null, null, trans, null);
+ }
+
+ /**
+ * Starts the drag given the initial Cursor to display, the Transferable
+ * object, and the DragSourceListener to use.
+ *
+ * @exception InvalidDnDOperationException If the Drag and Drop system is
+ * unable to initiate a drag operation, or if the user attempts to start
+ * a drag while an existing drag operation is still executing.
+ */
+ public void startDrag(Cursor dragCursor, Transferable trans,
+ DragSourceListener l)
+ {
+ startDrag(dragCursor, null, null, trans, l);
+ }
+
+ /**
+ * Starts the drag given the initial Cursor to display, the Transferable
+ * object, and the DragSourceListener to use.
+ *
+ * @exception InvalidDnDOperationException If the Drag and Drop system is
+ * unable to initiate a drag operation, or if the user attempts to start
+ * a drag while an existing drag operation is still executing.
+ */
+ public void startDrag(Cursor dragCursor, Image dragImage, Point imageOffset,
+ Transferable trans, DragSourceListener l)
+ {
+ dragSource.startDrag(this, dragCursor, dragImage, imageOffset, trans, l);
+ }
+} // class DragGestureEvent
diff --git a/libjava/classpath/java/awt/dnd/DragGestureListener.java b/libjava/classpath/java/awt/dnd/DragGestureListener.java
new file mode 100644
index 000000000..e8befe80f
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DragGestureListener.java
@@ -0,0 +1,63 @@
+/* DragGestureListener.java --
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import java.util.EventListener;
+
+/**
+ * This is a listener for starting a drag-and-drop gesture. Upon receiving
+ * notification, the implementor then starts the drag operation.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see DragGestureRecognizer
+ * @see DragGestureEvent
+ * @see DragSource
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface DragGestureListener extends EventListener
+{
+ /**
+ * Called when the native platform notifies the virtual machine that a
+ * drag-and-drop has been initiated.
+ *
+ * @param e the event
+ */
+ void dragGestureRecognized(DragGestureEvent e);
+} // interface DragGestureListener
diff --git a/libjava/classpath/java/awt/dnd/DragGestureRecognizer.java b/libjava/classpath/java/awt/dnd/DragGestureRecognizer.java
new file mode 100644
index 000000000..c41402ca7
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DragGestureRecognizer.java
@@ -0,0 +1,191 @@
+/* DragGestureRecognizer.java --
+ Copyright (C) 2002, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import java.awt.Component;
+import java.awt.Point;
+import java.awt.event.InputEvent;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.TooManyListenersException;
+
+/**
+ * STUBBED
+ * @author Michael Koch (konqueror@gmx.de)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.2
+ */
+public abstract class DragGestureRecognizer implements Serializable
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 8996673345831063337L;
+
+ protected DragSource dragSource;
+ protected Component component;
+ protected transient DragGestureListener dragGestureListener;
+ protected int sourceActions;
+ protected ArrayList<InputEvent> events = new ArrayList<InputEvent>();
+
+ protected DragGestureRecognizer(DragSource ds, Component c, int sa,
+ DragGestureListener dgl)
+ {
+ if (ds == null)
+ throw new IllegalArgumentException();
+ dragSource = ds;
+ component = c;
+ sourceActions = sa;
+ dragGestureListener = dgl;
+ }
+
+ protected DragGestureRecognizer(DragSource ds, Component c, int sa)
+ {
+ this(ds, c, sa, null);
+ }
+
+ protected DragGestureRecognizer(DragSource ds, Component c)
+ {
+ this(ds, c, 0, null);
+ }
+
+ protected DragGestureRecognizer(DragSource ds)
+ {
+ this(ds, null, 0, null);
+ }
+
+ protected abstract void registerListeners();
+
+ protected abstract void unregisterListeners();
+
+ public DragSource getDragSource()
+ {
+ return dragSource;
+ }
+
+ public Component getComponent()
+ {
+ return component;
+ }
+
+ public void setComponent(Component c)
+ {
+ component = c;
+ }
+
+ public int getSourceActions()
+ {
+ return sourceActions;
+ }
+
+ public void setSourceActions(int sa)
+ {
+ sourceActions = sa;
+ }
+
+ public InputEvent getTriggerEvent()
+ {
+ return events.size() > 0 ? events.get(0) : null;
+ }
+
+ /**
+ * Resets the recognizer. If a gesture is currently recognize, discard it.
+ */
+ public void resetRecognizer()
+ {
+ events.clear();
+ }
+
+ /**
+ * Register a new DragGestureListener.
+ *
+ * @exception TooManyListenersException If a DragGestureListener has already
+ * been added.
+ */
+ public void addDragGestureListener(DragGestureListener dgl)
+ throws TooManyListenersException
+ {
+ if (dragGestureListener != null)
+ throw new TooManyListenersException();
+ dragGestureListener = dgl;
+ }
+
+ public void removeDragGestureListener(DragGestureListener dgl)
+ {
+ if (dragGestureListener != dgl)
+ throw new IllegalArgumentException();
+ dragGestureListener = null;
+ }
+
+ /**
+ * Fires a <code>DragGestureEvent</code> to the DragGestureListener
+ * associated with this object, if there is one.
+ */
+ protected void fireDragGestureRecognized(int dragAction, Point p)
+ {
+ if(dragGestureListener != null)
+ dragGestureListener.dragGestureRecognized
+ (new DragGestureEvent(this, dragAction, p, events));
+ resetRecognizer();
+ }
+
+ protected void appendEvent(InputEvent e)
+ {
+ if (e == null)
+ return;
+ events.add(e);
+ }
+
+ private void readObject(ObjectInputStream s)
+ throws ClassNotFoundException, IOException
+ {
+ s.defaultReadObject();
+ dragGestureListener = (DragGestureListener) s.readObject();
+ }
+
+ private void writeObject(ObjectOutputStream s) throws IOException
+ {
+ s.defaultWriteObject();
+ s.writeObject(dragGestureListener instanceof Serializable
+ ? dragGestureListener : null);
+ }
+} // class DragGestureRecognizer
diff --git a/libjava/classpath/java/awt/dnd/DragSource.java b/libjava/classpath/java/awt/dnd/DragSource.java
new file mode 100644
index 000000000..af8b37668
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DragSource.java
@@ -0,0 +1,326 @@
+/* DragSource.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import gnu.classpath.NotImplementedException;
+
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.GraphicsEnvironment;
+import java.awt.HeadlessException;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Toolkit;
+import java.awt.datatransfer.FlavorMap;
+import java.awt.datatransfer.SystemFlavorMap;
+import java.awt.datatransfer.Transferable;
+import java.awt.dnd.peer.DragSourceContextPeer;
+import java.io.Serializable;
+import java.util.EventListener;
+
+/**
+ * @since 1.2
+ */
+public class DragSource implements Serializable
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 6236096958971414066L;
+
+ public static final Cursor DefaultCopyDrop = null;
+ public static final Cursor DefaultMoveDrop = null;
+ public static final Cursor DefaultLinkDrop = null;
+ public static final Cursor DefaultCopyNoDrop = null;
+ public static final Cursor DefaultMoveNoDrop = null;
+ public static final Cursor DefaultLinkNoDrop = null;
+
+ private transient FlavorMap flavorMap = SystemFlavorMap.getDefaultFlavorMap ();
+ private transient DragSourceListener dragSourceListener;
+ private transient DragSourceMotionListener dragSourceMotionListener;
+
+ private static DragSource ds;
+ private DragSourceContextPeer peer;
+ private DragSourceContext context;
+
+ /**
+ * Initializes the drag source.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public DragSource()
+ {
+ if (GraphicsEnvironment.isHeadless())
+ {
+ ds = null;
+ throw new HeadlessException();
+ }
+ }
+
+ /**
+ * Gets the default drag source.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public static DragSource getDefaultDragSource()
+ {
+ if (GraphicsEnvironment.isHeadless())
+ {
+ ds = null;
+ throw new HeadlessException();
+ }
+
+ if (ds == null)
+ ds = new DragSource();
+ return ds;
+ }
+
+ public static boolean isDragImageSupported()
+ {
+ // In all cases, Sun returns false here.
+ return false;
+ }
+
+ /**
+ * Start a drag, given the DragGestureEvent that initiated the drag.
+ *
+ * @exception InvalidDnDOperationException If the Drag and Drop system is
+ * unable to initiate a drag operation, or if the user attempts to start
+ * a drag while an existing drag operation is still executing.
+ */
+ public void startDrag(DragGestureEvent trigger, Cursor dragCursor,
+ Image dragImage, Point imageOffset,
+ Transferable trans, DragSourceListener dsl,
+ FlavorMap map)
+ {
+ // http://www.javaworld.com/javaworld/jw-03-1999/jw-03-dragndrop.html
+
+ // This function creates a DragSourceContext object. This object tracks the
+ // state of the operation by listening to a native peer. In this situation,
+ // the DragSource may be obtained from the event or by an instance variable.
+ // This function also creates a new DragSourceContextPeer.
+
+ // This function sends the same message to the context, which then forwards
+ // it to the peer, passing itself as a parameter. Now, the native system has
+ // access to the Transferable through the context.
+
+ try
+ {
+ flavorMap = map;
+
+ if (peer == null)
+ peer = Toolkit.getDefaultToolkit().createDragSourceContextPeer(trigger);
+
+ if (context == null)
+ context = createDragSourceContext(peer, trigger,
+ dragCursor,
+ dragImage,
+ imageOffset, trans,
+ dsl);
+
+ if (peer == null)
+ throw new InvalidDnDOperationException();
+
+ peer.startDrag(context, dragCursor, dragImage, imageOffset);
+ }
+ catch (Exception e)
+ {
+ throw new InvalidDnDOperationException("Drag and Drop system is "
+ + "unable to initiate a drag operation.");
+ }
+ }
+
+ /**
+ * Start a drag, given the DragGestureEvent that initiated the drag.
+ *
+ * @exception InvalidDnDOperationException If the Drag and Drop system is
+ * unable to initiate a drag operation, or if the user attempts to start
+ * a drag while an existing drag operation is still executing.
+ */
+ public void startDrag(DragGestureEvent trigger, Cursor dragCursor,
+ Transferable trans, DragSourceListener dsl,
+ FlavorMap map)
+ {
+ startDrag(trigger, dragCursor, null, null, trans, dsl, map);
+ }
+
+ /**
+ * Start a drag, given the DragGestureEvent that initiated the drag.
+ *
+ * @exception InvalidDnDOperationException If the Drag and Drop system is
+ * unable to initiate a drag operation, or if the user attempts to start
+ * a drag while an existing drag operation is still executing.
+ */
+ public void startDrag(DragGestureEvent trigger, Cursor dragCursor,
+ Image dragImage, Point imageOffset,
+ Transferable trans, DragSourceListener dsl)
+ {
+ startDrag(trigger, dragCursor, dragImage, imageOffset, trans, dsl, null);
+ }
+
+ /**
+ * Start a drag, given the DragGestureEvent that initiated the drag.
+ *
+ * @exception InvalidDnDOperationException If the Drag and Drop system is
+ * unable to initiate a drag operation, or if the user attempts to start
+ * a drag while an existing drag operation is still executing.
+ */
+ public void startDrag(DragGestureEvent trigger, Cursor dragCursor,
+ Transferable trans, DragSourceListener dsl)
+ {
+ startDrag(trigger, dragCursor, null, null, trans, dsl, null);
+ }
+
+ /**
+ * Creates the DragSourceContext to handle this drag.
+ *
+ * @exception IllegalArgumentException
+ * @exception NullPointerException If dscp, dgl, dragImage or t is null.
+ */
+ protected DragSourceContext
+ createDragSourceContext(DragSourceContextPeer peer, DragGestureEvent dge,
+ Cursor cursor, Image image, Point offset,
+ Transferable t, DragSourceListener dsl)
+ {
+ return new DragSourceContext(peer, dge, cursor, image, offset, t, dsl);
+ }
+
+ public FlavorMap getFlavorMap()
+ {
+ return flavorMap;
+ }
+
+ public <T extends DragGestureRecognizer> T
+ createDragGestureRecognizer(Class<T> recognizer,
+ Component c,
+ int actions,
+ DragGestureListener dgl)
+ {
+ return (T) Toolkit.getDefaultToolkit().createDragGestureRecognizer(recognizer,
+ this, c,
+ actions, dgl);
+ }
+
+ public DragGestureRecognizer createDefaultDragGestureRecognizer(Component c,
+ int actions,
+ DragGestureListener dgl)
+ {
+ return createDragGestureRecognizer(MouseDragGestureRecognizer.class, c,
+ actions, dgl);
+ }
+
+ /**
+ * @since 1.4
+ */
+ public void addDragSourceListener(DragSourceListener l)
+ {
+ DnDEventMulticaster.add (dragSourceListener, l);
+ }
+
+ /**
+ * @since 1.4
+ */
+ public void removeDragSourceListener(DragSourceListener l)
+ {
+ DnDEventMulticaster.remove (dragSourceListener, l);
+ }
+
+ /**
+ * @since 1.4
+ */
+ public DragSourceListener[] getDragSourceListeners()
+ {
+ return (DragSourceListener[]) getListeners (DragSourceListener.class);
+ }
+
+ /**
+ * @since 1.4
+ */
+ public void addDragSourceMotionListener(DragSourceMotionListener l)
+ {
+ DnDEventMulticaster.add (dragSourceMotionListener, l);
+ }
+
+ /**
+ * @since 1.4
+ */
+ public void removeDragSourceMotionListener(DragSourceMotionListener l)
+ {
+ DnDEventMulticaster.remove (dragSourceMotionListener, l);
+ }
+
+ /**
+ * @since 1.4
+ */
+ public DragSourceMotionListener[] getDragSourceMotionListeners ()
+ {
+ return (DragSourceMotionListener[]) getListeners
+ (DragSourceMotionListener.class);
+ }
+
+ /**
+ * @since 1.4
+ */
+ public <T extends EventListener> T[] getListeners (Class<T> listenerType)
+ {
+ if (listenerType == DragSourceListener.class)
+ return DnDEventMulticaster.getListeners (dragSourceListener,
+ listenerType);
+
+ if (listenerType == DragSourceMotionListener.class)
+ return DnDEventMulticaster.getListeners (dragSourceMotionListener,
+ listenerType);
+
+ // Return an empty EventListener array.
+ return (T[]) new EventListener [0];
+ }
+
+ /**
+ * TODO
+ * @return TODO
+ *
+ * @since 1.5
+ */
+ public static int getDragThreshold()
+ throws NotImplementedException
+ {
+ // FIXME: Not implemented.
+ return 8;
+ }
+} // class DragSource
diff --git a/libjava/classpath/java/awt/dnd/DragSourceAdapter.java b/libjava/classpath/java/awt/dnd/DragSourceAdapter.java
new file mode 100644
index 000000000..90d9a6983
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DragSourceAdapter.java
@@ -0,0 +1,126 @@
+/* DragSourceAdapter.java -- drag-and-drop listener adapter
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+/**
+ * This class implements <code>DragSourceListener</code> and
+ * <code>DragSourceMotionListener</code>, and implements all methods
+ * with empty bodies. This allows a listener interested in implementing only
+ * a subset of these interfaces to extend this class and override only the
+ * desired methods.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see DragSourceEvent
+ * @see DragSourceListener
+ * @see DragSourceMotionListener
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public abstract class DragSourceAdapter
+ implements DragSourceListener, DragSourceMotionListener
+{
+ /**
+ * Default constructor.
+ */
+ public DragSourceAdapter()
+ {
+ }
+
+ /**
+ * Called when the cursor hotspot enters a drop site which will accept the
+ * drag.
+ *
+ * @param e the event
+ */
+ public void dragEnter(DragSourceDragEvent e)
+ {
+ }
+
+ /**
+ * Called when the cursor hotspot moves inside of a drop site which will
+ * accept the drag.
+ *
+ * @param e the event
+ */
+ public void dragOver(DragSourceDragEvent e)
+ {
+ }
+
+ /**
+ * Called whenever the mouse is moved during a drag-and-drop operation.
+ *
+ * @param e the event
+ */
+ public void dragMouseMoved(DragSourceDragEvent e)
+ {
+ }
+
+ /**
+ * Called when the user modifies the drop gesture. This is often the case
+ * when additional mouse or key events are received during the drag.
+ *
+ * @param e the event
+ */
+ public void dropActionChanged(DragSourceDragEvent e)
+ {
+ }
+
+ /**
+ * Called when the cursor hotspot moves outside of a drop site which will
+ * accept the drag. This could also happen if the drop site is no longer
+ * active, or no longer accepts the drag.
+ *
+ * @param e the event
+ */
+ public void dragExit(DragSourceEvent e)
+ {
+ }
+
+ /**
+ * Called when the drag and drop operation is complete. After this event,
+ * <code>getDropSuccess</code> of the event is valid, and
+ * <code>getDropAction</code> holds the action requested by the drop site.
+ * Furthermore, the <code>DragSourceContext</code> is invalidated.
+ *
+ * @param e the event
+ */
+ public void dragDropEnd(DragSourceDropEvent e)
+ {
+ }
+} // class DragSourceAdapter
diff --git a/libjava/classpath/java/awt/dnd/DragSourceContext.java b/libjava/classpath/java/awt/dnd/DragSourceContext.java
new file mode 100644
index 000000000..e21b4fdae
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DragSourceContext.java
@@ -0,0 +1,383 @@
+/* DragSourceContext.java --
+ Copyright (C) 2002 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.datatransfer.Transferable;
+import java.awt.dnd.peer.DragSourceContextPeer;
+import java.io.Serializable;
+import java.util.TooManyListenersException;
+
+/**
+ * @since 1.2
+ */
+public class DragSourceContext
+ implements DragSourceListener, DragSourceMotionListener, Serializable
+{
+ /**
+ * Compatible with JDK 1.2+
+ */
+ static final long serialVersionUID = -115407898692194719L;
+
+ protected static final int DEFAULT = 0;
+ protected static final int ENTER = 1;
+ protected static final int OVER = 2;
+ protected static final int CHANGED = 3;
+
+ private DragSourceContextPeer peer;
+ private Cursor cursor;
+ private Transferable transferable;
+ private DragGestureEvent trigger;
+ private DragSourceListener dragSourceListener;
+ private boolean useCustomCursor;
+ private int sourceActions;
+ private Image image;
+ private Point offset;
+
+ /**
+ * Initializes a drag source context.
+ *
+ * @exception IllegalArgumentException If Component or DragSource of trigger
+ * are null, the drag action for the trigger event is DnDConstants.ACTION_NONE
+ * or if the source actions for the DragGestureRecognizer associated with the
+ * trigger event are equal to DnDConstants.ACTION_NONE.
+ * @exception NullPointerException If peer, trans or trigger is null or if the
+ * image is not null but the offset is.
+ */
+ public DragSourceContext (DragSourceContextPeer peer,
+ DragGestureEvent trigger, Cursor cursor,
+ Image image, Point offset, Transferable trans,
+ DragSourceListener dsl)
+ {
+ if (peer == null
+ || trigger == null || trans == null
+ || (image != null && offset == null))
+ throw new NullPointerException ();
+
+ if (trigger.getComponent () == null
+ || trigger.getDragSource () == null
+ || trigger.getDragAction () == DnDConstants.ACTION_NONE
+ || trigger.getSourceAsDragGestureRecognizer ()
+ .getSourceActions () == DnDConstants.ACTION_NONE)
+ throw new IllegalArgumentException ();
+
+ this.peer = peer;
+ this.trigger = trigger;
+ this.cursor = cursor;
+ this.image = image;
+ this.offset = offset;
+ this.transferable = trans;
+ this.dragSourceListener = dsl;
+ this.sourceActions = trigger.getSourceAsDragGestureRecognizer().getSourceActions();
+
+ setCursor(cursor);
+ updateCurrentCursor(trigger.getDragAction(), sourceActions, DEFAULT);
+ }
+
+ /**
+ * Returns the DragSource object associated with the
+ * DragGestureEvent.
+ *
+ * @return the DragSource associated with the trigger.
+ */
+ public DragSource getDragSource()
+ {
+ return trigger.getDragSource ();
+ }
+
+ /**
+ * Returns the component associated with this.
+ *
+ * @return the component associated with the trigger.
+ */
+ public Component getComponent()
+ {
+ return trigger.getComponent ();
+ }
+
+ /**
+ * Gets the trigger associated with this.
+ *
+ * @return the trigger.
+ */
+ public DragGestureEvent getTrigger()
+ {
+ return trigger;
+ }
+
+ /**
+ * Returns the source actions for the DragGestureRecognizer.
+ *
+ * @return the source actions for DragGestureRecognizer.
+ */
+ public int getSourceActions()
+ {
+ if (sourceActions == 0)
+ sourceActions = trigger.getSourceAsDragGestureRecognizer().getSourceActions();
+ return sourceActions;
+ }
+
+ /**
+ * Sets the cursor for this drag operation to the specified cursor.
+ *
+ * @param cursor c - the Cursor to use, or null to use the default drag
+ * cursor.
+ */
+ public void setCursor(Cursor cursor)
+ {
+ if (cursor == null)
+ useCustomCursor = false;
+ else
+ useCustomCursor = true;
+ this.cursor = cursor;
+ peer.setCursor(cursor);
+ }
+
+ /**
+ * Returns the current cursor or null if the default
+ * drag cursor is used.
+ *
+ * @return the current cursor or null.
+ */
+ public Cursor getCursor()
+ {
+ return cursor;
+ }
+
+ /**
+ * Adds a <code>DragSourceListener</code>.
+ *
+ * @exception TooManyListenersException If a <code>DragSourceListener</code>
+ * has already been added.
+ */
+ public void addDragSourceListener (DragSourceListener dsl)
+ throws TooManyListenersException
+ {
+ if (dragSourceListener != null)
+ throw new TooManyListenersException ();
+
+ dragSourceListener = dsl;
+ }
+
+ public void removeDragSourceListener (DragSourceListener dsl)
+ {
+ if (dragSourceListener == dsl)
+ dragSourceListener = null;
+ }
+
+ /**
+ * This function tells the peer that the DataFlavors have been modified.
+ */
+ public void transferablesFlavorsChanged()
+ {
+ peer.transferablesFlavorsChanged();
+ }
+
+ /**
+ * Calls dragEnter on the listeners registered with this
+ * and with the DragSource.
+ *
+ * @param e - the DragSourceDragEvent
+ */
+ public void dragEnter(DragSourceDragEvent e)
+ {
+ if (dragSourceListener != null)
+ dragSourceListener.dragEnter(e);
+
+ DragSource ds = getDragSource();
+ DragSourceListener[] dsl = ds.getDragSourceListeners();
+ for (int i = 0; i < dsl.length; i++)
+ dsl[i].dragEnter(e);
+
+ updateCurrentCursor(e.getDropAction(), e.getTargetActions(), ENTER);
+ }
+
+ /**
+ * Calls dragOver on the listeners registered with this
+ * and with the DragSource.
+ *
+ * @param e - the DragSourceDragEvent
+ */
+ public void dragOver(DragSourceDragEvent e)
+ {
+ if (dragSourceListener != null)
+ dragSourceListener.dragOver(e);
+
+ DragSource ds = getDragSource();
+ DragSourceListener[] dsl = ds.getDragSourceListeners();
+ for (int i = 0; i < dsl.length; i++)
+ dsl[i].dragOver(e);
+
+ updateCurrentCursor(e.getDropAction(), e.getTargetActions(), OVER);
+ }
+
+ /**
+ * Calls dragExit on the listeners registered with this
+ * and with the DragSource.
+ *
+ * @param e - the DragSourceEvent
+ */
+ public void dragExit(DragSourceEvent e)
+ {
+ if (dragSourceListener != null)
+ dragSourceListener.dragExit(e);
+
+ DragSource ds = getDragSource();
+ DragSourceListener[] dsl = ds.getDragSourceListeners();
+ for (int i = 0; i < dsl.length; i++)
+ dsl[i].dragExit(e);
+
+ updateCurrentCursor(DnDConstants.ACTION_NONE, DnDConstants.ACTION_NONE,
+ DEFAULT);
+ }
+
+ /**
+ * Calls dropActionChanged on the listeners registered with this
+ * and with the DragSource.
+ *
+ * @param e - the DragSourceDragEvent
+ */
+ public void dropActionChanged(DragSourceDragEvent e)
+ {
+ if (dragSourceListener != null)
+ dragSourceListener.dropActionChanged(e);
+
+ DragSource ds = getDragSource();
+ DragSourceListener[] dsl = ds.getDragSourceListeners();
+ for (int i = 0; i < dsl.length; i++)
+ dsl[i].dropActionChanged(e);
+
+ updateCurrentCursor(e.getDropAction(), e.getTargetActions(), CHANGED);
+ }
+
+ /**
+ * Calls dragDropEnd on the listeners registered with this
+ * and with the DragSource.
+ *
+ * @param e - the DragSourceDropEvent
+ */
+ public void dragDropEnd(DragSourceDropEvent e)
+ {
+ if (dragSourceListener != null)
+ dragSourceListener.dragDropEnd(e);
+
+ DragSource ds = getDragSource();
+ DragSourceListener[] dsl = ds.getDragSourceListeners();
+ for (int i = 0; i < dsl.length; i++)
+ dsl[i].dragDropEnd(e);
+ }
+
+ /**
+ * Calls dragMouseMoved on the listeners registered with the DragSource.
+ *
+ * @param e - the DragSourceDragEvent
+ */
+ public void dragMouseMoved(DragSourceDragEvent e)
+ {
+ DragSource ds = getDragSource();
+ DragSourceMotionListener[] dsml = ds.getDragSourceMotionListeners();
+ for (int i = 0; i < dsml.length; i++)
+ dsml[i].dragMouseMoved(e);
+ }
+
+ /**
+ * Returns the Transferable set with this object.
+ *
+ * @return the transferable.
+ */
+ public Transferable getTransferable()
+ {
+ return transferable;
+ }
+
+ /**
+ * This function sets the drag cursor for the specified operation, actions and
+ * status if the default drag cursor is active. Otherwise, the cursor is not
+ * updated in any way.
+ *
+ * @param dropOp - the current operation.
+ * @param targetAct - the supported actions.
+ * @param status - the status of the cursor (constant).
+ */
+ protected void updateCurrentCursor(int dropOp, int targetAct, int status)
+ {
+ if (! useCustomCursor)
+ {
+ Cursor newCursor = null;
+ switch (status)
+ {
+ default:
+ targetAct = DnDConstants.ACTION_NONE;
+ case ENTER:
+ case CHANGED:
+ case OVER:
+ int action = dropOp & targetAct;
+ if (action == DnDConstants.ACTION_NONE)
+ {
+ if ((dropOp & DnDConstants.ACTION_LINK) != 0)
+ newCursor = DragSource.DefaultLinkNoDrop;
+ else if ((dropOp & DnDConstants.ACTION_MOVE) != 0)
+ newCursor = DragSource.DefaultMoveNoDrop;
+ else
+ newCursor = DragSource.DefaultCopyNoDrop;
+ }
+ else
+ {
+ if ((dropOp & DnDConstants.ACTION_LINK) != 0)
+ newCursor = DragSource.DefaultLinkDrop;
+ else if ((dropOp & DnDConstants.ACTION_MOVE) != 0)
+ newCursor = DragSource.DefaultMoveDrop;
+ else
+ newCursor = DragSource.DefaultCopyDrop;
+ }
+ }
+
+ if (cursor == null || ! cursor.equals(newCursor))
+ {
+ cursor = newCursor;
+ DragSourceContextPeer p = peer;
+ if (p != null)
+ p.setCursor(cursor);
+ }
+ }
+ }
+} // class DragSourceContext
diff --git a/libjava/classpath/java/awt/dnd/DragSourceDragEvent.java b/libjava/classpath/java/awt/dnd/DragSourceDragEvent.java
new file mode 100644
index 000000000..511700b61
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DragSourceDragEvent.java
@@ -0,0 +1,102 @@
+/* DragSourceDragEvent.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import gnu.java.awt.EventModifier;
+
+/**
+ * @author Michael Koch
+ * @since 1.2
+ */
+public class DragSourceDragEvent extends DragSourceEvent
+{
+ /**
+ * Compatible with JDK 1.2+
+ */
+ private static final long serialVersionUID = 481346297933902471L;
+
+ private final int dropAction;
+ private final int targetActions;
+ private final int gestureModifiers;
+
+ public DragSourceDragEvent(DragSourceContext context, int dropAction,
+ int actions, int modifiers)
+ {
+ super(context);
+ this.dropAction = dropAction;
+ targetActions = actions;
+ gestureModifiers = EventModifier.extend(modifiers);
+ }
+
+ public DragSourceDragEvent(DragSourceContext context, int dropAction,
+ int actions, int modifiers, int x, int y)
+ {
+ super(context, x, y);
+ this.dropAction = dropAction;
+ targetActions = actions;
+ gestureModifiers = EventModifier.extend(modifiers);
+ }
+
+ public int getTargetActions()
+ {
+ return targetActions;
+ }
+
+ public int getGestureModifiers()
+ {
+ return EventModifier.revert(gestureModifiers);
+ }
+
+ public int getGestureModifiersEx()
+ {
+ return gestureModifiers;
+ }
+
+ public int getUserAction()
+ {
+ return dropAction;
+ }
+
+ public int getDropAction()
+ {
+ return (dropAction
+ & targetActions
+ & ((DragSourceContext) source).getSourceActions());
+ }
+} // class DragSourceDragEvent
diff --git a/libjava/classpath/java/awt/dnd/DragSourceDropEvent.java b/libjava/classpath/java/awt/dnd/DragSourceDropEvent.java
new file mode 100644
index 000000000..4df984994
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DragSourceDropEvent.java
@@ -0,0 +1,89 @@
+/* DragSourceDragEvent.java --
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.dnd;
+
+/**
+ * @author Michael Koch (konqueror@gmx.de)
+ * @since 1.2
+ *
+ * Written using JDK 1.4.1 Online API
+ * Status: JDK 1.4 complete
+ */
+public class DragSourceDropEvent extends DragSourceEvent
+{
+ /**
+ * Compatible with JDK 1.2+
+ */
+ private static final long serialVersionUID = -5571321229470821891L;
+
+ private final int dropAction;
+ private final boolean dropSuccess;
+
+ public DragSourceDropEvent (DragSourceContext context)
+ {
+ super (context);
+ this.dropAction = 0;
+ this.dropSuccess = false;
+ }
+
+ public DragSourceDropEvent (DragSourceContext context, int dropAction,
+ boolean dropSuccess)
+ {
+ super (context);
+ this.dropAction = dropAction;
+ this.dropSuccess = dropSuccess;
+ }
+
+ public DragSourceDropEvent (DragSourceContext context, int dropAction,
+ boolean dropSuccess, int x, int y)
+ {
+ super (context, x, y);
+ this.dropAction = dropAction;
+ this.dropSuccess = dropSuccess;
+ }
+
+ public int getDropAction()
+ {
+ return dropAction & ((DragSourceContext) source).getSourceActions();
+ }
+
+ public boolean getDropSuccess()
+ {
+ return dropSuccess;
+ }
+} // class DragSourceDropEvent
diff --git a/libjava/classpath/java/awt/dnd/DragSourceEvent.java b/libjava/classpath/java/awt/dnd/DragSourceEvent.java
new file mode 100644
index 000000000..c9e18d712
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DragSourceEvent.java
@@ -0,0 +1,93 @@
+/* DragSourceEvent.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import java.awt.Point;
+import java.util.EventObject;
+
+/**
+ * @since 1.2
+ */
+public class DragSourceEvent extends EventObject
+{
+ /**
+ * Compatible with JDK 1.2+
+ */
+ private static final long serialVersionUID = -763287114604032641L;
+
+ private final boolean locationSpecified;
+ private final int x;
+ private final int y;
+
+ public DragSourceEvent(DragSourceContext context)
+ {
+ super(context);
+ locationSpecified = false;
+ x = 0;
+ y = 0;
+ }
+
+ public DragSourceEvent(DragSourceContext context, int x, int y)
+ {
+ super(context);
+ locationSpecified = true;
+ this.x = x;
+ this.y = y;
+ }
+
+ public DragSourceContext getDragSourceContext()
+ {
+ return (DragSourceContext) source;
+ }
+
+ public Point getLocation()
+ {
+ return locationSpecified ? new Point(x, y) : null;
+ }
+
+ public int getX()
+ {
+ return x;
+ }
+
+ public int getY()
+ {
+ return y;
+ }
+} // class DragSourceEvent
diff --git a/libjava/classpath/java/awt/dnd/DragSourceListener.java b/libjava/classpath/java/awt/dnd/DragSourceListener.java
new file mode 100644
index 000000000..aac6e94eb
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DragSourceListener.java
@@ -0,0 +1,97 @@
+/* DragSourceListener.java -- listen to events during the drag
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import java.util.EventListener;
+
+/**
+ * This class allows an object to listen for drag and drop events. It can
+ * be used to provide appropriate feedback for "drag over" actions. You can
+ * also use a <code>DragSourceAdapter</code> to filter the events you are
+ * interested in.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface DragSourceListener extends EventListener
+{
+ /**
+ * Called when the cursor hotspot enters a drop site which will accept the
+ * drag.
+ *
+ * @param e the drag source drag event
+ */
+ void dragEnter(DragSourceDragEvent e);
+
+ /**
+ * Called when the cursor hotspot moves inside of a drop site which will
+ * accept the drag.
+ *
+ * @param e the drag source drag event
+ */
+ void dragOver(DragSourceDragEvent e);
+
+ /**
+ * Called when the user modifies the drop gesture. This is often the case
+ * when additional mouse or key events are received during the drag.
+ *
+ * @param e the drag source drag event
+ */
+ void dropActionChanged(DragSourceDragEvent e);
+
+ /**
+ * Called when the cursor hotspot moves outside of a drop site which will
+ * accept the drag. This could also happen if the drop site is no longer
+ * active, or no longer accepts the drag.
+ *
+ * @param e the drag source drag event
+ */
+ void dragExit(DragSourceEvent e);
+
+ /**
+ * Called when the drag and drop operation is complete. After this event,
+ * <code>getDropSuccess</code> of the event is valid, and
+ * <code>getDropAction</code> holds the action requested by the drop site.
+ * Furthermore, the <code>DragSourceContext</code> is invalidated.
+ *
+ * @param e the drag source drag event
+ */
+ void dragDropEnd(DragSourceDropEvent e);
+} // interface DragSourceListener
diff --git a/libjava/classpath/java/awt/dnd/DragSourceMotionListener.java b/libjava/classpath/java/awt/dnd/DragSourceMotionListener.java
new file mode 100644
index 000000000..5d04c2271
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DragSourceMotionListener.java
@@ -0,0 +1,64 @@
+/* DragSourceMotionListener.java -- tracks motion in the drag source
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import java.util.EventListener;
+
+/**
+ * This is a listener for mouse motion in the drag source before the drop
+ * event occurs. You can also use a <code>DragSourceAdapter</code> to filter
+ * the events you are interested in.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see DragSourceDragEvent
+ * @see DragSource
+ * @see DragSourceListener
+ * @see DragSourceAdapter
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public interface DragSourceMotionListener extends EventListener
+{
+ /**
+ * Called whenever the mouse is moved during a drag-and-drop operation.
+ *
+ * @param e the event
+ */
+ void dragMouseMoved(DragSourceDragEvent e);
+} // interface DragSourceMotionListener
diff --git a/libjava/classpath/java/awt/dnd/DropTarget.java b/libjava/classpath/java/awt/dnd/DropTarget.java
new file mode 100644
index 000000000..e5180d074
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DropTarget.java
@@ -0,0 +1,438 @@
+/* DropTarget.java --
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import java.awt.Component;
+import java.awt.GraphicsEnvironment;
+import java.awt.HeadlessException;
+import java.awt.Insets;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.datatransfer.FlavorMap;
+import java.awt.datatransfer.SystemFlavorMap;
+import java.awt.dnd.peer.DropTargetPeer;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.peer.ComponentPeer;
+import java.awt.peer.LightweightPeer;
+import java.io.Serializable;
+import java.util.EventListener;
+import java.util.TooManyListenersException;
+
+import javax.swing.Timer;
+
+/**
+ * @author Michael Koch
+ * @since 1.2
+ */
+public class DropTarget
+ implements DropTargetListener, EventListener, Serializable
+{
+ /**
+ * Compatible with JDK 1.2+
+ */
+ private static final long serialVersionUID = -6283860791671019047L;
+
+ protected static class DropTargetAutoScroller
+ implements ActionListener
+ {
+ /**
+ * The threshold that keeps the autoscroller running.
+ */
+ private static final int HYSTERESIS = 10;
+
+ /**
+ * The initial timer delay.
+ */
+ private static final int DELAY = 100;
+
+ private Component component;
+ private Point point;
+
+ /**
+ * The timer that triggers autoscrolling.
+ */
+ private Timer timer;
+
+ /**
+ * The outer region of the scroller. This is the component's size.
+ */
+ private Rectangle outer;
+
+ /**
+ * The inner region of the scroller. This is the component size without
+ * the autoscroll insets.
+ */
+ private Rectangle inner;
+
+ protected DropTargetAutoScroller (Component c, Point p)
+ {
+ component = c;
+ point = p;
+ timer = new Timer(DELAY, this);
+ timer.setCoalesce(true);
+ timer.start();
+ }
+
+ protected void updateLocation (Point newLocn)
+ {
+ Point previous = point;
+ point = newLocn;
+ if (Math.abs(point.x - previous.x) > HYSTERESIS
+ || Math.abs(point.y - previous.y) > HYSTERESIS)
+ {
+ if (timer.isRunning())
+ timer.stop();
+ }
+ else
+ {
+ if (! timer.isRunning())
+ timer.start();
+ }
+ }
+
+ protected void stop ()
+ {
+ timer.start();
+ }
+
+ public void actionPerformed (ActionEvent e)
+ {
+ Autoscroll autoScroll = (Autoscroll) component;
+
+ // First synchronize the inner and outer rectangles.
+ Insets i = autoScroll.getAutoscrollInsets();
+ int width = component.getWidth();
+ int height = component.getHeight();
+ if (width != outer.width || height != outer.height)
+ outer.setBounds(0, 0, width, height);
+ if (inner.x != i.left || inner.y != i.top)
+ inner.setLocation(i.left, i.top);
+ int inWidth = width - i.left - i.right;
+ int inHeight = height - i.top - i.bottom;
+ if (inWidth != inner.width || inHeight != inner.height)
+ inner.setSize(inWidth, inHeight);
+
+ // Scroll if the outer rectangle contains the location, but the
+ // inner doesn't.
+ if (outer.contains(point) && ! inner.contains(point))
+ autoScroll.autoscroll(point);
+ }
+ }
+
+ private Component component;
+ private FlavorMap flavorMap;
+ private int actions;
+ private DropTargetPeer peer;
+ private DropTargetContext dropTargetContext;
+ private DropTargetListener dropTargetListener;
+ private DropTarget.DropTargetAutoScroller autoscroller;
+ private boolean active = true;
+
+ /**
+ * Creates a <code>DropTarget</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true.
+ */
+ public DropTarget ()
+ {
+ this (null, DnDConstants.ACTION_COPY_OR_MOVE, null, true, null);
+ }
+
+ /**
+ * Creates a <code>DropTarget</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true.
+ */
+ public DropTarget (Component c, DropTargetListener dtl)
+ {
+ this (c, DnDConstants.ACTION_COPY_OR_MOVE, dtl, true, null);
+ }
+
+ /**
+ * Creates a <code>DropTarget</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true.
+ */
+ public DropTarget (Component c, int i, DropTargetListener dtl)
+ {
+ this (c, i, dtl, true, null);
+ }
+
+ /**
+ * Creates a <code>DropTarget</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true.
+ */
+ public DropTarget (Component c, int i, DropTargetListener dtl, boolean b)
+ {
+ this (c, i, dtl, b, null);
+ }
+
+ /**
+ * Creates a <code>DropTarget</code> object.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless()
+ * returns true.
+ */
+ public DropTarget (Component c, int i, DropTargetListener dtl, boolean b,
+ FlavorMap fm)
+ {
+ if (GraphicsEnvironment.isHeadless ())
+ throw new HeadlessException ();
+
+ setComponent(c);
+ setDefaultActions(i);
+ dropTargetListener = dtl;
+
+ if (fm == null)
+ flavorMap = SystemFlavorMap.getDefaultFlavorMap();
+ else
+ flavorMap = fm;
+
+ setActive (b);
+
+ if (c != null)
+ c.setDropTarget(this);
+ }
+
+ /**
+ * Sets the component associated with this drop target object.
+ */
+ public void setComponent (Component c)
+ {
+ if (component != null)
+ clearAutoscroll();
+ component = c;
+ }
+
+ /**
+ * Returns the component associated with this drop target object.
+ */
+ public Component getComponent ()
+ {
+ return component;
+ }
+
+ /**
+ * Sets the default actions.
+ */
+ public void setDefaultActions (int ops)
+ {
+ actions = ops;
+ }
+
+ /**
+ * Returns the default actions.
+ */
+ public int getDefaultActions ()
+ {
+ return actions;
+ }
+
+ public void setActive (boolean active)
+ {
+ this.active = active;
+ if (! active)
+ clearAutoscroll();
+ }
+
+ public boolean isActive()
+ {
+ return active;
+ }
+
+ /**
+ * Adds a new <code>DropTargetListener</code>.
+ *
+ * @exception TooManyListenersException Sun's JDK does not, despite
+ * documentation, throw this exception here when you install an additional
+ * <code>DropTargetListener</code>. So to be compatible, we do the same
+ * thing.
+ */
+ public void addDropTargetListener (DropTargetListener dtl)
+ throws TooManyListenersException
+ {
+ if (dtl == null)
+ return;
+
+ if (dtl.equals(this))
+ throw new IllegalArgumentException();
+
+ if (dropTargetListener != null)
+ throw new TooManyListenersException();
+
+ dropTargetListener = dtl;
+ }
+
+ public void removeDropTargetListener(DropTargetListener dtl)
+ {
+ if (dropTargetListener != null)
+ dropTargetListener = null;
+ }
+
+ public void dragEnter(DropTargetDragEvent dtde)
+ {
+ if (active)
+ {
+ if (dropTargetListener != null)
+ dropTargetListener.dragEnter(dtde);
+ initializeAutoscrolling(dtde.getLocation());
+ }
+ }
+
+ public void dragOver(DropTargetDragEvent dtde)
+ {
+ if (active)
+ {
+ if (dropTargetListener != null)
+ dropTargetListener.dragOver(dtde);
+ updateAutoscroll(dtde.getLocation());
+ }
+ }
+
+ public void dropActionChanged(DropTargetDragEvent dtde)
+ {
+ if (active)
+ {
+ if (dropTargetListener != null)
+ dropTargetListener.dropActionChanged(dtde);
+ updateAutoscroll(dtde.getLocation());
+ }
+ }
+
+ public void dragExit(DropTargetEvent dte)
+ {
+ if (active)
+ {
+ if (dropTargetListener != null)
+ dropTargetListener.dragExit(dte);
+ clearAutoscroll();
+ }
+ }
+
+ public void drop(DropTargetDropEvent dtde)
+ {
+ clearAutoscroll();
+ if (dropTargetListener != null)
+ dropTargetListener.drop(dtde);
+ }
+
+ public FlavorMap getFlavorMap()
+ {
+ return flavorMap;
+ }
+
+ public void setFlavorMap(FlavorMap fm)
+ {
+ flavorMap = fm;
+ }
+
+ public void addNotify(ComponentPeer p)
+ {
+ Component c = component;
+ while (c != null && p instanceof LightweightPeer)
+ {
+ p = c.getPeer();
+ c = c.getParent();
+ }
+
+ if (p instanceof DropTargetPeer)
+ {
+ peer = ((DropTargetPeer) p);
+ peer.addDropTarget(this);
+ }
+ else
+ peer = null;
+ }
+
+ public void removeNotify(ComponentPeer p)
+ {
+ ((DropTargetPeer) peer).removeDropTarget(this);
+ peer = null;
+ p = null;
+ }
+
+ public DropTargetContext getDropTargetContext()
+ {
+ if (dropTargetContext == null)
+ dropTargetContext = createDropTargetContext ();
+
+ return dropTargetContext;
+ }
+
+ protected DropTargetContext createDropTargetContext()
+ {
+ if (dropTargetContext == null)
+ dropTargetContext = new DropTargetContext (this);
+
+ return dropTargetContext;
+ }
+
+ protected DropTarget.DropTargetAutoScroller createDropTargetAutoScroller
+ (Component c, Point p)
+ {
+ return new DropTarget.DropTargetAutoScroller (c, p);
+ }
+
+ protected void initializeAutoscrolling(Point p)
+ {
+ if (component instanceof Autoscroll) // Checks for null too.
+ autoscroller = createDropTargetAutoScroller (component, p);
+ }
+
+ protected void updateAutoscroll(Point dragCursorLocn)
+ {
+ if (autoscroller != null)
+ autoscroller.updateLocation(dragCursorLocn);
+ }
+
+ protected void clearAutoscroll()
+ {
+ if (autoscroller != null)
+ {
+ autoscroller.stop();
+ autoscroller = null;
+ }
+ }
+} // class DropTarget
diff --git a/libjava/classpath/java/awt/dnd/DropTargetAdapter.java b/libjava/classpath/java/awt/dnd/DropTargetAdapter.java
new file mode 100644
index 000000000..13c6b9f4b
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DropTargetAdapter.java
@@ -0,0 +1,100 @@
+/* DragSourceAdapter.java -- drag-and-drop listener adapter
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.dnd;
+
+/**
+ * This class implements <code>DropTargetListener</code>, and implements all methods
+ * with empty bodies. This allows a listener interested in implementing only
+ * a subset of these interfaces to extend this class and override only the
+ * desired methods.
+ *
+ * @author Michael Koch (konqueror@gmx.de)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public abstract class DropTargetAdapter
+ implements DropTargetListener
+{
+ /**
+ * Default constructor.
+ */
+ public DropTargetAdapter()
+ {
+ }
+
+ /**
+ * Called when the cursor hotspot enters a drop site which will accept the
+ * drag.
+ *
+ * @param e the event
+ */
+ public void dragEnter (DropTargetDragEvent e)
+ {
+ }
+
+ /**
+ * Called when the cursor hotspot moves inside of a drop site which will
+ * accept the drag.
+ *
+ * @param e the event
+ */
+ public void dragOver (DropTargetDragEvent e)
+ {
+ }
+
+ /**
+ * Called when the user modifies the drop gesture. This is often the case
+ * when additional mouse or key events are received during the drag.
+ *
+ * @param e the event
+ */
+ public void dropActionChanged (DropTargetDragEvent e)
+ {
+ }
+
+ /**
+ * Called when the cursor hotspot moves outside of a drop site which will
+ * accept the drag. This could also happen if the drop site is no longer
+ * active, or no longer accepts the drag.
+ *
+ * @param e the event
+ */
+ public void dragExit(DropTargetEvent e)
+ {
+ }
+} // class DropTargetAdapter
diff --git a/libjava/classpath/java/awt/dnd/DropTargetContext.java b/libjava/classpath/java/awt/dnd/DropTargetContext.java
new file mode 100644
index 000000000..4c21a6e8a
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DropTargetContext.java
@@ -0,0 +1,197 @@
+/* DropTargetContext.java --
+ Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.dnd;
+
+import java.awt.Component;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.awt.dnd.peer.DropTargetContextPeer;
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author Michael Koch (konqueror@gmx.de)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.2
+ */
+public class DropTargetContext implements Serializable
+{
+ static final long serialVersionUID = -634158968993743371L;
+
+ protected class TransferableProxy implements Transferable
+ {
+ protected boolean isLocal;
+ protected Transferable transferable;
+
+ TransferableProxy(Transferable t, boolean local)
+ {
+ this.transferable = t;
+ this.isLocal = local;
+ }
+
+ public DataFlavor[] getTransferDataFlavors()
+ {
+ return transferable.getTransferDataFlavors();
+ }
+
+ public boolean isDataFlavorSupported(DataFlavor flavor)
+ {
+ return transferable.isDataFlavorSupported(flavor);
+ }
+
+ public Object getTransferData(DataFlavor flavor)
+ throws UnsupportedFlavorException, IOException
+ {
+ return transferable.getTransferData (flavor);
+ }
+ }
+
+ private DropTarget dropTarget;
+ private int targetActions;
+ private DropTargetContextPeer dtcp;
+
+ // package private
+ DropTargetContext(DropTarget dropTarget)
+ {
+ this.dropTarget = dropTarget;
+ }
+
+ public DropTarget getDropTarget()
+ {
+ return dropTarget;
+ }
+
+ public Component getComponent()
+ {
+ return dropTarget.getComponent();
+ }
+
+ public void addNotify(DropTargetContextPeer dtcp)
+ {
+ this.dtcp = dtcp;
+ }
+
+ public void removeNotify()
+ {
+ this.dtcp = null;
+ }
+
+ protected void setTargetActions(int actions)
+ {
+ targetActions = actions;
+ }
+
+ protected int getTargetActions()
+ {
+ return targetActions;
+ }
+
+ /**
+ * Signals that the drop is completed.
+ *
+ * @exception InvalidDnDOperationException If a drop is not outstanding.
+ */
+ public void dropComplete (boolean success)
+ {
+ if (dtcp != null)
+ dtcp.dropComplete(success);
+ }
+
+ protected void acceptDrag (int dragOperation)
+ {
+ if (dtcp != null)
+ dtcp.acceptDrag(dragOperation);
+ }
+
+ protected void rejectDrag ()
+ {
+ if (dtcp != null)
+ dtcp.rejectDrag();
+ }
+
+ protected void acceptDrop (int dropOperation)
+ {
+ if (dtcp != null)
+ dtcp.acceptDrop(dropOperation);
+ }
+
+ protected void rejectDrop ()
+ {
+ if (dtcp != null)
+ dtcp.rejectDrop();
+ }
+
+ protected DataFlavor[] getCurrentDataFlavors ()
+ {
+ if (dtcp != null)
+ dtcp.getTransferDataFlavors();
+ return null;
+ }
+
+ protected List<DataFlavor> getCurrentDataFlavorsAsList ()
+ {
+ return Arrays.asList(getCurrentDataFlavors ());
+ }
+
+ protected boolean isDataFlavorSupported (DataFlavor flavor)
+ {
+ return getCurrentDataFlavorsAsList().contains (flavor);
+ }
+
+ /**
+ * Return the <code>Transferable</code> operandof this operation.
+ *
+ * @exception InvalidDnDOperationException If a drag is not outstanding.
+ */
+ protected Transferable getTransferable()
+ throws InvalidDnDOperationException
+ {
+ // FIXME: Implement this
+ if (dtcp != null)
+ return dtcp.getTransferable();
+ return null;
+ }
+
+ protected Transferable createTransferableProxy(Transferable t, boolean local)
+ {
+ return new TransferableProxy(t, local);
+ }
+} // class DropTargetContext
diff --git a/libjava/classpath/java/awt/dnd/DropTargetDragEvent.java b/libjava/classpath/java/awt/dnd/DropTargetDragEvent.java
new file mode 100644
index 000000000..21c9e2b35
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DropTargetDragEvent.java
@@ -0,0 +1,152 @@
+/* DropTargetDragEvent.java --
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import java.awt.Point;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.util.List;
+
+/**
+ * @since 1.2
+ */
+public class DropTargetDragEvent extends DropTargetEvent
+{
+ /**
+ * Compatible with 1.2+
+ */
+ private static final long serialVersionUID = -8422265619058953682L;
+
+ private final int dropAction;
+ private final int srcActions;
+ private final Point location;
+
+ /**
+ * Initializes a <code>DropTargetDragEvent</code>.
+ *
+ * @exception IllegalArgumentException If dropAction is not one of DnDConstants,
+ * srcActions is not a bitwise mask of DnDConstants, or dtc is null.
+ * @exception NullPointerException If location is null.
+ */
+ public DropTargetDragEvent (DropTargetContext context, Point location,
+ int dropAction, int srcActions)
+ {
+ super (context);
+
+ if (location == null)
+ throw new NullPointerException ();
+
+ if (context == null)
+ throw new IllegalArgumentException ();
+
+ if (dropAction != DnDConstants.ACTION_NONE
+ && dropAction != DnDConstants.ACTION_COPY
+ && dropAction != DnDConstants.ACTION_MOVE
+ && dropAction != DnDConstants.ACTION_COPY_OR_MOVE
+ && dropAction != DnDConstants.ACTION_LINK
+ && dropAction != DnDConstants.ACTION_REFERENCE)
+ throw new IllegalArgumentException ();
+
+ int srcActionsMask = DnDConstants.ACTION_NONE
+ | DnDConstants.ACTION_COPY
+ | DnDConstants.ACTION_MOVE
+ | DnDConstants.ACTION_COPY_OR_MOVE
+ | DnDConstants.ACTION_LINK
+ | DnDConstants.ACTION_REFERENCE;
+
+ if (~(srcActions ^ srcActionsMask) != 0)
+ throw new IllegalArgumentException ();
+
+ this.dropAction = dropAction;
+ this.srcActions = srcActions;
+ this.location = location;
+ }
+
+ public void acceptDrag (int dragOperation)
+ {
+ context.acceptDrag (dragOperation);
+ }
+
+ public DataFlavor[] getCurrentDataFlavors ()
+ {
+ return context.getCurrentDataFlavors ();
+ }
+
+ public List<DataFlavor> getCurrentDataFlavorsAsList ()
+ {
+ return context.getCurrentDataFlavorsAsList ();
+ }
+
+ public int getDropAction()
+ {
+ return dropAction & ((DropTargetContext) source).getTargetActions();
+ }
+
+ public Point getLocation ()
+ {
+ return location;
+ }
+
+ public int getSourceActions ()
+ {
+ return srcActions;
+ }
+
+ public boolean isDataFlavorSupported (DataFlavor df)
+ {
+ return context.isDataFlavorSupported (df);
+ }
+
+ public void rejectDrag ()
+ {
+ context.rejectDrag ();
+ }
+
+ /**
+ * TODO
+ *
+ * @return
+ *
+ * @since 1.5
+ */
+ public Transferable getTransferable()
+ {
+ return context.getTransferable();
+ }
+} // class DropTargetDragEvent
diff --git a/libjava/classpath/java/awt/dnd/DropTargetDropEvent.java b/libjava/classpath/java/awt/dnd/DropTargetDropEvent.java
new file mode 100644
index 000000000..333f8c6cc
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DropTargetDropEvent.java
@@ -0,0 +1,170 @@
+/* DropTargetDropEvent.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.dnd;
+
+import java.awt.Point;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.util.List;
+
+/**
+ * @since 1.2
+ */
+public class DropTargetDropEvent extends DropTargetEvent
+{
+ /**
+ * Compatible with JDK 1.2+
+ */
+ private static final long serialVersionUID = -1721911170440459322L;
+
+ private final int dropAction;
+ private final int actions;
+ private final Point location;
+ private final boolean isLocalTx;
+
+ /**
+ * Initializes a <code>DropTargetDropEvent</code>. By default this constructor
+ * assumes that the target is not int same JVM.
+ *
+ * @exception IllegalArgumentException If dropAction is not one of DnDConstants,
+ * actions is not a bitwise mask of DnDConstants, or dtc is null.
+ * @exception NullPointerException If location is null.
+ */
+ public DropTargetDropEvent(DropTargetContext dtc, Point location,
+ int dropAction, int actions)
+ {
+ this(dtc, location, dropAction, actions, false);
+ }
+
+ /**
+ * Initializes a <code>DropTargetDropEvent</code>.
+ *
+ * @exception IllegalArgumentException If dropAction is not one of DnDConstants,
+ * actions is not a bitwise mask of DnDConstants, or dtc is null.
+ * @exception NullPointerException If location is null.
+ */
+ public DropTargetDropEvent(DropTargetContext dtc, Point location,
+ int dropAction, int actions, boolean isLocalTx)
+ {
+ super(dtc);
+
+ if (location == null)
+ throw new NullPointerException();
+
+ if (dtc == null)
+ throw new IllegalArgumentException();
+
+ if (dropAction != DnDConstants.ACTION_NONE
+ && dropAction != DnDConstants.ACTION_COPY
+ && dropAction != DnDConstants.ACTION_MOVE
+ && dropAction != DnDConstants.ACTION_COPY_OR_MOVE
+ && dropAction != DnDConstants.ACTION_LINK
+ && dropAction != DnDConstants.ACTION_REFERENCE)
+ throw new IllegalArgumentException();
+
+ int actionsMask = DnDConstants.ACTION_NONE
+ | DnDConstants.ACTION_COPY
+ | DnDConstants.ACTION_MOVE
+ | DnDConstants.ACTION_COPY_OR_MOVE
+ | DnDConstants.ACTION_LINK
+ | DnDConstants.ACTION_REFERENCE;
+
+ if (~(actions ^ actionsMask) != 0)
+ throw new IllegalArgumentException();
+
+ this.dropAction = dropAction;
+ this.actions = actions;
+ this.location = location;
+ this.isLocalTx = isLocalTx;
+ }
+
+ public Point getLocation()
+ {
+ return location;
+ }
+
+ public DataFlavor[] getCurrentDataFlavors()
+ {
+ return context.getCurrentDataFlavors();
+ }
+
+ public List<DataFlavor> getCurrentDataFlavorsAsList()
+ {
+ return context.getCurrentDataFlavorsAsList();
+ }
+
+ public boolean isDataFlavorSupported(DataFlavor flavor)
+ {
+ return context.isDataFlavorSupported(flavor);
+ }
+
+ public int getSourceActions()
+ {
+ return actions;
+ }
+
+ public int getDropAction()
+ {
+ return dropAction;
+ }
+
+ public Transferable getTransferable()
+ {
+ return context.getTransferable ();
+ }
+
+ public void acceptDrop(int dropAction)
+ {
+ context.acceptDrop(dropAction);
+ }
+
+ public void rejectDrop()
+ {
+ context.rejectDrop();
+ }
+
+ public void dropComplete(boolean success)
+ {
+ context.dropComplete(success);
+ }
+
+ public boolean isLocalTransfer()
+ {
+ return isLocalTx;
+ }
+} // class DropTargetDropEvent
diff --git a/libjava/classpath/java/awt/dnd/DropTargetEvent.java b/libjava/classpath/java/awt/dnd/DropTargetEvent.java
new file mode 100644
index 000000000..fc599a9e2
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DropTargetEvent.java
@@ -0,0 +1,62 @@
+/* DropTarget.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.dnd;
+
+import java.util.EventObject;
+
+public class DropTargetEvent extends EventObject
+{
+
+ /**
+ * Serialization identifier for Sun 1.5 compatability
+ */
+ private static final long serialVersionUID = 2821229066521922993L;
+
+ protected DropTargetContext context;
+
+ public DropTargetEvent (DropTargetContext context)
+ {
+ super (context);
+ this.context = context;
+ }
+
+ public DropTargetContext getDropTargetContext ()
+ {
+ return context;
+ }
+}
diff --git a/libjava/classpath/java/awt/dnd/DropTargetListener.java b/libjava/classpath/java/awt/dnd/DropTargetListener.java
new file mode 100644
index 000000000..ceb839bac
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/DropTargetListener.java
@@ -0,0 +1,89 @@
+/* DropTargetListener.java -- listen to events during the drop
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+import java.util.EventListener;
+
+/**
+ * @author Michael Koch (konqueror@gmx.de)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface DropTargetListener extends EventListener
+{
+ /**
+ * Called when the cursor hotspot enters a drop site which will accept the
+ * drag.
+ *
+ * @param e the drag source drag event
+ */
+ void dragEnter (DropTargetDragEvent e);
+
+ /**
+ * Called when the cursor hotspot moves inside of a drop site which will
+ * accept the drag.
+ *
+ * @param e the drag source drag event
+ */
+ void dragOver (DropTargetDragEvent e);
+
+ /**
+ * Called when the user modifies the drop gesture. This is often the case
+ * when additional mouse or key events are received during the drag.
+ *
+ * @param e the drag source drag event
+ */
+ void dropActionChanged (DropTargetDragEvent e);
+
+ /**
+ * Called when the cursor hotspot moves outside of a drop site which will
+ * accept the drag. This could also happen if the drop site is no longer
+ * active, or no longer accepts the drag.
+ *
+ * @param e the drag source drag event
+ */
+ void dragExit (DropTargetEvent e);
+
+ /**
+ * Called when the drag operation has terminated with a drop.
+ *
+ * @param e the drag source drag event
+ */
+ void drop (DropTargetDropEvent e);
+} // interface DropTargetListener
diff --git a/libjava/classpath/java/awt/dnd/InvalidDnDOperationException.java b/libjava/classpath/java/awt/dnd/InvalidDnDOperationException.java
new file mode 100644
index 000000000..4a75610bf
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/InvalidDnDOperationException.java
@@ -0,0 +1,74 @@
+/* InvalidDnDOperationException.java -- thrown when drag-and-drop fails
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd;
+
+/**
+ * Thrown when a method in the java.awt.dnd package is unable to perform a
+ * requested operation, usually because the underlying DnD system is in the
+ * wrong state.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class InvalidDnDOperationException extends IllegalStateException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = -6062568741193956678L;
+
+ /**
+ * Create an exception without a message.
+ */
+ public InvalidDnDOperationException()
+ {
+ super();
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public InvalidDnDOperationException(String s)
+ {
+ super(s);
+ }
+} // class InvalidDnDOperationException
diff --git a/libjava/classpath/java/awt/dnd/MouseDragGestureRecognizer.java b/libjava/classpath/java/awt/dnd/MouseDragGestureRecognizer.java
new file mode 100644
index 000000000..08a2ac085
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/MouseDragGestureRecognizer.java
@@ -0,0 +1,131 @@
+/* MouseDragGestureRecognizer.java --
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.dnd;
+
+import java.awt.Component;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+
+/**
+ * @author Michael Koch (konqueror@gmx.de)
+ */
+public abstract class MouseDragGestureRecognizer
+ extends DragGestureRecognizer
+ implements MouseListener, MouseMotionListener
+{
+ /**
+ * Creates a <code>MouseDragGestureRecognizer</code> object.
+ */
+ protected MouseDragGestureRecognizer (DragSource ds, Component c, int act,
+ DragGestureListener dgl)
+ {
+ super (ds, c, act, dgl);
+ }
+
+ /**
+ * Creates a <code>MouseDragGestureRecognizer</code> object.
+ */
+ protected MouseDragGestureRecognizer (DragSource ds, Component c, int act)
+ {
+ super (ds, c, act);
+ }
+
+ /**
+ * Creates a <code>MouseDragGestureRecognizer</code> object.
+ */
+ protected MouseDragGestureRecognizer (DragSource ds, Component c)
+ {
+ super (ds, c);
+ }
+
+ /**
+ * Creates a <code>MouseDragGestureRecognizer</code> object.
+ */
+ protected MouseDragGestureRecognizer (DragSource ds)
+ {
+ super (ds);
+ }
+
+ protected void registerListeners ()
+ {
+ component.addMouseListener (this);
+ component.addMouseMotionListener (this);
+ }
+
+ protected void unregisterListeners ()
+ {
+ component.removeMouseListener (this);
+ component.removeMouseMotionListener (this);
+ }
+
+ public void mouseClicked (MouseEvent e)
+ {
+ // Do nothing in here by default.
+ }
+
+ public void mousePressed (MouseEvent e)
+ {
+ // Do nothing in here by default.
+ }
+
+ public void mouseReleased (MouseEvent e)
+ {
+ // Do nothing in here by default.
+ }
+
+ public void mouseEntered (MouseEvent e)
+ {
+ // Do nothing in here by default.
+ }
+
+ public void mouseExited (MouseEvent e)
+ {
+ // Do nothing in here by default.
+ }
+
+ public void mouseDragged (MouseEvent e)
+ {
+ // Do nothing in here by default.
+ }
+
+ public void mouseMoved (MouseEvent e)
+ {
+ // Do nothing in here by default.
+ }
+} // class MouseDragGestureRecognizer
diff --git a/libjava/classpath/java/awt/dnd/package.html b/libjava/classpath/java/awt/dnd/package.html
new file mode 100644
index 000000000..d1ae5215c
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt.dnd package.
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - java.awt.dnd</title></head>
+
+<body>
+<p>Events and listeners for drag and drop sources and targets.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/dnd/peer/DragSourceContextPeer.java b/libjava/classpath/java/awt/dnd/peer/DragSourceContextPeer.java
new file mode 100644
index 000000000..8c134b623
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/peer/DragSourceContextPeer.java
@@ -0,0 +1,57 @@
+/* DragSourceContextPeer.java -- interface for drag-and-drop peers
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd.peer;
+
+import java.awt.Cursor;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.dnd.DragSourceContext;
+import java.awt.dnd.InvalidDnDOperationException;
+
+/**
+ * STUBBED
+ */
+public interface DragSourceContextPeer
+{
+ void startDrag(DragSourceContext context, Cursor c, Image i, Point p)
+ throws InvalidDnDOperationException;
+ Cursor getCursor();
+ void setCursor(Cursor c) throws InvalidDnDOperationException;
+ void transferablesFlavorsChanged();
+} // interface DragSourceContextPeer
diff --git a/libjava/classpath/java/awt/dnd/peer/DropTargetContextPeer.java b/libjava/classpath/java/awt/dnd/peer/DropTargetContextPeer.java
new file mode 100644
index 000000000..2f4da5ff3
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/peer/DropTargetContextPeer.java
@@ -0,0 +1,68 @@
+/* DropTargetContextPeer.java -- interface for drag-and-drop peers
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.dnd.peer;
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.dnd.DropTarget;
+import java.awt.dnd.InvalidDnDOperationException;
+
+
+/**
+ * Used to control state of recipient protocol from the
+ * <code>DropTargetListener</code>. Occurs when a <code>Component</code>
+ * with an associated <code>DropTarget</code> and visible geometry is first
+ * intersected by a logical cursor.
+ *
+ * @author Michael Koch (konqueror@gmx.de)
+ */
+public interface DropTargetContextPeer
+{
+ void setTargetActions(int actions);
+ int getTargetActions();
+ DropTarget getDropTarget();
+ DataFlavor[] getTransferDataFlavors();
+ Transferable getTransferable() throws InvalidDnDOperationException;
+ boolean isTransferableJVMLocal();
+ void acceptDrag(int dragAction);
+ void rejectDrag();
+ void acceptDrop(int dropAction);
+ void rejectDrop();
+ void dropComplete(boolean success);
+}
diff --git a/libjava/classpath/java/awt/dnd/peer/DropTargetPeer.java b/libjava/classpath/java/awt/dnd/peer/DropTargetPeer.java
new file mode 100644
index 000000000..ec17cbe4b
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/peer/DropTargetPeer.java
@@ -0,0 +1,48 @@
+/* DropTargetPeer.java -- interface for drag-and-drop peers
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.dnd.peer;
+
+import java.awt.dnd.DropTarget;
+
+/**
+ */
+public interface DropTargetPeer
+{
+ void addDropTarget (DropTarget target);
+ void removeDropTarget (DropTarget target);
+} // interface DropTargetContextPeer
diff --git a/libjava/classpath/java/awt/dnd/peer/package.html b/libjava/classpath/java/awt/dnd/peer/package.html
new file mode 100644
index 000000000..52ec19cb4
--- /dev/null
+++ b/libjava/classpath/java/awt/dnd/peer/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt.dnd.peer package.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - java.awt.dnd.peer</title></head>
+
+<body>
+<p>Interfaces for using native interface components.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/doc-files/capjoin.png b/libjava/classpath/java/awt/doc-files/capjoin.png
new file mode 100644
index 000000000..555dca901
--- /dev/null
+++ b/libjava/classpath/java/awt/doc-files/capjoin.png
Binary files differ
diff --git a/libjava/classpath/java/awt/event/AWTEventListener.java b/libjava/classpath/java/awt/event/AWTEventListener.java
new file mode 100644
index 000000000..3f30df46e
--- /dev/null
+++ b/libjava/classpath/java/awt/event/AWTEventListener.java
@@ -0,0 +1,65 @@
+/* AWTEventListener.java -- listen for all events in the AWT system
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.AWTEvent;
+import java.awt.Toolkit;
+import java.util.EventListener;
+
+/**
+ * This listener is for classes that need to listen to all events in the AWT
+ * system. In general, this should not be used except for classes like
+ * javax.accessibility or by event recorders.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see AWTEvent
+ * @see Toolkit#addAWTEventListener(AWTEventListener, long)
+ * @see Toolkit#removeAWTEventListener(AWTEventListener)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface AWTEventListener extends EventListener
+{
+ /**
+ * This method is called when any event in the AWT system is dispatched.
+ *
+ * @param event the AWTEvent that was dispatched
+ */
+ void eventDispatched(AWTEvent event);
+} // interface AWTEventListener
diff --git a/libjava/classpath/java/awt/event/AWTEventListenerProxy.java b/libjava/classpath/java/awt/event/AWTEventListenerProxy.java
new file mode 100644
index 000000000..55a4bfe37
--- /dev/null
+++ b/libjava/classpath/java/awt/event/AWTEventListenerProxy.java
@@ -0,0 +1,95 @@
+/* AWTEventListenerProxy.java -- wrapper/filter for AWTEventListener
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.AWTEvent;
+import java.awt.Toolkit;
+import java.util.EventListenerProxy;
+
+/**
+ * This class allows adding an AWTEventListener which only pays attention to
+ * a specific event mask.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Toolkit
+ * @see EventListenerProxy
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public class AWTEventListenerProxy extends EventListenerProxy
+ implements AWTEventListener
+{
+ /** The event mask. */
+ private final long mask;
+
+ /**
+ * Construct an AWT Event Listener which only listens to events in the given
+ * mask, passing the work on to the real listener.
+ *
+ * @param eventMask the mask of events to listen to
+ * @param listener the wrapped listener
+ */
+ public AWTEventListenerProxy(long eventMask, AWTEventListener listener)
+ {
+ super(listener);
+ mask = eventMask;
+ }
+
+ /**
+ * Forwards events on to the delegate.
+ *
+ * @param event the to forward to the delagate listener
+ *
+ * @throws NullPointerException if the delegate this was created with is null
+ */
+ public void eventDispatched(AWTEvent event)
+ {
+ ((AWTEventListener) getListener()).eventDispatched(event);
+ }
+
+ /**
+ * This returns the event mask associated with this listener.
+ *
+ * @return the event mask
+ */
+ public long getEventMask()
+ {
+ return mask;
+ }
+} // class AWTEventListenerProxy
diff --git a/libjava/classpath/java/awt/event/ActionEvent.java b/libjava/classpath/java/awt/event/ActionEvent.java
new file mode 100644
index 000000000..776ab04be
--- /dev/null
+++ b/libjava/classpath/java/awt/event/ActionEvent.java
@@ -0,0 +1,228 @@
+/* ActionEvent.java -- an action has been triggered
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.awt.AWTEvent;
+import java.awt.EventQueue;
+
+/**
+ * This event is generated when an action on a component (such as a
+ * button press) occurs.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see ActionListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class ActionEvent extends AWTEvent
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -7671078796273832149L;
+
+ /** Bit mask indicating the shift key was pressed. */
+ public static final int SHIFT_MASK = InputEvent.SHIFT_MASK;
+
+ /** Bit mask indicating the control key was pressed. */
+ public static final int CTRL_MASK = InputEvent.CTRL_MASK;
+
+ /** Bit mask indicating the that meta key was pressed. */
+ public static final int META_MASK = InputEvent.META_MASK;
+
+ /** Bit mask indicating that the alt key was pressed. */
+ public static final int ALT_MASK = InputEvent.ALT_MASK;
+
+ /** The first id number in the range of action id's. */
+ public static final int ACTION_FIRST = 1001;
+
+ /** The last id number in the range of action id's. */
+ public static final int ACTION_LAST = 1001;
+
+ /** An event id indicating that an action has occurred. */
+ public static final int ACTION_PERFORMED = 1001;
+
+ /**
+ * A nonlocalized string that gives more specific details of the event cause.
+ *
+ * @see #getActionCommand()
+ * @serial the command for this event
+ */
+ private final String actionCommand;
+
+ /**
+ * The bitmask of the modifiers that were pressed during the action.
+ *
+ * @see #getModifiers()
+ * @serial modifiers for this event
+ */
+ private final int modifiers;
+
+ /**
+ * The timestamp of this event; usually the same as the underlying input
+ * event.
+ *
+ * @see #getWhen()
+ * @serial the timestamp of the event
+ * @since 1.4
+ */
+ private final long when;
+
+ /**
+ * Initializes a new instance of <code>ActionEvent</code> with the
+ * specified source, id, and command. Note that an invalid id leads to
+ * unspecified results.
+ *
+ * @param source the event source
+ * @param id the event id
+ * @param command the command string for this action
+ * @throws IllegalArgumentException if source is null
+ */
+ public ActionEvent(Object source, int id, String command)
+ {
+ this(source, id, command, EventQueue.getMostRecentEventTime(), 0);
+ }
+
+ /**
+ * Initializes a new instance of <code>ActionEvent</code> with the
+ * specified source, id, command, and modifiers. Note that an invalid id
+ * leads to unspecified results.
+ *
+ * @param source the event source
+ * @param id the event id
+ * @param command the command string for this action
+ * @param modifiers the bitwise or of modifier keys down during the action
+ * @throws IllegalArgumentException if source is null
+ */
+ public ActionEvent(Object source, int id, String command, int modifiers)
+ {
+ this(source, id, command, EventQueue.getMostRecentEventTime(), modifiers);
+ }
+
+ /**
+ * Initializes a new instance of <code>ActionEvent</code> with the
+ * specified source, id, command, and modifiers, and timestamp. Note that
+ * an invalid id leads to unspecified results.
+ *
+ * @param source the event source
+ * @param id the event id
+ * @param command the command string for this action
+ * @param when the timestamp of the event
+ * @param modifiers the bitwise or of modifier keys down during the action
+ * @throws IllegalArgumentException if source is null
+ * @since 1.4
+ */
+ public ActionEvent(Object source, int id, String command, long when,
+ int modifiers)
+ {
+ super(source, id);
+ actionCommand = command;
+ this.when = when;
+ this.modifiers = modifiers;
+ }
+
+ /**
+ * Returns the command string associated with this action.
+ *
+ * @return the command string associated with this action
+ */
+ public String getActionCommand()
+ {
+ return actionCommand;
+ }
+
+ /**
+ * Gets the timestamp of when this action took place. Usually, this
+ * corresponds to the timestamp of the underlying InputEvent.
+ *
+ * @return the timestamp of this action
+ * @since 1.4
+ */
+ public long getWhen()
+ {
+ return when;
+ }
+
+ /**
+ * Returns the keys held down during the action. This value will be a
+ * combination of the bit mask constants defined in this class, or 0 if no
+ * modifiers were pressed.
+ *
+ * @return the modifier bits
+ */
+ public int getModifiers()
+ {
+ return modifiers;
+ }
+
+ /**
+ * Returns a string that identifies the action event. This is in the format
+ * <code>"ACTION_PERFORMED,cmd=" + getActionCommand() + ",when=" + getWhen()
+ * + ",modifiers=" + &lt;modifier string&gt;</code>, where the modifier
+ * string is in the order "Meta", "Ctrl", "Alt", "Shift", "Alt Graph", and
+ * "Button1", separated by '+', according to the bits set in getModifiers().
+ *
+ * @return a string identifying the event
+ */
+ public String paramString()
+ {
+ CPStringBuilder s = new CPStringBuilder(id == ACTION_PERFORMED
+ ? "ACTION_PERFORMED,cmd="
+ : "unknown type,cmd=");
+ s.append(actionCommand).append(",when=").append(when).append(",modifiers");
+ int len = s.length();
+ s.setLength(len + 1);
+ if ((modifiers & META_MASK) != 0)
+ s.append("+Meta");
+ if ((modifiers & CTRL_MASK) != 0)
+ s.append("+Ctrl");
+ if ((modifiers & ALT_MASK) != 0)
+ s.append("+Alt");
+ if ((modifiers & SHIFT_MASK) != 0)
+ s.append("+Shift");
+ if ((modifiers & InputEvent.ALT_GRAPH_MASK) != 0)
+ s.append("+Alt Graph");
+ if ((modifiers & InputEvent.BUTTON1_MASK) != 0)
+ s.append("+Button1");
+ s.setCharAt(len, '=');
+ return s.toString();
+ }
+} // class ActionEvent
diff --git a/libjava/classpath/java/awt/event/ActionListener.java b/libjava/classpath/java/awt/event/ActionListener.java
new file mode 100644
index 000000000..4c302cca3
--- /dev/null
+++ b/libjava/classpath/java/awt/event/ActionListener.java
@@ -0,0 +1,59 @@
+/* ActionListener.java -- listens for action events
+ Copyright (C) 1999, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that listen for action events.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see ActionEvent
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface ActionListener extends EventListener
+{
+ /**
+ * This method is invoked when an action occurs.
+ *
+ * @param event the <code>ActionEvent</code> that occurred
+ */
+ void actionPerformed(ActionEvent event);
+}
diff --git a/libjava/classpath/java/awt/event/AdjustmentEvent.java b/libjava/classpath/java/awt/event/AdjustmentEvent.java
new file mode 100644
index 000000000..867c577d3
--- /dev/null
+++ b/libjava/classpath/java/awt/event/AdjustmentEvent.java
@@ -0,0 +1,222 @@
+/* AdjustmentEvent.java -- an adjustable value was changed
+ Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.AWTEvent;
+import java.awt.Adjustable;
+
+/**
+ * This class represents an event that is generated when an adjustable
+ * value is changed.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see Adjustable
+ * @see AdjustmentListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class AdjustmentEvent extends AWTEvent
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 5700290645205279921L;
+
+ /** This is the first id in the range of ids used by adjustment events. */
+ public static final int ADJUSTMENT_FIRST = 601;
+
+ /** This is the last id in the range of ids used by adjustment events. */
+ public static final int ADJUSTMENT_LAST = 601;
+
+ /** This is the id indicating an adjustment value changed. */
+ public static final int ADJUSTMENT_VALUE_CHANGED = 601;
+
+ /** Adjustment type for unit increments. */
+ public static final int UNIT_INCREMENT = 1;
+
+ /** Adjustment type for unit decrements. */
+ public static final int UNIT_DECREMENT = 2;
+
+ /** Adjustment type for block decrements. */
+ public static final int BLOCK_DECREMENT = 3;
+
+ /** Adjustment type for block increments. */
+ public static final int BLOCK_INCREMENT = 4;
+
+ /** Adjustment type for tracking adjustments. */
+ public static final int TRACK = 5;
+
+ /**
+ * The adjustable object that caused the event.
+ *
+ * @see #getAdjustable()
+ * @serial the cause
+ */
+ private final Adjustable adjustable;
+
+ /**
+ * The type of adjustment, one of {@link #UNIT_INCREMENT},
+ * {@link #UNIT_DECREMENT}, {@link #BLOCK_INCREMENT},
+ * {@link #BLOCK_DECREMENT}, or {@link #TRACK}.
+ *
+ * @see #getAdjustmentType()
+ * @serial the adjustment type
+ */
+ private final int adjustmentType;
+
+ /**
+ * The new value of the adjustable; it should be in the range of the
+ * adjustable cause.
+ *
+ * @see #getValue()
+ * @serial the adjustment value
+ */
+ private final int value;
+
+ /**
+ * True if this is in a series of multiple adjustment events.
+ *
+ * @see #getValueIsAdjusting()
+ * @serial true if this is not the last adjustment
+ * @since 1.4
+ */
+ private final boolean isAdjusting;
+
+ /**
+ * Initializes an instance of <code>AdjustmentEvent</code> with the
+ * specified source, id, type, and value. Note that an invalid id leads to
+ * unspecified results.
+ *
+ * @param source the source of the event
+ * @param id the event id
+ * @param type the event type, one of the constants of this class
+ * @param value the value of the adjustment
+ * @throws IllegalArgumentException if source is null
+ */
+ public AdjustmentEvent(Adjustable source, int id, int type, int value)
+ {
+ this(source, id, type, value, false);
+ }
+
+ /**
+ * Initializes an instance of <code>AdjustmentEvent</code> with the
+ * specified source, id, type, and value. Note that an invalid id leads to
+ * unspecified results.
+ *
+ * @param source the source of the event
+ * @param id the event id
+ * @param type the event type, one of the constants of this class
+ * @param value the value of the adjustment
+ * @param isAdjusting if this event is in a chain of adjustments
+ * @throws IllegalArgumentException if source is null
+ * @since 1.4
+ */
+ public AdjustmentEvent(Adjustable source, int id, int type, int value,
+ boolean isAdjusting)
+ {
+ super(source, id);
+ this.adjustmentType = type;
+ this.value = value;
+ adjustable = source;
+ this.isAdjusting = isAdjusting;
+ }
+
+ /**
+ * This method returns the source of the event as an <code>Adjustable</code>.
+ *
+ * @return the <code>Adjustable</code> source of the event
+ */
+ public Adjustable getAdjustable()
+ {
+ return adjustable;
+ }
+
+ /**
+ * Returns the new value of the adjustable object.
+ *
+ * @return the value of the event
+ */
+ public int getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Returns the type of the event, which will be one of
+ * {@link #UNIT_INCREMENT}, {@link #UNIT_DECREMENT},
+ * {@link #BLOCK_INCREMENT}, {@link #BLOCK_DECREMENT}, or {@link #TRACK}.
+ *
+ * @return the type of the event
+ */
+ public int getAdjustmentType()
+ {
+ return adjustmentType;
+ }
+
+ /**
+ * Test if this event is part of a sequence of multiple adjustements.
+ *
+ * @return true if this is not the last adjustment
+ * @since 1.4
+ */
+ public boolean getValueIsAdjusting()
+ {
+ return isAdjusting;
+ }
+
+ /**
+ * Returns a string that describes the event. This is in the format
+ * <code>"ADJUSTMENT_VALUE_CHANGED,adjType=" + &lt;type&gt; + ",value="
+ * + getValue() + ",isAdjusting=" + getValueIsAdjusting()</code>, where
+ * type is the name of the constant returned by getAdjustmentType().
+ *
+ * @return a string that describes the event
+ */
+ public String paramString()
+ {
+ return (id == ADJUSTMENT_VALUE_CHANGED
+ ? "ADJUSTMENT_VALUE_CHANGED,adjType=" : "unknown type,adjType=")
+ + (adjustmentType == UNIT_INCREMENT ? "UNIT_INCREMENT,value="
+ : adjustmentType == UNIT_DECREMENT ? "UNIT_DECREMENT,value="
+ : adjustmentType == BLOCK_INCREMENT ? "BLOCK_INCREMENT,value="
+ : adjustmentType == BLOCK_DECREMENT ? "BLOCK_DECREMENT,value="
+ : adjustmentType == TRACK ? "TRACK,value=" : "unknown type,value=")
+ + value + ",isAdjusting=" + isAdjusting;
+ }
+} // class AdjustmentEvent
diff --git a/libjava/classpath/java/awt/event/AdjustmentListener.java b/libjava/classpath/java/awt/event/AdjustmentListener.java
new file mode 100644
index 000000000..1eb2e3bcf
--- /dev/null
+++ b/libjava/classpath/java/awt/event/AdjustmentListener.java
@@ -0,0 +1,58 @@
+/* AdjustmentListener.java -- listen for adjustment events
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.util.EventListener;
+
+/**
+ * Interface for classes that listen for adjustment events.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface AdjustmentListener extends EventListener
+{
+ /**
+ * This method is called when an adjustable value changes.
+ *
+ * @param event the <code>AdjustmentEvent</code> that occurred
+ */
+ void adjustmentValueChanged(AdjustmentEvent event);
+} // interface AdjustmentListener
diff --git a/libjava/classpath/java/awt/event/ComponentAdapter.java b/libjava/classpath/java/awt/event/ComponentAdapter.java
new file mode 100644
index 000000000..cb1c0dae9
--- /dev/null
+++ b/libjava/classpath/java/awt/event/ComponentAdapter.java
@@ -0,0 +1,97 @@
+/* ComponentAdapter.java -- convenience class for writing component listeners
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+/**
+ * This class implements <code>ComponentListener</code> and implements
+ * all methods with empty bodies. This allows a listener interested in
+ * implementing only a subset of the <code>ComponentListener</code>
+ * interface to extend this class and override only the desired methods.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see ComponentEvent
+ * @see ComponentListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class ComponentAdapter implements ComponentListener
+{
+ /**
+ * Do nothing default constructor for subclasses.
+ */
+ public ComponentAdapter()
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void componentResized(ComponentEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void componentMoved(ComponentEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void componentShown(ComponentEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void componentHidden(ComponentEvent event)
+ {
+ }
+} // class ComponentAdapter
diff --git a/libjava/classpath/java/awt/event/ComponentEvent.java b/libjava/classpath/java/awt/event/ComponentEvent.java
new file mode 100644
index 000000000..3fd86853b
--- /dev/null
+++ b/libjava/classpath/java/awt/event/ComponentEvent.java
@@ -0,0 +1,142 @@
+/* ComponentEvent.java -- notification of events for components
+ Copyright (C) 1999, 2002, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.awt.AWTEvent;
+import java.awt.Component;
+
+/**
+ * This class is for events generated when a component is moved, resized,
+ * hidden, or shown. These events normally do not need to be handled by the
+ * application, since the AWT system automatically takes care of them. This
+ * is also the superclass for other events on components, but
+ * ComponentListeners ignore such subclasses.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see ComponentAdapter
+ * @see ComponentListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class ComponentEvent extends AWTEvent
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 8101406823902992965L;
+
+ /** This is the first id in the range of ids used by this class. */
+ public static final int COMPONENT_FIRST = 100;
+
+ /** This is the last id in the range of ids used by this class. */
+ public static final int COMPONENT_LAST = 103;
+
+ /** This id indicates that a component was moved. */
+ public static final int COMPONENT_MOVED = 100;
+
+ /** This id indicates that a component was resized. */
+ public static final int COMPONENT_RESIZED = 101;
+
+ /** This id indicates that a component was shown. */
+ public static final int COMPONENT_SHOWN = 102;
+
+ /** This id indicates that a component was hidden. */
+ public static final int COMPONENT_HIDDEN = 103;
+
+ /**
+ * Initializes a new instance of <code>ComponentEvent</code> with the
+ * specified source and id. Note that an invalid id leads to unspecified
+ * results.
+ *
+ * @param source the source of the event
+ * @param id the event id
+ * @throws IllegalArgumentException if source is null
+ */
+ public ComponentEvent(Component source, int id)
+ {
+ super(source, id);
+ }
+
+ /**
+ * This method returns the event source as a <code>Component</code>. If the
+ * source has subsequently been modified to a non-Component, this returns
+ * null.
+ *
+ * @return the event source as a <code>Component</code>, or null
+ */
+ public Component getComponent()
+ {
+ return source instanceof Component ? (Component) source : null;
+ }
+
+ /**
+ * This method returns a string identifying this event. This is the field
+ * name of the id type, and for COMPONENT_MOVED or COMPONENT_RESIZED, the
+ * new bounding box of the component.
+ *
+ * @return a string identifying this event
+ */
+ public String paramString()
+ {
+ CPStringBuilder s = new CPStringBuilder();
+
+ // Unlike Sun, we don't throw NullPointerException or ClassCastException
+ // when source was illegally changed.
+ if (id == COMPONENT_MOVED)
+ s.append("COMPONENT_MOVED ");
+ else if (id == COMPONENT_RESIZED)
+ s.append("COMPONENT_RESIZED ");
+ else if (id == COMPONENT_SHOWN)
+ s.append("COMPONENT_SHOWN ");
+ else if (id == COMPONENT_HIDDEN)
+ s.append("COMPONENT_HIDDEN ");
+ else
+ return "unknown type";
+
+ s.append("(").append(getComponent().getX()).append(",")
+ .append(getComponent().getY()).append(" ")
+ .append(getComponent().getWidth()).append("x")
+ .append(getComponent().getHeight()).append(")");
+
+ return s.toString();
+ }
+
+} // class ComponentEvent
diff --git a/libjava/classpath/java/awt/event/ComponentListener.java b/libjava/classpath/java/awt/event/ComponentListener.java
new file mode 100644
index 000000000..b43faaed7
--- /dev/null
+++ b/libjava/classpath/java/awt/event/ComponentListener.java
@@ -0,0 +1,84 @@
+/* ComponentListener.java -- receive all events for a component
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that receive all events from a component.
+ * Normally it is not necessary to process these events since the AWT
+ * handles them internally, taking all appropriate actions. To watch a subset
+ * of these events, use a ComponentAdapter.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see ComponentAdapter
+ * @see ComponentEvent
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface ComponentListener extends EventListener
+{
+ /**
+ * This method is called when the component is resized.
+ *
+ * @param event the <code>ComponentEvent</code> indicating the resize
+ */
+ void componentResized(ComponentEvent event);
+
+ /**
+ * This method is called when the component is moved.
+ *
+ * @param event the <code>ComponentEvent</code> indicating the move
+ */
+ void componentMoved(ComponentEvent event);
+
+ /**
+ * This method is called when the component is made visible.
+ *
+ * @param event the <code>ComponentEvent</code> indicating the visibility
+ */
+ void componentShown(ComponentEvent event);
+
+ /**
+ * This method is called when the component is hidden.
+ *
+ * @param event the <code>ComponentEvent</code> indicating the visibility
+ */
+ void componentHidden(ComponentEvent event);
+} // interface ComponentListener
diff --git a/libjava/classpath/java/awt/event/ContainerAdapter.java b/libjava/classpath/java/awt/event/ContainerAdapter.java
new file mode 100644
index 000000000..c847adfa2
--- /dev/null
+++ b/libjava/classpath/java/awt/event/ContainerAdapter.java
@@ -0,0 +1,79 @@
+/* ContainerAdapter.java -- convenience class for writing container listeners
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+/**
+ * This class implements <code>ContainerListener</code> and implements
+ * all methods with empty bodies. This allows a listener interested in
+ * implementing only a subset of the <code>ContainerListener</code>
+ * interface to extend this class and override only the desired methods.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see ContainerEvent
+ * @see ContainerListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class ContainerAdapter implements ContainerListener
+{
+ /**
+ * Do nothing default constructor for subclasses.
+ */
+ public ContainerAdapter()
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void componentAdded(ContainerEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void componentRemoved(ContainerEvent event)
+ {
+ }
+} // class ContainerAdapter
diff --git a/libjava/classpath/java/awt/event/ContainerEvent.java b/libjava/classpath/java/awt/event/ContainerEvent.java
new file mode 100644
index 000000000..3c401fe1a
--- /dev/null
+++ b/libjava/classpath/java/awt/event/ContainerEvent.java
@@ -0,0 +1,135 @@
+/* ContainerEvent.java -- components added/removed from a container
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.Component;
+import java.awt.Container;
+
+/**
+ * This event is generated when a component is added or removed from a
+ * container. Applications do not ordinarily need to handle these events
+ * since the AWT system handles them internally.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see ContainerAdapter
+ * @see ContainerListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class ContainerEvent extends ComponentEvent
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -4114942250539772041L;
+
+ /** This is the first id in the id range used by this class. */
+ public static final int CONTAINER_FIRST = 300;
+
+ /** This is the last id in the id range used by this class. */
+ public static final int CONTAINER_LAST = 301;
+
+ /** This id indicates a component was added to the container. */
+ public static final int COMPONENT_ADDED = 300;
+
+ /** This id indicates a component was removed from the container. */
+ public static final int COMPONENT_REMOVED = 301;
+
+ /**
+ * The non-null child component that was added or removed.
+ *
+ * @serial the child component that changed
+ */
+ private final Component child;
+
+ /**
+ * Initializes a new instance of <code>ContainerEvent</code> with the
+ * specified source and id. Additionally, the affected child component
+ * is also passed as a parameter. Note that an invalid id leads to
+ * unspecified results.
+ *
+ * @param source the source container of the event
+ * @param id the event id
+ * @param child the child component affected by this event
+ * @throws IllegalArgumentException if source is null
+ */
+ public ContainerEvent(Component source, int id, Component child)
+ {
+ super(source, id);
+ this.child = child;
+ }
+
+ /**
+ * Returns the source of this event as a <code>Container</code>.
+ *
+ * @return the source of the event
+ * @throws ClassCastException if the source is changed to a non-Container
+ */
+ public Container getContainer()
+ {
+ return (Container) source;
+ }
+
+ /**
+ * This method returns the child object that was added or removed from
+ * the container.
+ *
+ * @return the child object added or removed
+ */
+ public Component getChild()
+ {
+ return child;
+ }
+
+ /**
+ * This method returns a string identifying this event. It is formatted as:
+ * <code>(getID() == COMPONENT_ADDED ? "COMPONENT_ADDED"
+ * : "COMPONENT_REMOVED") + ",child=" + getChild().getName()</code>.
+ *
+ * @return a string identifying this event
+ */
+ public String paramString()
+ {
+ // Unlike Sun, we don't throw NullPointerException if child is illegally
+ // null.
+ return (id == COMPONENT_ADDED ? "COMPONENT_ADDED,child="
+ : id == COMPONENT_REMOVED ? "COMPONENT_REMOVED,child="
+ : "unknown type,child=") + (child == null ? "" : child.getName());
+ }
+} // class ContainerEvent
diff --git a/libjava/classpath/java/awt/event/ContainerListener.java b/libjava/classpath/java/awt/event/ContainerListener.java
new file mode 100644
index 000000000..b37d43408
--- /dev/null
+++ b/libjava/classpath/java/awt/event/ContainerListener.java
@@ -0,0 +1,70 @@
+/* ContainerListener.java -- listen for container events
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that wish to listen for all events from
+ * container objects. This is normally not necessary since the AWT system
+ * listens for and processes these events. To watch a subset of these events,
+ * use a ContainerAdapter.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see ContainerAdapter
+ * @see ContainerEvent
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface ContainerListener extends EventListener
+{
+ /**
+ * This method is called when a component is added to the container.
+ *
+ * @param event the <code>ContainerEvent</code> indicating component addition
+ */
+ void componentAdded(ContainerEvent event);
+
+ /**
+ * This method is called when a component is removed from the container.
+ *
+ * @param event the <code>ContainerEvent</code> indicating component removal
+ */
+ void componentRemoved(ContainerEvent event);
+} // interface ContainerListener
diff --git a/libjava/classpath/java/awt/event/FocusAdapter.java b/libjava/classpath/java/awt/event/FocusAdapter.java
new file mode 100644
index 000000000..fb0532a3a
--- /dev/null
+++ b/libjava/classpath/java/awt/event/FocusAdapter.java
@@ -0,0 +1,79 @@
+/* FocusAdapter.java -- convenience class for writing focus listeners
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+/**
+ * This class implements <code>FocusListener</code> and implements all
+ * methods with empty bodies. This allows a listener interested in
+ * implementing only a subset of the <code>FocusListener</code> interface to
+ * extend this class and override only the desired methods.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see FocusEvent
+ * @see FocusListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class FocusAdapter implements FocusListener
+{
+ /**
+ * Do nothing default constructor for subclasses.
+ */
+ public FocusAdapter()
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void focusGained(FocusEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void focusLost(FocusEvent event)
+ {
+ }
+} // class FocusAdapter
diff --git a/libjava/classpath/java/awt/event/FocusEvent.java b/libjava/classpath/java/awt/event/FocusEvent.java
new file mode 100644
index 000000000..a44284aea
--- /dev/null
+++ b/libjava/classpath/java/awt/event/FocusEvent.java
@@ -0,0 +1,181 @@
+/* FocusEvent.java -- generated for a focus change
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.Component;
+
+/**
+ * This class represents an event generated when a focus change occurs for a
+ * component. There are both temporary changes, such as when focus is stolen
+ * during a sroll then returned, and permanent changes, such as when the user
+ * TABs through focusable components.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see FocusAdapter
+ * @see FocusListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class FocusEvent extends ComponentEvent
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 523753786457416396L;
+
+ /** This is the first id in the range of ids used by this class. */
+ public static final int FOCUS_FIRST = 1004;
+
+ /** This is the last id in the range of ids used by this class. */
+ public static final int FOCUS_LAST = 1005;
+
+ /** This is the event id for a focus gained event. */
+ public static final int FOCUS_GAINED = 1004;
+
+ /** This is the event id for a focus lost event. */
+ public static final int FOCUS_LOST = 1005;
+
+ /**
+ * Indicates whether or not the focus change is temporary.
+ *
+ * @see #isTemporary()
+ * @serial true if the focus change is temporary
+ */
+ private final boolean temporary;
+
+ /**
+ * The other component which is giving up or stealing focus from this
+ * component, if known.
+ *
+ * @see #getOppositeComponent()
+ * @serial the component with the opposite focus event, or null
+ * @since 1.4
+ */
+ private final Component opposite;
+
+ /**
+ * Initializes a new instance of <code>FocusEvent</code> with the
+ * specified source, id, temporary status, and opposite counterpart. Note
+ * that an invalid id leads to unspecified results.
+ *
+ * @param source the component that is gaining or losing focus
+ * @param id the event id
+ * @param temporary true if the focus change is temporary
+ * @param opposite the component receiving the opposite focus event, or null
+ * @throws IllegalArgumentException if source is null
+ */
+ public FocusEvent(Component source, int id, boolean temporary,
+ Component opposite)
+ {
+ super(source, id);
+ this.temporary = temporary;
+ this.opposite = opposite;
+ }
+
+ /**
+ * Initializes a new instance of <code>FocusEvent</code> with the
+ * specified source, id, and temporary status. Note that an invalid id
+ * leads to unspecified results.
+ *
+ * @param source the component that is gaining or losing focus
+ * @param id the event id
+ * @param temporary true if the focus change is temporary
+ * @throws IllegalArgumentException if source is null
+ */
+ public FocusEvent(Component source, int id, boolean temporary)
+ {
+ this(source, id, temporary, null);
+ }
+
+ /**
+ * Initializes a new instance of <code>FocusEvent</code> with the
+ * specified source and id. Note that an invalid id leads to unspecified
+ * results.
+ *
+ * @param source the component that is gaining or losing focus
+ * @param id the event id
+ * @throws IllegalArgumentException if source is null
+ */
+ public FocusEvent(Component source, int id)
+ {
+ this(source, id, false, null);
+ }
+
+ /**
+ * This method tests whether or not the focus change is temporary or
+ * permanent.
+ *
+ * @return true if the focus change is temporary
+ */
+ public boolean isTemporary()
+ {
+ return temporary;
+ }
+
+ /**
+ * Returns the component which received the opposite focus event. If this
+ * component gained focus, the opposite lost focus; likewise if this
+ * component is giving up focus, the opposite is gaining it. If this
+ * information is unknown, perhaps because the opposite is a native
+ * application, this returns null.
+ *
+ * @return the component with the focus opposite, or null
+ * @since 1.4
+ */
+ public Component getOppositeComponent()
+ {
+ return opposite;
+ }
+
+ /**
+ * Returns a string identifying this event. This is formatted as:
+ * <code>(getID() == FOCUS_GAINED ? "FOCUS_GAINED" : "FOCUS_LOST")
+ * + (isTemporary() ? ",temporary," : ",permanent,") + "opposite="
+ * + getOppositeComponent()</code>.
+ *
+ * @return a string identifying this event
+ */
+ public String paramString()
+ {
+ return (id == FOCUS_GAINED ? "FOCUS_GAINED"
+ : id == FOCUS_LOST ? "FOCUS_LOST" : "unknown type")
+ + (temporary ? ",temporary,opposite=" : ",permanent,opposite=")
+ + opposite;
+ }
+} // class FocusEvent
diff --git a/libjava/classpath/java/awt/event/FocusListener.java b/libjava/classpath/java/awt/event/FocusListener.java
new file mode 100644
index 000000000..1f7201825
--- /dev/null
+++ b/libjava/classpath/java/awt/event/FocusListener.java
@@ -0,0 +1,69 @@
+/* FocusListener.java -- listen for focus changes
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that wish to be notified of changes of
+ * keyboard focus for a component. To watch a subset of these events, use a
+ * FocusAdapter.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see FocusAdapter
+ * @see FocusEvent
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface FocusListener extends EventListener
+{
+ /**
+ * This method is called when a component gains the keyboard focus.
+ *
+ * @param event the <code>FocusEvent</code> indicating that focus was gained
+ */
+ void focusGained(FocusEvent event);
+
+ /**
+ * This method is invoked when a component loses the keyboard focus.
+ *
+ * @param event the <code>FocusEvent</code> indicating that focus was lost
+ */
+ void focusLost(FocusEvent event);
+} // interface FocusListener
diff --git a/libjava/classpath/java/awt/event/HierarchyBoundsAdapter.java b/libjava/classpath/java/awt/event/HierarchyBoundsAdapter.java
new file mode 100644
index 000000000..340cf01ed
--- /dev/null
+++ b/libjava/classpath/java/awt/event/HierarchyBoundsAdapter.java
@@ -0,0 +1,78 @@
+/* HierarchyBoundsAdapter.java -- convenience class for writing listeners
+ Copyright (C) 2000, 2002 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.event;
+
+/**
+ * This class implements <code>HierarchyBoundsListener</code> and implements
+ * all methods with empty bodies. This allows a listener interested in
+ * implementing only a subset of the <code>HierarchyBoundsListener</code>
+ * interface to extend this class and override only the desired methods.
+ *
+ * @author Bryce McKinlay
+ * @see HierarchyBoundsListener
+ * @see HierarchyEvent
+ * @since 1.3
+ * @status updated to 1.4
+ */
+public abstract class HierarchyBoundsAdapter implements HierarchyBoundsListener
+{
+ /**
+ * Do nothing default constructor for subclasses.
+ */
+ public HierarchyBoundsAdapter()
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void ancestorMoved(HierarchyEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void ancestorResized(HierarchyEvent event)
+ {
+ }
+}
diff --git a/libjava/classpath/java/awt/event/HierarchyBoundsListener.java b/libjava/classpath/java/awt/event/HierarchyBoundsListener.java
new file mode 100644
index 000000000..689623744
--- /dev/null
+++ b/libjava/classpath/java/awt/event/HierarchyBoundsListener.java
@@ -0,0 +1,70 @@
+/* HierarchyBoundsListener.java -- listens to bounds changes of parents
+ Copyright (C) 2000, 2002 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.util.EventListener;
+
+/**
+ * This listens for changes in an ancestors size or location. Normally it is
+ * not necessary to process these events since the AWT handles them
+ * internally, taking all appropriate actions. To watch a subset of these
+ * events, use a HierarchyBoundsAdapter.
+ *
+ * @author Bryce McKinlay
+ * @see HierarchyBoundsAdapter
+ * @see HierarchyEvent
+ * @since 1.3
+ * @status updated to 1.4
+ */
+public interface HierarchyBoundsListener extends EventListener
+{
+ /**
+ * Called when an ancestor component of the source is moved.
+ *
+ * @param e the event describing the ancestor's motion
+ */
+ void ancestorMoved(HierarchyEvent e);
+
+ /**
+ * Called when an ancestor component is resized.
+ *
+ * @param e the event describing the ancestor's resizing
+ */
+ void ancestorResized(HierarchyEvent e);
+} // interface HierarchyBoundsListener
diff --git a/libjava/classpath/java/awt/event/HierarchyEvent.java b/libjava/classpath/java/awt/event/HierarchyEvent.java
new file mode 100644
index 000000000..3237978f9
--- /dev/null
+++ b/libjava/classpath/java/awt/event/HierarchyEvent.java
@@ -0,0 +1,255 @@
+/* HierarchyEvent.java -- generated for a change in hierarchy
+ Copyright (C) 2000, 2002 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.awt.AWTEvent;
+import java.awt.Component;
+import java.awt.Container;
+
+/**
+ * This class represents an event generated for an ancestor component which
+ * may affect this component. These events normally do not need to be handled
+ * by the application, since the AWT system automatically takes care of them.
+ *
+ * <p>There are two types of hierarchy events. The first type is handled by
+ * HierarchyListener, and includes addition or removal of an ancestor, or
+ * an ancestor changing its on-screen status (visible and/or displayble). The
+ * second type is handled by HierarchyBoundsListener, and includes resizing
+ * or moving of an ancestor.
+ *
+ * @author Bryce McKinlay
+ * @see HierarchyListener
+ * @see HierarchyBoundsAdapter
+ * @see HierarchyBoundsListener
+ * @since 1.3
+ * @status updated to 1.4
+ */
+public class HierarchyEvent extends AWTEvent
+{
+ /**
+ * Compatible with JDK 1.3+.
+ */
+ private static final long serialVersionUID = -5337576970038043990L;
+
+ /** This is the first id in the range of ids used by this class. */
+ public static final int HIERARCHY_FIRST = 1400;
+
+ /** This id indicates that the hierarchy tree changed. */
+ public static final int HIERARCHY_CHANGED = 1400;
+
+ /** This id indicates that an ancestor was moved. */
+ public static final int ANCESTOR_MOVED = 1401;
+
+ /** This id indicates that an ancestor was resized. */
+ public static final int ANCESTOR_RESIZED = 1402;
+
+ /** This is the last id in the range of ids used by this class. */
+ public static final int HIERARCHY_LAST = 1402;
+
+ /** This indicates that the HIERARCHY_CHANGED is a changed parent. */
+ public static final int PARENT_CHANGED = 1;
+
+ /**
+ * This indicates that the HIERARCHY_CHANGED is caused by a change in
+ * displayability.
+ *
+ * @see Component#isDisplayable()
+ * @see Component#addNotify()
+ * @see Component#removeNotify()
+ */
+ public static final int DISPLAYABILITY_CHANGED = 2;
+
+ /**
+ * This indicates that the HIERARCHY_CHANGED is a changed visibility.
+ *
+ * @see Component#isShowing()
+ * @see Component#addNotify()
+ * @see Component#removeNotify()
+ * @see Component#show()
+ * @see Component#hide()
+ */
+ public static final int SHOWING_CHANGED = 4;
+
+ /**
+ * The component at the top of the changed hierarchy.
+ *
+ * @serial the top component changed
+ */
+ private final Component changed;
+
+ /**
+ * The parent of this component, either before or after the change depending
+ * on the type of change.
+ *
+ * @serial the parent component changed
+ */
+ private final Container changedParent;
+
+ /**
+ * The bitmask of HIERARCHY_CHANGED event types.
+ *
+ * @serial the change flags
+ */
+ private final long changeFlags;
+
+ /**
+ * Initializes a new instance of <code>HierarchyEvent</code> with the
+ * specified parameters. Note that an invalid id leads to unspecified
+ * results.
+ *
+ * @param source the component whose hierarchy changed
+ * @param id the event id
+ * @param changed the top component in the tree of changed hierarchy
+ * @param changedParent the updated parent of this object
+ * @throws IllegalArgumentException if source is null
+ */
+ public HierarchyEvent(Component source, int id, Component changed,
+ Container changedParent)
+ {
+ this(source, id, changed, changedParent, 0);
+ }
+
+ /**
+ * Initializes a new instance of <code>HierarchyEvent</code> with the
+ * specified parameters. Note that an invalid id leads to unspecified
+ * results.
+ *
+ * @param source the component whose hierarchy changed
+ * @param id the event id
+ * @param changed the top component in the tree of changed hierarchy
+ * @param changedParent the updated parent of this object
+ * @param changeFlags the bitmask of specific HIERARCHY_CHANGED events
+ * @throws IllegalArgumentException if source is null
+ */
+ public HierarchyEvent(Component source, int id, Component changed,
+ Container changedParent, long changeFlags)
+ {
+ super(source, id);
+ this.changed = changed;
+ this.changedParent = changedParent;
+ this.changeFlags = changeFlags;
+ }
+
+ /**
+ * This method returns the event source as a <code>Component</code>. If the
+ * source has subsequently been modified to a non-Component, this returns
+ * null.
+ *
+ * @return the event source as a <code>Component</code>, or null
+ */
+ public Component getComponent()
+ {
+ return source instanceof Component ? (Component) source : null;
+ }
+
+ /**
+ * Returns the component at the top of the hierarchy which changed.
+ *
+ * @return the top changed component
+ */
+ public Component getChanged()
+ {
+ return changed;
+ }
+
+ /**
+ * Returns the parent of the component listed in <code>getChanged()</code>.
+ * If the cause of this event was <code>Container.add</code>, this is the
+ * new parent; if the cause was <code>Container.remove</code>, this is the
+ * old parent; otherwise it is the unchanged parent.
+ *
+ * @return the parent container of the changed component
+ */
+ public Container getChangedParent()
+ {
+ return changedParent;
+ }
+
+ /**
+ * If this is a HIERARCHY_CHANGED event, this returns a bitmask of the
+ * types of changes that took place.
+ *
+ * @return the bitwise or of hierarchy change types, or 0
+ * @see #PARENT_CHANGED
+ * @see #DISPLAYABILITY_CHANGED
+ * @see #SHOWING_CHANGED
+ */
+ public long getChangeFlags()
+ {
+ return changeFlags;
+ }
+
+ /**
+ * This method returns a string identifying this event. This is the field
+ * name of the id type, followed by a parenthesized listing of the changed
+ * component and its parent container. In addition, if the type is
+ * HIERARCHY_CHANGED, the flags preceed the changed component, in the
+ * order PARENT_CHANGED, DISPLAYABILITY_CHANGED, and SHOWING_CHANGED.
+ *
+ * @return a string identifying this event
+ */
+ public String paramString()
+ {
+ CPStringBuilder r = new CPStringBuilder();
+ switch (id)
+ {
+ case HIERARCHY_CHANGED:
+ r.append("HIERARCHY_CHANGED (");
+ if ((changeFlags & PARENT_CHANGED) != 0)
+ r.append("PARENT_CHANGED,");
+ if ((changeFlags & DISPLAYABILITY_CHANGED) != 0)
+ r.append("DISPLAYABILITY_CHANGED,");
+ if ((changeFlags & SHOWING_CHANGED) != 0)
+ r.append("SHOWING_CHANGED,");
+ break;
+ case ANCESTOR_MOVED:
+ r.append("ANCESTOR_MOVED (");
+ break;
+ case ANCESTOR_RESIZED:
+ r.append("ANCESTOR_RESIZED (");
+ break;
+ default:
+ return "unknown type";
+ }
+ r.append(changed).append(',').append(changedParent).append(')');
+ return r.toString();
+ }
+} // class HierarchyEvent
diff --git a/libjava/classpath/java/awt/event/HierarchyListener.java b/libjava/classpath/java/awt/event/HierarchyListener.java
new file mode 100644
index 000000000..f90414b86
--- /dev/null
+++ b/libjava/classpath/java/awt/event/HierarchyListener.java
@@ -0,0 +1,62 @@
+/* HierarchyListener.java -- listens to changes in the component hierarchy
+ Copyright (C) 2000, 2002 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.util.EventListener;
+
+/**
+ * This listens for changes in the hierarchy tree of components. Normally it is
+ * not necessary to process these events since the AWT handles them
+ * internally, taking all appropriate actions.
+ *
+ * @author Bryce McKinlay
+ * @see HierarchyEvent
+ * @since 1.3
+ * @status updated to 1.4
+ */
+public interface HierarchyListener extends EventListener
+{
+ /**
+ * Called when the hierarchy of this component changes. Use
+ * <code>getChangeFlags()</code> on the event to see what exactly changed.
+ *
+ * @param e the event describing the change
+ */
+ void hierarchyChanged(HierarchyEvent e);
+} // interface HierarchyListener
diff --git a/libjava/classpath/java/awt/event/InputEvent.java b/libjava/classpath/java/awt/event/InputEvent.java
new file mode 100644
index 000000000..241630ca3
--- /dev/null
+++ b/libjava/classpath/java/awt/event/InputEvent.java
@@ -0,0 +1,399 @@
+/* InputEvent.java -- common superclass of component input events
+ Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import gnu.java.awt.EventModifier;
+import gnu.java.lang.CPStringBuilder;
+
+import java.awt.Component;
+
+/**
+ * This is the common superclass for all component input classes. These are
+ * passed to listeners before the component, so that listeners can consume
+ * the event before it does its default behavior.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see KeyEvent
+ * @see KeyAdapter
+ * @see MouseEvent
+ * @see MouseAdapter
+ * @see MouseMotionAdapter
+ * @see MouseWheelEvent
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class InputEvent extends ComponentEvent
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -2482525981698309786L;
+
+ /**
+ * This is the bit mask which indicates the shift key is down. It is
+ * recommended that SHIFT_DOWN_MASK be used instead.
+ *
+ * @see #SHIFT_DOWN_MASK
+ */
+ public static final int SHIFT_MASK = 1;
+
+ /**
+ * This is the bit mask which indicates the control key is down. It is
+ * recommended that CTRL_DOWN_MASK be used instead.
+ *
+ * @see #CTRL_DOWN_MASK
+ */
+ public static final int CTRL_MASK = 2;
+
+ /**
+ * This is the bit mask which indicates the meta key is down. It is
+ * recommended that META_DOWN_MASK be used instead.
+ *
+ * @see #META_DOWN_MASK
+ */
+ public static final int META_MASK = 4;
+
+ /**
+ * This is the bit mask which indicates the alt key is down. It is
+ * recommended that ALT_DOWN_MASK be used instead.
+ *
+ * @see #ALT_DOWN_MASK
+ */
+ public static final int ALT_MASK = 8;
+
+ /**
+ * This is the bit mask which indicates the alt-graph modifier is in effect.
+ * It is recommended that ALT_GRAPH_DOWN_MASK be used instead.
+ *
+ * @see #ALT_GRAPH_DOWN_MASK
+ */
+ public static final int ALT_GRAPH_MASK = 0x20;
+
+ /**
+ * This bit mask indicates mouse button one is down. It is recommended that
+ * BUTTON1_DOWN_MASK be used instead.
+ *
+ * @see #BUTTON1_DOWN_MASK
+ */
+ public static final int BUTTON1_MASK = 0x10;
+
+ /**
+ * This bit mask indicates mouse button two is down. It is recommended that
+ * BUTTON2_DOWN_MASK be used instead.
+ *
+ * @see #BUTTON2_DOWN_MASK
+ */
+ public static final int BUTTON2_MASK = 8;
+
+ /**
+ * This bit mask indicates mouse button three is down. It is recommended
+ * that BUTTON3_DOWN_MASK be used instead.
+ *
+ * @see #BUTTON3_DOWN_MASK
+ */
+ public static final int BUTTON3_MASK = 4;
+
+ /**
+ * The SHIFT key extended modifier.
+ *
+ * @since 1.4
+ */
+ public static final int SHIFT_DOWN_MASK = 0x0040;
+
+ /**
+ * The CTRL key extended modifier.
+ *
+ * @since 1.4
+ */
+ public static final int CTRL_DOWN_MASK = 0x0080;
+
+ /**
+ * The META key extended modifier.
+ *
+ * @since 1.4
+ */
+ public static final int META_DOWN_MASK = 0x0100;
+
+ /**
+ * The ALT key extended modifier.
+ *
+ * @since 1.4
+ */
+ public static final int ALT_DOWN_MASK = 0x0200;
+
+ /**
+ * The mouse button1 key extended modifier.
+ *
+ * @since 1.4
+ */
+ public static final int BUTTON1_DOWN_MASK = 0x0400;
+
+ /**
+ * The mouse button2 extended modifier.
+ *
+ * @since 1.4
+ */
+ public static final int BUTTON2_DOWN_MASK = 0x0800;
+
+ /**
+ * The mouse button3 extended modifier.
+ *
+ * @since 1.4
+ */
+ public static final int BUTTON3_DOWN_MASK = 0x1000;
+
+ /**
+ * The ALT_GRAPH key extended modifier.
+ *
+ * @since 1.4
+ */
+ public static final int ALT_GRAPH_DOWN_MASK = 0x2000;
+
+ /** The mask to convert new to old, package visible for use in subclasses. */
+ static final int CONVERT_MASK
+ = EventModifier.NEW_MASK & ~(BUTTON2_DOWN_MASK | BUTTON3_DOWN_MASK);
+
+ /**
+ * The timestamp when this event occurred.
+ *
+ * @see #getWhen()
+ * @serial the timestamp
+ */
+ private final long when;
+
+ /**
+ * The old-style modifiers in effect for this event. Package visible
+ * for use by subclasses. The old style (bitmask 0x3f) should not be
+ * mixed with the new style (bitmasks 0xffffffc0).
+ *
+ * @see #getModifiers()
+ * @see MouseEvent
+ * @serial the modifier state, stored in the old style
+ */
+ int modifiers;
+
+ /**
+ * The new-style modifiers in effect for this event. Package visible
+ * for use by subclasses. The old style (bitmask 0x3f) should not be
+ * mixed with the new style (bitmasks 0xffffffc0).
+ *
+ * @see #getModifiersEx()
+ * @see MouseEvent
+ * @serial the modifier state, stored in the new style
+ */
+ int modifiersEx;
+
+ /**
+ * Initializes a new instance of <code>InputEvent</code> with the specified
+ * source, id, timestamp, and modifiers. Note that an invalid id leads to
+ * unspecified results.
+ *
+ * @param source the source of the event
+ * @param id the event id
+ * @param when the timestamp when the event occurred
+ * @param modifiers the modifiers in effect for this event, old or new style
+ * @throws IllegalArgumentException if source is null
+ */
+ InputEvent(Component source, int id, long when, int modifiers)
+ {
+ super(source, id);
+ this.when = when;
+ this.modifiers = modifiers & EventModifier.OLD_MASK;
+ this.modifiersEx = modifiers & EventModifier.NEW_MASK;
+ }
+
+ /**
+ * This method tests whether or not the shift key was down during the event.
+ *
+ * @return true if the shift key is down
+ */
+ public boolean isShiftDown()
+ {
+ return ((modifiers & SHIFT_MASK) != 0)
+ || ((modifiersEx & SHIFT_DOWN_MASK) != 0);
+ }
+
+ /**
+ * This method tests whether or not the control key was down during the
+ * event.
+ *
+ * @return true if the control key is down
+ */
+ public boolean isControlDown()
+ {
+ return ((modifiers & CTRL_MASK) != 0)
+ || ((modifiersEx & CTRL_DOWN_MASK) != 0);
+ }
+
+ /**
+ * This method tests whether or not the meta key was down during the event.
+ *
+ * @return true if the meta key is down
+ */
+ public boolean isMetaDown()
+ {
+ return ((modifiers & META_MASK) != 0)
+ || ((modifiersEx & META_DOWN_MASK) != 0);
+ }
+
+ /**
+ * This method tests whether or not the alt key was down during the event.
+ *
+ * @return true if the alt key is down
+ */
+ public boolean isAltDown()
+ {
+ return ((modifiers & ALT_MASK) != 0)
+ || ((modifiersEx & ALT_DOWN_MASK) != 0);
+ }
+
+ /**
+ * This method tests whether or not the alt-graph modifier was in effect
+ * during the event.
+ *
+ * @return true if the alt-graph modifier is down
+ */
+ public boolean isAltGraphDown()
+ {
+ return ((modifiers & ALT_GRAPH_MASK) != 0)
+ || ((modifiersEx & ALT_GRAPH_DOWN_MASK) != 0);
+ }
+
+ /**
+ * This method returns the timestamp when this event occurred.
+ *
+ * @return the timestamp when this event occurred
+ */
+ public long getWhen()
+ {
+ return when;
+ }
+
+ /**
+ * This method returns the old-style modifiers in effect for this event.
+ * Note that this is ambiguous between button2 and alt, and between
+ * button3 and meta. Also, code which generated these modifiers tends to
+ * only list the modifier that just changed, even if others were down at
+ * the time. Consider using getModifiersEx instead. This will be a union
+ * of the bit masks defined in this class that are applicable to the event.
+ *
+ * @return the modifiers in effect for this event
+ * @see #getModifiersEx()
+ */
+ public int getModifiers()
+ {
+ return modifiers;
+ }
+
+ /**
+ * Returns the extended modifiers (new-style) for this event. This represents
+ * the state of all modal keys and mouse buttons at the time of the event,
+ * and does not suffer from the problems mentioned in getModifiers.
+ *
+ * <p>For an example of checking multiple modifiers, this code will return
+ * true only if SHIFT and BUTTON1 were pressed and CTRL was not:
+ * <pre>
+ * int onmask = InputEvent.SHIFT_DOWN_MASK | InputEvent.BUTTON1_DOWN_MASK;
+ * int offmask = InputEvent.CTRL_DOWN_MASK;
+ * return (event.getModifiersEx() & (onmask | offmask)) == onmask;
+ * </pre>
+ *
+ * @return the bitwise or of all modifiers pressed during the event
+ * @since 1.4
+ */
+ public int getModifiersEx()
+ {
+ return modifiersEx;
+ }
+
+ /**
+ * Consumes this event. A consumed event is not processed further by the AWT
+ * system.
+ */
+ public void consume()
+ {
+ consumed = true;
+ }
+
+ /**
+ * This method tests whether or not this event has been consumed.
+ *
+ * @return true if this event has been consumed
+ */
+ public boolean isConsumed()
+ {
+ return consumed;
+ }
+
+ /**
+ * Convert the extended modifier bitmask into a String, such as "Shift" or
+ * "Ctrl+Button1".
+ *
+ * XXX Sun claims this can be localized via the awt.properties file - how
+ * do we implement that?
+ *
+ * @param modifiers the modifiers
+ * @return a string representation of the modifiers in this bitmask
+ * @since 1.4
+ */
+ public static String getModifiersExText(int modifiers)
+ {
+ modifiers &= EventModifier.NEW_MASK;
+ if (modifiers == 0)
+ return "";
+ CPStringBuilder s = new CPStringBuilder();
+ if ((modifiers & META_DOWN_MASK) != 0)
+ s.append("Meta+");
+ if ((modifiers & CTRL_DOWN_MASK) != 0)
+ s.append("Ctrl+");
+ if ((modifiers & ALT_DOWN_MASK) != 0)
+ s.append("Alt+");
+ if ((modifiers & SHIFT_DOWN_MASK) != 0)
+ s.append("Shift+");
+ if ((modifiers & ALT_GRAPH_DOWN_MASK) != 0)
+ s.append("Alt Graph+");
+ if ((modifiers & BUTTON1_DOWN_MASK) != 0)
+ s.append("Button1+");
+ if ((modifiers & BUTTON2_DOWN_MASK) != 0)
+ s.append("Button2+");
+ if ((modifiers & BUTTON3_DOWN_MASK) != 0)
+ s.append("Button3+");
+ return s.substring(0, s.length() - 1);
+ }
+} // class InputEvent
diff --git a/libjava/classpath/java/awt/event/InputMethodEvent.java b/libjava/classpath/java/awt/event/InputMethodEvent.java
new file mode 100644
index 000000000..1542bcc9f
--- /dev/null
+++ b/libjava/classpath/java/awt/event/InputMethodEvent.java
@@ -0,0 +1,305 @@
+/* InputMethodEvent.java -- events from a text input method
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.awt.AWTEvent;
+import java.awt.Component;
+import java.awt.EventQueue;
+import java.awt.font.TextHitInfo;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.text.AttributedCharacterIterator;
+
+/**
+ * This class is for event generated by change in a text input method.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see InputMethodListener
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class InputMethodEvent extends AWTEvent
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 4727190874778922661L;
+
+ /** This is the first id in the range of event ids used by this class. */
+ public static final int INPUT_METHOD_FIRST = 1100;
+
+ /** This event id indicates that the text in the input method has changed. */
+ public static final int INPUT_METHOD_TEXT_CHANGED = 1100;
+
+ /** This event id indicates that the input method curor point has changed. */
+ public static final int CARET_POSITION_CHANGED = 1101;
+
+ /** This is the last id in the range of event ids used by this class. */
+ public static final int INPUT_METHOD_LAST = 1101;
+
+ /**
+ * The timestamp when this event was created.
+ *
+ * @serial the timestamp
+ * @since 1.4
+ */
+ private long when;
+
+ /** The input method text. */
+ private final transient AttributedCharacterIterator text;
+
+ /** The number of committed characters in the text. */
+ private final transient int committedCharacterCount;
+
+ /** The caret. */
+ private final transient TextHitInfo caret;
+
+ /** The most important position to be visible. */
+ private final transient TextHitInfo visiblePosition;
+
+ /**
+ * Initializes a new instance of <code>InputMethodEvent</code> with the
+ * specified source, id, timestamp, text, char count, caret, and visible
+ * position.
+ *
+ * @param source the source that generated the event
+ * @param id the event id
+ * @param when the timestamp of the event
+ * @param text the input text
+ * @param committedCharacterCount the number of committed characters
+ * @param caret the caret position
+ * @param visiblePosition the position most important to make visible
+ * @throws IllegalArgumentException if source is null, id is invalid, id is
+ * CARET_POSITION_CHANGED and text is non-null, or if
+ * committedCharacterCount is out of range
+ * @since 1.4
+ */
+ public InputMethodEvent(Component source, int id, long when,
+ AttributedCharacterIterator text,
+ int committedCharacterCount, TextHitInfo caret,
+ TextHitInfo visiblePosition)
+ {
+ super(source, id);
+ this.when = when;
+ this.text = text;
+ this.committedCharacterCount = committedCharacterCount;
+ this.caret = caret;
+ this.visiblePosition = visiblePosition;
+ if (id < INPUT_METHOD_FIRST || id > INPUT_METHOD_LAST
+ || (id == CARET_POSITION_CHANGED && text != null)
+ || committedCharacterCount < 0
+ || (committedCharacterCount
+ > (text == null ? 0 : text.getEndIndex() - text.getBeginIndex())))
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Initializes a new instance of <code>InputMethodEvent</code> with the
+ * specified source, id, text, char count, caret, and visible position.
+ *
+ * @param source the source that generated the event
+ * @param id the event id
+ * @param text the input text
+ * @param committedCharacterCount the number of committed characters
+ * @param caret the caret position
+ * @param visiblePosition the position most important to make visible
+ * @throws IllegalArgumentException if source is null, id is invalid, id is
+ * CARET_POSITION_CHANGED and text is non-null, or if
+ * committedCharacterCount is out of range
+ * @since 1.4
+ */
+ public InputMethodEvent(Component source, int id,
+ AttributedCharacterIterator text,
+ int committedCharacterCount, TextHitInfo caret,
+ TextHitInfo visiblePosition)
+ {
+ this(source, id, EventQueue.getMostRecentEventTime(), text,
+ committedCharacterCount, caret, visiblePosition);
+ }
+
+ /**
+ * Initializes a new instance of <code>InputMethodEvent</code> with the
+ * specified source, id, caret, and visible position, and with a null
+ * text and char count.
+ *
+ * @param source the source that generated the event
+ * @param id the event id
+ * @param caret the caret position
+ * @param visiblePosition the position most important to make visible
+ * @throws IllegalArgumentException if source is null or id is invalid
+ * @since 1.4
+ */
+ public InputMethodEvent(Component source, int id, TextHitInfo caret,
+ TextHitInfo visiblePosition)
+ {
+ this(source, id, EventQueue.getMostRecentEventTime(), null, 0, caret,
+ visiblePosition);
+ }
+
+ /**
+ * This method returns the input method text. This can be <code>null</code>,
+ * and will always be null for <code>CARET_POSITION_CHANGED</code> events.
+ * Characters from 0 to <code>getCommittedCharacterCount()-1</code> have
+ * been committed, the remaining characters are composed text.
+ *
+ * @return the input method text, or null
+ */
+ public AttributedCharacterIterator getText()
+ {
+ return text;
+ }
+
+ /**
+ * Returns the number of committed characters in the input method text.
+ *
+ * @return the number of committed characters in the input method text
+ */
+ public int getCommittedCharacterCount()
+ {
+ return committedCharacterCount;
+ }
+
+ /**
+ * Returns the caret position. The caret offset is relative to the composed
+ * text of the most recent <code>INPUT_METHOD_TEXT_CHANGED</code> event.
+ *
+ * @return the caret position, or null
+ */
+ public TextHitInfo getCaret()
+ {
+ return caret;
+ }
+
+ /**
+ * Returns the position that is most important to be visible, or null if
+ * such a hint is not necessary. The caret offset is relative to the composed
+ * text of the most recent <code>INPUT_METHOD_TEXT_CHANGED</code> event.
+ *
+ * @return the position that is most important to be visible
+ */
+ public TextHitInfo getVisiblePosition()
+ {
+ return visiblePosition;
+ }
+
+ /**
+ * This method consumes the event. A consumed event is not processed
+ * in the default manner by the component that generated it.
+ */
+ public void consume()
+ {
+ consumed = true;
+ }
+
+ /**
+ * This method tests whether or not this event has been consumed.
+ *
+ * @return true if the event has been consumed
+ */
+ public boolean isConsumed()
+ {
+ return consumed;
+ }
+
+ /**
+ * Return the timestamp of this event.
+ *
+ * @return the timestamp
+ * @since 1.4
+ */
+ public long getWhen()
+ {
+ return when;
+ }
+
+ /**
+ * This method returns a string identifying the event. This contains the
+ * event ID, the committed and composed characters separated by '+', the
+ * number of committed characters, the caret, and the visible position.
+ *
+ * @return a string identifying the event
+ */
+ public String paramString()
+ {
+ CPStringBuilder s
+ = new CPStringBuilder(80 + (text == null ? 0
+ : text.getEndIndex() - text.getBeginIndex()));
+ s.append(id == INPUT_METHOD_TEXT_CHANGED ? "INPUT_METHOD_TEXT_CHANGED, "
+ : "CARET_POSITION_CHANGED, ");
+ if (text == null)
+ s.append("no text, 0 characters committed, caret: ");
+ else
+ {
+ s.append('"');
+ int i = text.getBeginIndex();
+ int j = committedCharacterCount;
+ while (--j >= 0)
+ s.append(text.setIndex(i++));
+ s.append("\" + \"");
+ j = text.getEndIndex() - i;
+ while (--j >= 0)
+ s.append(text.setIndex(i++));
+ s.append("\", ").append(committedCharacterCount)
+ .append(" characters committed, caret: ");
+ }
+ s.append(caret == null ? (Object) "no caret" : caret).append(", ")
+ .append(visiblePosition == null ? (Object) "no visible position"
+ : visiblePosition);
+ return s.toString();
+ }
+
+ /**
+ * Reads in the object from a serial stream, updating when to
+ * {@link EventQueue#getMostRecentEventTime()} if necessary.
+ *
+ * @param s the stream to read from
+ * @throws IOException if deserialization fails
+ * @throws ClassNotFoundException if deserialization fails
+ * @serialData default, except for updating when
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ if (when == 0)
+ when = EventQueue.getMostRecentEventTime();
+ }
+} // class InputMethodEvent
diff --git a/libjava/classpath/java/awt/event/InputMethodListener.java b/libjava/classpath/java/awt/event/InputMethodListener.java
new file mode 100644
index 000000000..e2f6a4e67
--- /dev/null
+++ b/libjava/classpath/java/awt/event/InputMethodListener.java
@@ -0,0 +1,70 @@
+/* InputMethodListener.java -- listen for input method events
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.im.InputMethodRequests;
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that wish to receive events from an input
+ * method. For a text component to use input methods, it must also install
+ * an InputMethodRequests handler.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see InputMethodEvent
+ * @see InputMethodRequests
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface InputMethodListener extends EventListener
+{
+ /**
+ * This method is called when the text is changed.
+ *
+ * @param event the <code>InputMethodEvent</code> indicating the text change
+ */
+ void inputMethodTextChanged(InputMethodEvent event);
+
+ /**
+ * This method is called when the cursor position within the text is changed.
+ *
+ * @param event the <code>InputMethodEvent</code> indicating the change
+ */
+ void caretPositionChanged(InputMethodEvent event);
+} // interface InputMethodListener
diff --git a/libjava/classpath/java/awt/event/InvocationEvent.java b/libjava/classpath/java/awt/event/InvocationEvent.java
new file mode 100644
index 000000000..afa09de13
--- /dev/null
+++ b/libjava/classpath/java/awt/event/InvocationEvent.java
@@ -0,0 +1,258 @@
+/* InvocationEvent.java -- call a runnable when dispatched
+ Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.AWTEvent;
+import java.awt.ActiveEvent;
+import java.awt.EventQueue;
+
+/**
+ * This event executes {@link Runnable#run()} of a target object when it is
+ * dispatched. This class is used by calls to <code>invokeLater</code> and
+ * <code>invokeAndWait</code>, so client code can use this fact to avoid
+ * writing special-casing AWTEventListener objects.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see ActiveEvent
+ * @see EventQueue#invokeLater(Runnable)
+ * @see EventQueue#invokeAndWait(Runnable)
+ * @see AWTEventListener
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class InvocationEvent extends AWTEvent implements ActiveEvent
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 436056344909459450L;
+
+ /** This is the first id in the range of event ids used by this class. */
+ public static final int INVOCATION_FIRST = 1200;
+
+ /** This is the default id for this event type. */
+ public static final int INVOCATION_DEFAULT = 1200;
+
+ /** This is the last id in the range of event ids used by this class. */
+ public static final int INVOCATION_LAST = 1200;
+
+ /**
+ * This is the <code>Runnable</code> object to call when dispatched.
+ *
+ * @serial the runnable to execute
+ */
+ protected Runnable runnable;
+
+ /**
+ * This is the object to call <code>notifyAll()</code> on when
+ * the call to <code>run()</code> returns, or <code>null</code> if no
+ * object is to be notified.
+ *
+ * @serial the object to notify
+ */
+ protected Object notifier;
+
+ /**
+ * This variable is set to <code>true</code> if exceptions are caught
+ * and stored in a variable during the call to <code>run()</code>, otherwise
+ * exceptions are ignored and propagate up.
+ *
+ * @serial true to catch exceptions
+ */
+ protected boolean catchExceptions;
+
+ /**
+ * This is the caught exception thrown in the <code>run()</code> method. It
+ * is null if exceptions are ignored, the run method hasn't completed, or
+ * there were no exceptions.
+ *
+ * @serial the caught exception, if any
+ */
+ private Exception exception;
+
+ /**
+ * This is the caught Throwable thrown in the <code>run()</code> method.
+ * It is null if throwables are ignored, the run method hasn't completed,
+ * or there were no throwables thrown.
+ */
+ private Throwable throwable;
+
+ /**
+ * The timestamp when this event was created.
+ *
+ * @see #getWhen()
+ * @serial the timestamp
+ * @since 1.4
+ */
+ private final long when = EventQueue.getMostRecentEventTime();
+
+ /**
+ * Initializes a new instance of <code>InvocationEvent</code> with the
+ * specified source and runnable.
+ *
+ * @param source the source of the event
+ * @param runnable the <code>Runnable</code> object to invoke
+ * @throws IllegalArgumentException if source is null
+ */
+ public InvocationEvent(Object source, Runnable runnable)
+ {
+ this(source, INVOCATION_DEFAULT, runnable, null, false);
+ }
+
+ /**
+ * Initializes a new instance of <code>InvocationEvent</code> with the
+ * specified source, runnable, and notifier. It will also catch exceptions
+ * if specified. If notifier is non-null, this will call notifyAll() on
+ * the object when the runnable is complete. If catchExceptions is true,
+ * this traps any exception in the runnable, otherwise it lets the exception
+ * propagate up the Event Dispatch thread.
+ *
+ * @param source the source of the event
+ * @param runnable the <code>Runnable</code> object to invoke
+ * @param notifier the object to notify, or null
+ * @param catchExceptions true to catch exceptions from the runnable
+ */
+ public InvocationEvent(Object source, Runnable runnable, Object notifier,
+ boolean catchExceptions)
+ {
+ this(source, INVOCATION_DEFAULT, runnable, notifier, catchExceptions);
+ }
+
+ /**
+ * Initializes a new instance of <code>InvocationEvent</code> with the
+ * specified source, runnable, and notifier. It will also catch exceptions
+ * if specified. If notifier is non-null, this will call notifyAll() on
+ * the object when the runnable is complete. If catchExceptions is true,
+ * this traps any exception in the runnable, otherwise it lets the exception
+ * propagate up the Event Dispatch thread. Note that an invalid id leads to
+ * unspecified results.
+ *
+ * @param source the source of the event
+ * @param id the event id
+ * @param runnable the <code>Runnable</code> object to invoke
+ * @param notifier the object to notify, or null
+ * @param catchExceptions true to catch exceptions from the runnable
+ */
+ protected InvocationEvent(Object source, int id, Runnable runnable,
+ Object notifier, boolean catchExceptions)
+ {
+ super(source, id);
+ this.runnable = runnable;
+ this.notifier = notifier;
+ this.catchExceptions = catchExceptions;
+ }
+
+ /**
+ * This method calls the <code>run()</code> method of the runnable, traps
+ * exceptions if instructed to do so, and calls <code>notifyAll()</code>
+ * on any notifier if all worked successfully.
+ */
+ public void dispatch()
+ {
+ if (catchExceptions)
+ try
+ {
+ runnable.run();
+ }
+ catch (Throwable t)
+ {
+ throwable = t;
+ if (t instanceof Exception)
+ exception = (Exception)t;
+ }
+ else
+ runnable.run();
+
+ Object o = notifier;
+ if (o != null)
+ synchronized(o)
+ {
+ o.notifyAll();
+ }
+ }
+
+ /**
+ * This method returns the exception that occurred during the execution of
+ * the runnable, or <code>null</code> if not exception was thrown or
+ * exceptions were not caught.
+ *
+ * @return the exception thrown by the runnable
+ */
+ public Exception getException()
+ {
+ return exception;
+ }
+
+ /**
+ * Returns a throwable caught while executing the Runnable's run() method.
+ * Null if none was thrown or if this InvocationEvent doesn't catch
+ * throwables.
+ * @return the caught Throwable
+ * @since 1.5
+ */
+ public Throwable getThrowable()
+ {
+ return throwable;
+ }
+
+ /**
+ * Gets the timestamp of when this event was created.
+ *
+ * @return the timestamp of this event
+ * @since 1.4
+ */
+ public long getWhen()
+ {
+ return when;
+ }
+
+ /**
+ * This method returns a string identifying this event. This is formatted as:
+ * <code>"INVOCATION_DEFAULT,runnable=" + runnable + ",notifier=" + notifier
+ * + ",catchExceptions=" + catchExceptions + ",when=" + getWhen()</code>.
+ *
+ * @return a string identifying this event
+ */
+ public String paramString()
+ {
+ return (id == INVOCATION_DEFAULT ? "INVOCATION_DEFAULT,runnable="
+ : "unknown type,runnable=") + runnable + ",notifier=" + notifier
+ + ",catchExceptions=" + catchExceptions + ",when=" + when;
+ }
+} // class InvocationEvent
diff --git a/libjava/classpath/java/awt/event/ItemEvent.java b/libjava/classpath/java/awt/event/ItemEvent.java
new file mode 100644
index 000000000..467815b16
--- /dev/null
+++ b/libjava/classpath/java/awt/event/ItemEvent.java
@@ -0,0 +1,155 @@
+/* ItemEvent.java -- event for item state changes
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.AWTEvent;
+import java.awt.ItemSelectable;
+
+/**
+ * This event is generated when a selection item changes state. This is an
+ * abstraction that distills a large number of individual mouse or keyboard
+ * events into a simpler "item selected" and "item deselected" events.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see ItemSelectable
+ * @see ItemListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class ItemEvent extends AWTEvent
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -608708132447206933L;
+
+ /** This is the first id in the event id range used by this class. */
+ public static final int ITEM_FIRST = 701;
+
+ /** This is the last id in the event id range used by this class. */
+ public static final int ITEM_LAST = 701;
+
+ /** This event id indicates a state change occurred. */
+ public static final int ITEM_STATE_CHANGED = 701;
+
+ /** This type indicates that the item was selected. */
+ public static final int SELECTED = 1;
+
+ /** This type indicates that the item was deselected. */
+ public static final int DESELECTED = 2;
+
+ /**
+ * The item affected by this event.
+ *
+ * @serial the item of the selection
+ */
+ private final Object item;
+
+ /**
+ * The state change direction, one of {@link #SELECTED} or
+ * {@link #DESELECTED}.
+ *
+ * @serial the selection state
+ */
+ private final int stateChange;
+
+ /**
+ * Initializes a new instance of <code>ItemEvent</code> with the specified
+ * source, id, and state change constant. Note that an invalid id leads to
+ * unspecified results.
+ *
+ * @param source the source of the event
+ * @param id the event id
+ * @param item the item affected by the state change
+ * @param stateChange one of {@link #SELECTED} or {@link #DESELECTED}
+ */
+ public ItemEvent(ItemSelectable source, int id, Object item, int stateChange)
+ {
+ super(source, id);
+ this.item = item;
+ this.stateChange = stateChange;
+ }
+
+ /**
+ * This method returns the event source as an <code>ItemSelectable</code>.
+ *
+ * @return the event source as an <code>ItemSelected</code>
+ * @throws ClassCastException if source is changed to a non-ItemSelectable
+ */
+ public ItemSelectable getItemSelectable()
+ {
+ return (ItemSelectable) source;
+ }
+
+ /**
+ * Returns the item affected by this state change.
+ *
+ * @return the item affected by this state change
+ */
+ public Object getItem()
+ {
+ return item;
+ }
+
+ /**
+ * Returns the type of state change, either {@link #SELECTED} or
+ * {@link #DESELECTED}.
+ *
+ * @return the type of state change
+ */
+ public int getStateChange()
+ {
+ return stateChange;
+ }
+
+ /**
+ * Returns a string identifying this event. This is in the format:
+ * <code>"ITEM_STATE_CHANGED,item=" + item + ",stateChange="
+ * + (getStateChange() == DESELECTED ? "DESELECTED" : "SELECTED")</code>.
+ *
+ * @return a string identifying this event
+ */
+ public String paramString()
+ {
+ return (id == ITEM_STATE_CHANGED ? "ITEM_STATE_CHANGED,item="
+ : "unknown type,item=") + item + ",stateChange="
+ + (stateChange == SELECTED ? "SELECTED"
+ : stateChange == DESELECTED ? "DESELECTED" : "unknown type");
+ }
+} // class ItemEvent
diff --git a/libjava/classpath/java/awt/event/ItemListener.java b/libjava/classpath/java/awt/event/ItemListener.java
new file mode 100644
index 000000000..fa5f3aad3
--- /dev/null
+++ b/libjava/classpath/java/awt/event/ItemListener.java
@@ -0,0 +1,62 @@
+/* ItemListener.java -- listen for item events
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.ItemSelectable;
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that wish to receive events when an
+ * item's selection state changes.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see ItemSelectable
+ * @see ItemEvent
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface ItemListener extends EventListener
+{
+ /**
+ * This method is called when an item's state is changed.
+ *
+ * @param event the <code>ItemEvent</code> indicating the change
+ */
+ void itemStateChanged(ItemEvent event);
+} // interface ItemListener
diff --git a/libjava/classpath/java/awt/event/KeyAdapter.java b/libjava/classpath/java/awt/event/KeyAdapter.java
new file mode 100644
index 000000000..c01d61ff3
--- /dev/null
+++ b/libjava/classpath/java/awt/event/KeyAdapter.java
@@ -0,0 +1,88 @@
+/* KeyAdapter.java -- convenience class for writing key listeners
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+/**
+ * This class implements <code>KeyListener</code> and implements all methods
+ * with empty bodies. This allows a listener interested in implementing only
+ * a subset of the <code>KeyListener</code> interface to extend this class
+ * and override only the desired methods.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see KeyEvent
+ * @see KeyListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class KeyAdapter implements KeyListener
+{
+ /**
+ * Do nothing default constructor for subclasses.
+ */
+ public KeyAdapter()
+ {
+ }
+
+ /**
+ * Implements this method in the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void keyTyped(KeyEvent event)
+ {
+ }
+
+ /**
+ * Implements this method in the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void keyPressed(KeyEvent event)
+ {
+ }
+
+ /**
+ * Implements this method in the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void keyReleased(KeyEvent event)
+ {
+ }
+} // class KeyAdapter
diff --git a/libjava/classpath/java/awt/event/KeyEvent.java b/libjava/classpath/java/awt/event/KeyEvent.java
new file mode 100644
index 000000000..a2b1dc94c
--- /dev/null
+++ b/libjava/classpath/java/awt/event/KeyEvent.java
@@ -0,0 +1,1762 @@
+/* KeyEvent.java -- event for key presses
+ Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import gnu.java.awt.EventModifier;
+import gnu.java.lang.CPStringBuilder;
+
+import java.awt.Component;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+
+/**
+ * This event is generated when a key is pressed or released. There are two
+ * categories of key events:
+ *
+ * <p><em>"Key typed" events</em> are higher-level, and have already
+ * compensated for modifiers and keyboard layout to generate a single Unicode
+ * character. It may take several key press events to generate one key typed.
+ * The <code>getKeyCode</code> method will return <code>VK_UNDEFINED</code>,
+ * and <code>getKeyChar</code> will return a valid Unicode character or
+ * <code>CHAR_UNDEFINED</code>.
+ *
+ * <p><em>"Key pressed" and "key released" events</em> are lower-level, and
+ * are platform and keyboard dependent. They correspond to the actaul motion
+ * on a keyboard, and return a virtual key code which labels the key that was
+ * pressed. The <code>getKeyCode</code> method will return one of the
+ * <code>VK_*</code> constants (except VK_UNDEFINED), and the
+ * <code>getKeyChar</code> method is undefined.
+ *
+ * <p>Some keys do not generate key typed events, such as the F1 or HELP keys.
+ * Not all keyboards can generate all virtual keys, and no attempt is made to
+ * simulate the ones that can't be typed. Virtual keys correspond to the
+ * keyboard layout, so for example, VK_Q in English is VK_A in French. Also,
+ * there are some additional virtual keys to ease handling of actions, such
+ * as VK_ALL_CANDIDATES in place of ALT+VK_CONVERT. Do not rely on the value
+ * of the VK_* constants, except for VK_ENTER, VK_BACK_SPACE, and VK_TAB.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see KeyAdapter
+ * @see KeyListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class KeyEvent extends InputEvent
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -2352130953028126954L;
+
+ /** This is the first id in the range of event ids used by this class. */
+ public static final int KEY_FIRST = 400;
+
+ /** This is the last id in the range of event ids used by this class. */
+ public static final int KEY_LAST = 402;
+
+ /**
+ * This event id indicates a key was typed, which is a key press followed
+ * by a key release to generate an actual Unicode character. It may take
+ * several key presses to generate one key typed event, and some action
+ * keys have no corresponding key typed.
+ */
+ public static final int KEY_TYPED = 400;
+
+ /** This event id indicates a key was pressed. */
+ public static final int KEY_PRESSED = 401;
+
+ /** This event it indicates a key was released. */
+ public static final int KEY_RELEASED = 402;
+
+ /** The virtual key Enter, which will always map to '\n'. */
+ public static final int VK_ENTER = '\n';
+
+ /** The virtual key Backspace, which will always map to '\b'. */
+ public static final int VK_BACK_SPACE = '\b';
+
+ /** The virtual key Tab, which will always map to '\t'. */
+ public static final int VK_TAB = '\t';
+
+ /** The virtual key Cancel. */
+ public static final int VK_CANCEL = 3;
+
+ /** The virtual key VK_CLEAR. */
+ public static final int VK_CLEAR = 12;
+
+ /** The virtual key VK_SHIFT. */
+ public static final int VK_SHIFT = 16;
+
+ /** The virtual key VK_CONTROL. */
+ public static final int VK_CONTROL = 17;
+
+ /** The virtual key VK_ALT. */
+ public static final int VK_ALT = 18;
+
+ /** The virtual key VK_PAUSE. */
+ public static final int VK_PAUSE = 19;
+
+ /** The virtual key VK_CAPS_LOCK. */
+ public static final int VK_CAPS_LOCK = 20;
+
+ /** The virtual key VK_ESCAPE. */
+ public static final int VK_ESCAPE = 27;
+
+ /** The virtual key VK_SPACE. */
+ public static final int VK_SPACE = ' ';
+
+ /** The virtual key VK_PAGE_UP. */
+ public static final int VK_PAGE_UP = 33;
+
+ /** The virtual key VK_PAGE_DOWN. */
+ public static final int VK_PAGE_DOWN = 34;
+
+ /** The virtual key VK_END. */
+ public static final int VK_END = 35;
+
+ /** The virtual key VK_HOME. */
+ public static final int VK_HOME = 36;
+
+ /**
+ * The virtual key for the non-numpad VK_LEFT.
+ *
+ * @see #VK_KP_LEFT
+ */
+ public static final int VK_LEFT = 37;
+
+ /**
+ * The virtual key for the non-numpad VK_UP.
+ *
+ * @see #VK_KP_UP
+ */
+ public static final int VK_UP = 38;
+
+ /**
+ * The virtual key for the non-numpad VK_RIGHT.
+ *
+ * @see #VK_KP_RIGHT
+ */
+ public static final int VK_RIGHT = 39;
+
+ /**
+ * The virtual key for the non-numpad VK_DOWN.
+ *
+ * @see #VK_KP_DOWN
+ */
+ public static final int VK_DOWN = 40;
+
+ /** The virtual key VK_COMMA. */
+ public static final int VK_COMMA = ',';
+
+ /**
+ * The virtual key VK_MINUS.
+ *
+ * @since 1.2
+ */
+ public static final int VK_MINUS = '-';
+
+ /** The virtual key VK_PERIOD. */
+ public static final int VK_PERIOD = '.';
+
+ /** The virtual key VK_SLASH. */
+ public static final int VK_SLASH = '/';
+
+ /** The virtual key VK_0. */
+ public static final int VK_0 = '0';
+
+ /** The virtual key VK_1. */
+ public static final int VK_1 = '1';
+
+ /** The virtual key VK_2. */
+ public static final int VK_2 = '2';
+
+ /** The virtual key VK_3. */
+ public static final int VK_3 = '3';
+
+ /** The virtual key VK_4. */
+ public static final int VK_4 = '4';
+
+ /** The virtual key VK_5. */
+ public static final int VK_5 = '5';
+
+ /** The virtual key VK_6. */
+ public static final int VK_6 = '6';
+
+ /** The virtual key VK_7. */
+ public static final int VK_7 = '7';
+
+ /** The virtual key VK_8. */
+ public static final int VK_8 = '8';
+
+ /** The virtual key VK_9. */
+ public static final int VK_9 = '9';
+
+ /** The virtual key VK_SEMICOLON. */
+ public static final int VK_SEMICOLON = ';';
+
+ /** The virtual key VK_EQUALS. */
+ public static final int VK_EQUALS = '=';
+
+ /** The virtual key VK_A. */
+ public static final int VK_A = 'A';
+
+ /** The virtual key VK_B. */
+ public static final int VK_B = 'B';
+
+ /** The virtual key VK_C. */
+ public static final int VK_C = 'C';
+
+ /** The virtual key VK_D. */
+ public static final int VK_D = 'D';
+
+ /** The virtual key VK_E. */
+ public static final int VK_E = 'E';
+
+ /** The virtual key VK_F. */
+ public static final int VK_F = 'F';
+
+ /** The virtual key VK_G. */
+ public static final int VK_G = 'G';
+
+ /** The virtual key VK_H. */
+ public static final int VK_H = 'H';
+
+ /** The virtual key VK_I. */
+ public static final int VK_I = 'I';
+
+ /** The virtual key VK_J. */
+ public static final int VK_J = 'J';
+
+ /** The virtual key VK_K. */
+ public static final int VK_K = 'K';
+
+ /** The virtual key VK_L. */
+ public static final int VK_L = 'L';
+
+ /** The virtual key VK_M. */
+ public static final int VK_M = 'M';
+
+ /** The virtual key VK_N. */
+ public static final int VK_N = 'N';
+
+ /** The virtual key VK_O. */
+ public static final int VK_O = 'O';
+
+ /** The virtual key VK_P. */
+ public static final int VK_P = 'P';
+
+ /** The virtual key VK_Q. */
+ public static final int VK_Q = 'Q';
+
+ /** The virtual key VK_R. */
+ public static final int VK_R = 'R';
+
+ /** The virtual key VK_S. */
+ public static final int VK_S = 'S';
+
+ /** The virtual key VK_T. */
+ public static final int VK_T = 'T';
+
+ /** The virtual key VK_U. */
+ public static final int VK_U = 'U';
+
+ /** The virtual key VK_V. */
+ public static final int VK_V = 'V';
+
+ /** The virtual key VK_W. */
+ public static final int VK_W = 'W';
+
+ /** The virtual key VK_X. */
+ public static final int VK_X = 'X';
+
+ /** The virtual key VK_Y. */
+ public static final int VK_Y = 'Y';
+
+ /** The virtual key VK_Z. */
+ public static final int VK_Z = 'Z';
+
+ /** The virtual key VK_OPEN_BRACKET. */
+ public static final int VK_OPEN_BRACKET = '[';
+
+ /** The virtual key VK_BACK_SLASH. */
+ public static final int VK_BACK_SLASH = '\\';
+
+ /** The virtual key VK_CLOSE_BRACKET. */
+ public static final int VK_CLOSE_BRACKET = ']';
+
+ /** The virtual key VK_NUMPAD0. */
+ public static final int VK_NUMPAD0 = 96;
+
+ /** The virtual key VK_NUMPAD1. */
+ public static final int VK_NUMPAD1 = 97;
+
+ /** The virtual key VK_NUMPAD2. */
+ public static final int VK_NUMPAD2 = 98;
+
+ /** The virtual key VK_NUMPAD3. */
+ public static final int VK_NUMPAD3 = 99;
+
+ /** The virtual key VK_NUMPAD4. */
+ public static final int VK_NUMPAD4 = 100;
+
+ /** The virtual key VK_NUMPAD5. */
+ public static final int VK_NUMPAD5 = 101;
+
+ /** The virtual key VK_NUMPAD6. */
+ public static final int VK_NUMPAD6 = 102;
+
+ /** The virtual key VK_NUMPAD7. */
+ public static final int VK_NUMPAD7 = 103;
+
+ /** The virtual key VK_NUMPAD8. */
+ public static final int VK_NUMPAD8 = 104;
+
+ /** The virtual key VK_NUMPAD9. */
+ public static final int VK_NUMPAD9 = 105;
+
+ /** The virtual key VK_MULTIPLY. */
+ public static final int VK_MULTIPLY = 106;
+
+ /** The virtual key VK_ADD. */
+ public static final int VK_ADD = 107;
+
+ /**
+ * The virtual key VK_SEPARATOR, handily mispelled for those who can't
+ * figure it out.
+ *
+ * @deprecated use {@link #VK_SEPARATOR}
+ */
+ public static final int VK_SEPARATER = 108;
+
+ /**
+ * The virtual key VK_SEPARATOR.
+ *
+ * @since 1.4
+ */
+ public static final int VK_SEPARATOR = 108;
+
+ /** The virtual key VK_SUBTRACT. */
+ public static final int VK_SUBTRACT = 109;
+
+ /** The virtual key VK_DECIMAL. */
+ public static final int VK_DECIMAL = 110;
+
+ /** The virtual key VK_DIVIDE. */
+ public static final int VK_DIVIDE = 111;
+
+ /** The virtual key VK_DELETE. */
+ public static final int VK_DELETE = 127;
+
+ /** The virtual key VK_NUM_LOCK. */
+ public static final int VK_NUM_LOCK = 144;
+
+ /** The virtual key VK_SCROLL_LOCK. */
+ public static final int VK_SCROLL_LOCK = 145;
+
+ /** The virtual key VK_F1. */
+ public static final int VK_F1 = 112;
+
+ /** The virtual key VK_F2. */
+ public static final int VK_F2 = 113;
+
+ /** The virtual key VK_F3. */
+ public static final int VK_F3 = 114;
+
+ /** The virtual key VK_F4. */
+ public static final int VK_F4 = 115;
+
+ /** The virtual key VK_F5. */
+ public static final int VK_F5 = 116;
+
+ /** The virtual key VK_F6. */
+ public static final int VK_F6 = 117;
+
+ /** The virtual key VK_F7. */
+ public static final int VK_F7 = 118;
+
+ /** The virtual key VK_F8. */
+ public static final int VK_F8 = 119;
+
+ /** The virtual key VK_F9. */
+ public static final int VK_F9 = 120;
+
+ /** The virtual key VK_F10. */
+ public static final int VK_F10 = 121;
+
+ /** The virtual key VK_F11. */
+ public static final int VK_F11 = 122;
+
+ /** The virtual key VK_F12. */
+ public static final int VK_F12 = 123;
+
+ /**
+ * The virtual key VK_F13.
+ *
+ * @since 1.2
+ */
+ public static final int VK_F13 = 61440;
+
+ /**
+ * The virtual key VK_F14.
+ *
+ * @since 1.2
+ */
+ public static final int VK_F14 = 61441;
+
+ /**
+ * The virtual key VK_F15.
+ *
+ * @since 1.2
+ */
+ public static final int VK_F15 = 61442;
+
+ /**
+ * The virtual key VK_F16.
+ *
+ * @since 1.2
+ */
+ public static final int VK_F16 = 61443;
+
+ /**
+ * The virtual key VK_F17.
+ *
+ * @since 1.2
+ */
+ public static final int VK_F17 = 61444;
+
+ /**
+ * The virtual key VK_F18.
+ *
+ * @since 1.2
+ */
+ public static final int VK_F18 = 61445;
+
+ /**
+ * The virtual key VK_F19.
+ *
+ * @since 1.2
+ */
+ public static final int VK_F19 = 61446;
+
+ /**
+ * The virtual key VK_F20.
+ *
+ * @since 1.2
+ */
+ public static final int VK_F20 = 61447;
+
+ /**
+ * The virtual key VK_F21.
+ *
+ * @since 1.2
+ */
+ public static final int VK_F21 = 61448;
+
+ /**
+ * The virtual key VK_F22.
+ *
+ * @since 1.2
+ */
+ public static final int VK_F22 = 61449;
+
+ /**
+ * The virtual key VK_F23.
+ *
+ * @since 1.2
+ */
+ public static final int VK_F23 = 61450;
+
+ /**
+ * The virtual key VK_F24.
+ *
+ * @since 1.2
+ */
+ public static final int VK_F24 = 61451;
+
+ /** The virtual key VK_PRINTSCREEN. */
+ public static final int VK_PRINTSCREEN = 154;
+
+ /** The virtual key VK_INSERT. */
+ public static final int VK_INSERT = 155;
+
+ /** The virtual key VK_HELP. */
+ public static final int VK_HELP = 156;
+
+ /** The virtual key VK_META. */
+ public static final int VK_META = 157;
+
+ /** The virtual key VK_BACK_QUOTE. */
+ public static final int VK_BACK_QUOTE = 192;
+
+ /** The virtual key VK_QUOTE. */
+ public static final int VK_QUOTE = 222;
+
+ /**
+ * The virtual key for the numpad VK_KP_UP.
+ *
+ * @see #VK_UP
+ * @since 1.2
+ */
+ public static final int VK_KP_UP = 224;
+
+ /**
+ * The virtual key for the numpad VK_KP_DOWN.
+ *
+ * @see #VK_DOWN
+ * @since 1.2
+ */
+ public static final int VK_KP_DOWN = 225;
+
+ /**
+ * The virtual key for the numpad VK_KP_LEFT.
+ *
+ * @see #VK_LEFT
+ * @since 1.2
+ */
+ public static final int VK_KP_LEFT = 226;
+
+ /**
+ * The virtual key for the numpad VK_KP_RIGHT.
+ *
+ * @see #VK_RIGHT
+ * @since 1.2
+ */
+ public static final int VK_KP_RIGHT = 227;
+
+ /**
+ * The virtual key VK_DEAD_GRAVE.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_GRAVE = 128;
+
+ /**
+ * The virtual key VK_DEAD_ACUTE.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_ACUTE = 129;
+
+ /**
+ * The virtual key VK_DEAD_CIRCUMFLEX.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_CIRCUMFLEX = 130;
+
+ /**
+ * The virtual key VK_DEAD_TILDE.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_TILDE = 131;
+
+ /**
+ * The virtual key VK_DEAD_MACRON.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_MACRON = 132;
+
+ /**
+ * The virtual key VK_DEAD_BREVE.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_BREVE = 133;
+
+ /**
+ * The virtual key VK_DEAD_ABOVEDOT.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_ABOVEDOT = 134;
+
+ /**
+ * The virtual key VK_DEAD_DIAERESIS.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_DIAERESIS = 135;
+
+ /**
+ * The virtual key VK_DEAD_ABOVERING.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_ABOVERING = 136;
+
+ /**
+ * The virtual key VK_DEAD_DOUBLEACUTE.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_DOUBLEACUTE = 137;
+
+ /**
+ * The virtual key VK_DEAD_CARON.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_CARON = 138;
+
+ /**
+ * The virtual key VK_DEAD_CEDILLA.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_CEDILLA = 139;
+
+ /**
+ * The virtual key VK_DEAD_OGONEK.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_OGONEK = 140;
+
+ /**
+ * The virtual key VK_DEAD_IOTA.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_IOTA = 141;
+
+ /**
+ * The virtual key VK_DEAD_VOICED_SOUND.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_VOICED_SOUND = 142;
+
+ /**
+ * The virtual key VK_DEAD_SEMIVOICED_SOUND.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DEAD_SEMIVOICED_SOUND = 143;
+
+ /**
+ * The virtual key VK_AMPERSAND.
+ *
+ * @since 1.2
+ */
+ public static final int VK_AMPERSAND = 150;
+
+ /**
+ * The virtual key VK_ASTERISK.
+ *
+ * @since 1.2
+ */
+ public static final int VK_ASTERISK = 151;
+
+ /**
+ * The virtual key VK_QUOTEDBL.
+ *
+ * @since 1.2
+ */
+ public static final int VK_QUOTEDBL = 152;
+
+ /**
+ * The virtual key VK_LESS.
+ *
+ * @since 1.2
+ */
+ public static final int VK_LESS = 153;
+
+ /**
+ * The virtual key VK_GREATER.
+ *
+ * @since 1.2
+ */
+ public static final int VK_GREATER = 160;
+
+ /**
+ * The virtual key VK_BRACELEFT.
+ *
+ * @since 1.2
+ */
+ public static final int VK_BRACELEFT = 161;
+
+ /**
+ * The virtual key VK_BRACERIGHT.
+ *
+ * @since 1.2
+ */
+ public static final int VK_BRACERIGHT = 162;
+
+ /**
+ * The virtual key VK_AT.
+ *
+ * @since 1.2
+ */
+ public static final int VK_AT = 512;
+
+ /**
+ * The virtual key VK_COLON.
+ *
+ * @since 1.2
+ */
+ public static final int VK_COLON = 513;
+
+ /**
+ * The virtual key VK_CIRCUMFLEX.
+ *
+ * @since 1.2
+ */
+ public static final int VK_CIRCUMFLEX = 514;
+
+ /**
+ * The virtual key VK_DOLLAR.
+ *
+ * @since 1.2
+ */
+ public static final int VK_DOLLAR = 515;
+
+ /**
+ * The virtual key VK_EURO_SIGN.
+ *
+ * @since 1.2
+ */
+ public static final int VK_EURO_SIGN = 516;
+
+ /**
+ * The virtual key VK_EXCLAMATION_MARK.
+ *
+ * @since 1.2
+ */
+ public static final int VK_EXCLAMATION_MARK = 517;
+
+ /**
+ * The virtual key VK_INVERTED_EXCLAMATION_MARK.
+ *
+ * @since 1.2
+ */
+ public static final int VK_INVERTED_EXCLAMATION_MARK = 518;
+
+ /**
+ * The virtual key VK_LEFT_PARENTHESIS.
+ *
+ * @since 1.2
+ */
+ public static final int VK_LEFT_PARENTHESIS = 519;
+
+ /**
+ * The virtual key VK_NUMBER_SIGN.
+ *
+ * @since 1.2
+ */
+ public static final int VK_NUMBER_SIGN = 520;
+
+ /**
+ * The virtual key VK_PLUS.
+ *
+ * @since 1.2
+ */
+ public static final int VK_PLUS = 521;
+
+ /**
+ * The virtual key VK_RIGHT_PARENTHESIS.
+ *
+ * @since 1.2
+ */
+ public static final int VK_RIGHT_PARENTHESIS = 522;
+
+ /**
+ * The virtual key VK_UNDERSCORE.
+ *
+ * @since 1.2
+ */
+ public static final int VK_UNDERSCORE = 523;
+
+ /** The virtual key VK_FINAL. */
+ public static final int VK_FINAL = 24;
+
+ /** The virtual key VK_CONVERT. */
+ public static final int VK_CONVERT = 28;
+
+ /** The virtual key VK_NONCONVERT. */
+ public static final int VK_NONCONVERT = 29;
+
+ /** The virtual key VK_ACCEPT. */
+ public static final int VK_ACCEPT = 30;
+
+ /** The virtual key VK_MODECHANGE. */
+ public static final int VK_MODECHANGE = 31;
+
+ /** The virtual key VK_KANA. */
+ public static final int VK_KANA = 21;
+
+ /** The virtual key VK_KANJI. */
+ public static final int VK_KANJI = 25;
+
+ /**
+ * The virtual key VK_ALPHANUMERIC.
+ *
+ * @since 1.2
+ */
+ public static final int VK_ALPHANUMERIC = 240;
+
+ /**
+ * The virtual key VK_KATAKANA.
+ *
+ * @since 1.2
+ */
+ public static final int VK_KATAKANA = 241;
+
+ /**
+ * The virtual key VK_HIRAGANA.
+ *
+ * @since 1.2
+ */
+ public static final int VK_HIRAGANA = 242;
+
+ /**
+ * The virtual key VK_FULL_WIDTH.
+ *
+ * @since 1.2
+ */
+ public static final int VK_FULL_WIDTH = 243;
+
+ /**
+ * The virtual key VK_HALF_WIDTH.
+ *
+ * @since 1.2
+ */
+ public static final int VK_HALF_WIDTH = 244;
+
+ /**
+ * The virtual key VK_ROMAN_CHARACTERS.
+ *
+ * @since 1.2
+ */
+ public static final int VK_ROMAN_CHARACTERS = 245;
+
+ /**
+ * The virtual key VK_ALL_CANDIDATES.
+ *
+ * @since 1.2
+ */
+ public static final int VK_ALL_CANDIDATES = 256;
+
+ /**
+ * The virtual key VK_PREVIOUS_CANDIDATE.
+ *
+ * @since 1.2
+ */
+ public static final int VK_PREVIOUS_CANDIDATE = 257;
+
+ /**
+ * The virtual key VK_CODE_INPUT.
+ *
+ * @since 1.2
+ */
+ public static final int VK_CODE_INPUT = 258;
+
+ /**
+ * The virtual key VK_JAPANESE_KATAKANA.
+ *
+ * @since 1.2
+ */
+ public static final int VK_JAPANESE_KATAKANA = 259;
+
+ /**
+ * The virtual key VK_JAPANESE_HIRAGANA.
+ *
+ * @since 1.2
+ */
+ public static final int VK_JAPANESE_HIRAGANA = 260;
+
+ /**
+ * The virtual key VK_JAPANESE_ROMAN.
+ *
+ * @since 1.2
+ */
+ public static final int VK_JAPANESE_ROMAN = 261;
+
+ /**
+ * The virtual key VK_KANA_LOCK.
+ *
+ * @since 1.3
+ */
+ public static final int VK_KANA_LOCK = 262;
+
+ /**
+ * The virtual key VK_INPUT_METHOD_ON_OFF.
+ *
+ * @since 1.3
+ */
+ public static final int VK_INPUT_METHOD_ON_OFF = 263;
+
+ /**
+ * The virtual key VK_CUT.
+ *
+ * @since 1.2
+ */
+ public static final int VK_CUT = 65489;
+
+ /**
+ * The virtual key VK_COPY.
+ *
+ * @since 1.2
+ */
+ public static final int VK_COPY = 65485;
+
+ /**
+ * The virtual key VK_PASTE.
+ *
+ * @since 1.2
+ */
+ public static final int VK_PASTE = 65487;
+
+ /**
+ * The virtual key VK_UNDO.
+ *
+ * @since 1.2
+ */
+ public static final int VK_UNDO = 65483;
+
+ /**
+ * The virtual key VK_AGAIN.
+ *
+ * @since 1.2
+ */
+ public static final int VK_AGAIN = 65481;
+
+ /**
+ * The virtual key VK_FIND.
+ *
+ * @since 1.2
+ */
+ public static final int VK_FIND = 65488;
+
+ /**
+ * The virtual key VK_PROPS.
+ *
+ * @since 1.2
+ */
+ public static final int VK_PROPS = 65482;
+
+ /**
+ * The virtual key VK_STOP.
+ *
+ * @since 1.2
+ */
+ public static final int VK_STOP = 65480;
+
+ /**
+ * The virtual key VK_COMPOSE.
+ *
+ * @since 1.2
+ */
+ public static final int VK_COMPOSE = 65312;
+
+ /**
+ * The virtual key VK_ALT_GRAPH.
+ *
+ * @since 1.2
+ */
+ public static final int VK_ALT_GRAPH = 65406;
+
+ /**
+ * The 'begin' key VK_BEGIN
+ *
+ * @since 1.5
+ */
+ public static final int VK_BEGIN = 65368;
+
+ /**
+ * The context-menu key VK_CONTEXT_MENU
+ *
+ * @since 1.5
+ */
+ public static final int VK_CONTEXT_MENU = 525;
+
+ /**
+ * The 'Windows' key VK_WINDOWS
+ *
+ * @since 1.5
+ */
+ public static final int VK_WINDOWS = 524;
+
+ /**
+ * The virtual key VK_UNDEFINED. This is used for key typed events, which
+ * do not have a virtual key.
+ */
+ public static final int VK_UNDEFINED = 0;
+
+ /**
+ * The only char with no valid Unicode interpretation. This is used for
+ * key pressed and key released events which do not have a valid keyChar.
+ */
+ public static final char CHAR_UNDEFINED = '\uffff';
+
+ /**
+ * Indicates unknown or irrelavent key location. This is also used for
+ * key typed events, which do not need a location.
+ *
+ * @since 1.4
+ */
+ public static final int KEY_LOCATION_UNKNOWN = 0;
+
+ /**
+ * Indicates a standard key location, with no left/right variants and not
+ * on the numeric pad.
+ *
+ * @since 1.4
+ */
+ public static final int KEY_LOCATION_STANDARD = 1;
+
+ /**
+ * Indicates the key is on the left side of the keyboard, such as the left
+ * shift.
+ *
+ * @since 1.4
+ */
+ public static final int KEY_LOCATION_LEFT = 2;
+
+ /**
+ * Indicates the key is on the right side of the keyboard, such as the right
+ * shift.
+ *
+ * @since 1.4
+ */
+ public static final int KEY_LOCATION_RIGHT = 3;
+
+ /**
+ * Indicates the key is on the numeric pad, such as the numpad 0.
+ *
+ * @since 1.4
+ */
+ public static final int KEY_LOCATION_NUMPAD = 4;
+
+ /**
+ * The code assigned to the physical keyboard location (as adjusted by the
+ * keyboard layout). Use the symbolic VK_* names instead of numbers.
+ *
+ * @see #getKeyCode()
+ * @serial the VK_ code for this key
+ */
+ private int keyCode;
+
+ /**
+ * The Unicode character produced by the key type event. This has no meaning
+ * for key pressed and key released events.
+ *
+ * @see #getKeyChar()
+ * @serial the Unicode value for this key
+ */
+ private char keyChar;
+
+ /**
+ * The keyboard location of the key. One of {@link #KEY_LOCATION_UNKNOWN},
+ * {@link #KEY_LOCATION_STANDARD}, {@link #KEY_LOCATION_LEFT},
+ * {@link #KEY_LOCATION_RIGHT}, or {@link #KEY_LOCATION_NUMPAD}.
+ *
+ * @see #getKeyLocation()
+ * @serial the key location
+ * @since 1.4
+ */
+ private final int keyLocation;
+
+ /**
+ * Stores the state of the native event dispatching system, to correctly
+ * dispatch in Component#dispatchEventImpl when a proxy is active.
+ *
+ * XXX Does this matter in Classpath?
+ *
+ * @serial whether the proxy is active
+ */
+ private boolean isProxyActive;
+
+
+ /**
+ * Initializes a new instance of <code>KeyEvent</code> with the specified
+ * information. Note that an invalid id leads to unspecified results.
+ *
+ * @param source the component that generated this event
+ * @param id the event id
+ * @param when the timestamp when the even occurred
+ * @param modifiers the modifier keys during the event, in old or new style
+ * @param keyCode the integer constant for the virtual key type
+ * @param keyChar the Unicode value of the key
+ * @param keyLocation the location of the key
+ * @throws IllegalArgumentException if source is null, if keyLocation is
+ * invalid, or if (id == KEY_TYPED && (keyCode != VK_UNDEFINED
+ * || keyChar == CHAR_UNDEFINED))
+ */
+ public KeyEvent(Component source, int id, long when, int modifiers,
+ int keyCode, char keyChar, int keyLocation)
+ {
+ super(source, id, when, modifiers);
+ this.keyCode = keyCode;
+ this.keyChar = keyChar;
+ this.keyLocation = keyLocation;
+ if ((id == KEY_TYPED && (keyCode != VK_UNDEFINED
+ || keyChar == CHAR_UNDEFINED))
+ || keyLocation < KEY_LOCATION_UNKNOWN
+ || keyLocation > KEY_LOCATION_NUMPAD)
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Initializes a new instance of <code>KeyEvent</code> with the specified
+ * information. Note that an invalid id leads to unspecified results.
+ *
+ * @param source the component that generated this event
+ * @param id the event id
+ * @param when the timestamp when the even occurred
+ * @param modifiers the modifier keys during the event, in old or new style
+ * @param keyCode the integer constant for the virtual key type
+ * @param keyChar the Unicode value of the key
+ * @throws IllegalArgumentException if source is null, or if
+ * (id == KEY_TYPED && (keyCode != VK_UNDEFINED
+ * || keyChar == CHAR_UNDEFINED))
+ */
+ public KeyEvent(Component source, int id, long when, int modifiers,
+ int keyCode, char keyChar)
+ {
+ this(source, id, when, modifiers, keyCode, keyChar, KEY_LOCATION_UNKNOWN);
+ }
+
+ /**
+ * Initializes a new instance of <code>KeyEvent</code> with the specified
+ * information. Note that an invalid id leads to unspecified results.
+ *
+ * @param source the component that generated this event
+ * @param id the event id
+ * @param when the timestamp when the even occurred
+ * @param modifiers the modifier keys during the event, in old or new style
+ * @param keyCode the integer constant for the virtual key type
+ * @throws IllegalArgumentException if source is null, or if
+ * id == KEY_TYPED but keyCode != VK_UNDEFINED
+ *
+ * @deprecated
+ */
+ public KeyEvent(Component source, int id, long when, int modifiers,
+ int keyCode)
+ {
+ this(source, id, when, modifiers, keyCode, '\0', KEY_LOCATION_UNKNOWN);
+ }
+
+ /**
+ * Returns the key code for the event key. This will be one of the
+ * <code>VK_*</code> constants defined in this class. If the event type is
+ * KEY_TYPED, the result will be VK_UNDEFINED.
+ *
+ * @return the key code for this event
+ */
+ public int getKeyCode()
+ {
+ return keyCode;
+ }
+
+ /**
+ * Sets the key code for this event. This must be one of the
+ * <code>VK_*</code> constants defined in this class.
+ *
+ * @param keyCode the new key code for this event
+ */
+ public void setKeyCode(int keyCode)
+ {
+ this.keyCode = keyCode;
+ }
+
+ /**
+ * Returns the Unicode value for the event key. This will be
+ * <code>CHAR_UNDEFINED</code> if there is no Unicode equivalent for
+ * this key, usually when this is a KEY_PRESSED or KEY_RELEASED event.
+ *
+ * @return the Unicode character for this event
+ */
+ public char getKeyChar()
+ {
+ return keyChar;
+ }
+
+ /**
+ * Sets the Unicode character for this event to the specified value.
+ *
+ * @param keyChar the new Unicode character for this event
+ */
+ public void setKeyChar(char keyChar)
+ {
+ this.keyChar = keyChar;
+ }
+
+ /**
+ * Sets the modifier keys to the specified value. This should be a union
+ * of the bit mask constants from <code>InputEvent</code>. The use of this
+ * method is not recommended, particularly for KEY_TYPED events, which do
+ * not check if the modifiers were changed.
+ *
+ * @param modifiers the new modifier value, in either old or new style
+ * @see InputEvent
+ *
+ * @deprecated
+ */
+ public void setModifiers(int modifiers)
+ {
+ this.modifiers = EventModifier.extend(modifiers);
+ }
+
+ /**
+ * Returns the keyboard location of the key that generated this event. This
+ * provides a way to distinguish between keys like left and right shift
+ * which share a common key code. The result will be one of
+ * {@link #KEY_LOCATION_UNKNOWN}, {@link #KEY_LOCATION_STANDARD},
+ * {@link #KEY_LOCATION_LEFT}, {@link #KEY_LOCATION_RIGHT}, or
+ * {@link #KEY_LOCATION_NUMPAD}.
+ *
+ * @return the key location
+ * @since 1.4
+ */
+ public int getKeyLocation()
+ {
+ return keyLocation;
+ }
+
+ /**
+ * Returns the text name of key code, such as "HOME", "F1", or "A".
+ *
+ * XXX Sun claims this can be localized via the awt.properties file - how
+ * do we implement that?
+ *
+ * @return the text name of the key code
+ */
+ public static String getKeyText(int keyCode)
+ {
+ switch (keyCode)
+ {
+ case VK_CANCEL:
+ return "Cancel";
+ case VK_BACK_SPACE:
+ return "Backspace";
+ case VK_TAB:
+ return "Tab";
+ case VK_ENTER:
+ return "Enter";
+ case VK_CLEAR:
+ return "Clear";
+ case VK_SHIFT:
+ return "Shift";
+ case VK_CONTROL:
+ return "Ctrl";
+ case VK_ALT:
+ return "Alt";
+ case VK_PAUSE:
+ return "Pause";
+ case VK_CAPS_LOCK:
+ return "Caps Lock";
+ case VK_KANA:
+ return "Kana";
+ case VK_FINAL:
+ return "Final";
+ case VK_KANJI:
+ return "Kanji";
+ case VK_ESCAPE:
+ return "Escape";
+ case VK_CONVERT:
+ return "Convert";
+ case VK_NONCONVERT:
+ return "No Convert";
+ case VK_ACCEPT:
+ return "Accept";
+ case VK_MODECHANGE:
+ return "Mode Change";
+ case VK_SPACE:
+ return "Space";
+ case VK_PAGE_UP:
+ return "Page Up";
+ case VK_PAGE_DOWN:
+ return "Page Down";
+ case VK_END:
+ return "End";
+ case VK_HOME:
+ return "Home";
+ case VK_LEFT:
+ case VK_KP_LEFT:
+ return "Left";
+ case VK_UP:
+ case VK_KP_UP:
+ return "Up";
+ case VK_RIGHT:
+ case VK_KP_RIGHT:
+ return "Right";
+ case VK_DOWN:
+ case VK_KP_DOWN:
+ return "Down";
+ case VK_MINUS:
+ return "Minus";
+ case VK_MULTIPLY:
+ return "NumPad *";
+ case VK_ADD:
+ return "NumPad +";
+ case VK_SEPARATOR:
+ return "NumPad ,";
+ case VK_SUBTRACT:
+ return "NumPad -";
+ case VK_DECIMAL:
+ return "NumPad .";
+ case VK_DIVIDE:
+ return "NumPad /";
+ case VK_DELETE:
+ return "Delete";
+ case VK_DEAD_GRAVE:
+ return "Dead Grave";
+ case VK_DEAD_ACUTE:
+ return "Dead Acute";
+ case VK_DEAD_CIRCUMFLEX:
+ return "Dead Circumflex";
+ case VK_DEAD_TILDE:
+ return "Dead Tilde";
+ case VK_DEAD_MACRON:
+ return "Dead Macron";
+ case VK_DEAD_BREVE:
+ return "Dead Breve";
+ case VK_DEAD_ABOVEDOT:
+ return "Dead Above Dot";
+ case VK_DEAD_DIAERESIS:
+ return "Dead Diaeresis";
+ case VK_DEAD_ABOVERING:
+ return "Dead Above Ring";
+ case VK_DEAD_DOUBLEACUTE:
+ return "Dead Double Acute";
+ case VK_DEAD_CARON:
+ return "Dead Caron";
+ case VK_DEAD_CEDILLA:
+ return "Dead Cedilla";
+ case VK_DEAD_OGONEK:
+ return "Dead Ogonek";
+ case VK_DEAD_IOTA:
+ return "Dead Iota";
+ case VK_DEAD_VOICED_SOUND:
+ return "Dead Voiced Sound";
+ case VK_DEAD_SEMIVOICED_SOUND:
+ return "Dead Semivoiced Sound";
+ case VK_NUM_LOCK:
+ return "Num Lock";
+ case VK_SCROLL_LOCK:
+ return "Scroll Lock";
+ case VK_AMPERSAND:
+ return "Ampersand";
+ case VK_ASTERISK:
+ return "Asterisk";
+ case VK_QUOTEDBL:
+ return "Double Quote";
+ case VK_LESS:
+ return "Less";
+ case VK_PRINTSCREEN:
+ return "Print Screen";
+ case VK_INSERT:
+ return "Insert";
+ case VK_HELP:
+ return "Help";
+ case VK_META:
+ return "Meta";
+ case VK_GREATER:
+ return "Greater";
+ case VK_BRACELEFT:
+ return "Left Brace";
+ case VK_BRACERIGHT:
+ return "Right Brace";
+ case VK_BACK_QUOTE:
+ return "Back Quote";
+ case VK_QUOTE:
+ return "Quote";
+ case VK_ALPHANUMERIC:
+ return "Alphanumeric";
+ case VK_KATAKANA:
+ return "Katakana";
+ case VK_HIRAGANA:
+ return "Hiragana";
+ case VK_FULL_WIDTH:
+ return "Full-Width";
+ case VK_HALF_WIDTH:
+ return "Half-Width";
+ case VK_ROMAN_CHARACTERS:
+ return "Roman Characters";
+ case VK_ALL_CANDIDATES:
+ return "All Candidates";
+ case VK_PREVIOUS_CANDIDATE:
+ return "Previous Candidate";
+ case VK_CODE_INPUT:
+ return "Code Input";
+ case VK_JAPANESE_KATAKANA:
+ return "Japanese Katakana";
+ case VK_JAPANESE_HIRAGANA:
+ return "Japanese Hiragana";
+ case VK_JAPANESE_ROMAN:
+ return "Japanese Roman";
+ case VK_KANA_LOCK:
+ return "Kana Lock";
+ case VK_INPUT_METHOD_ON_OFF:
+ return "Input Method On/Off";
+ case VK_AT:
+ return "At";
+ case VK_COLON:
+ return "Colon";
+ case VK_CIRCUMFLEX:
+ return "Circumflex";
+ case VK_DOLLAR:
+ return "Dollar";
+ case VK_EURO_SIGN:
+ return "Euro";
+ case VK_EXCLAMATION_MARK:
+ return "Exclamation Mark";
+ case VK_INVERTED_EXCLAMATION_MARK:
+ return "Inverted Exclamation Mark";
+ case VK_LEFT_PARENTHESIS:
+ return "Left Parenthesis";
+ case VK_NUMBER_SIGN:
+ return "Number Sign";
+ case VK_PLUS:
+ return "Plus";
+ case VK_RIGHT_PARENTHESIS:
+ return "Right Parenthesis";
+ case VK_UNDERSCORE:
+ return "Underscore";
+ case VK_COMPOSE:
+ return "Compose";
+ case VK_ALT_GRAPH:
+ return "Alt Graph";
+ case VK_STOP:
+ return "Stop";
+ case VK_AGAIN:
+ return "Again";
+ case VK_PROPS:
+ return "Props";
+ case VK_UNDO:
+ return "Undo";
+ case VK_COPY:
+ return "Copy";
+ case VK_PASTE:
+ return "Paste";
+ case VK_FIND:
+ return "Find";
+ case VK_CUT:
+ return "Cut";
+ case VK_COMMA:
+ case VK_PERIOD:
+ case VK_SLASH:
+ case VK_0:
+ case VK_1:
+ case VK_2:
+ case VK_3:
+ case VK_4:
+ case VK_5:
+ case VK_6:
+ case VK_7:
+ case VK_8:
+ case VK_9:
+ case VK_SEMICOLON:
+ case VK_EQUALS:
+ case VK_A:
+ case VK_B:
+ case VK_C:
+ case VK_D:
+ case VK_E:
+ case VK_F:
+ case VK_G:
+ case VK_H:
+ case VK_I:
+ case VK_J:
+ case VK_K:
+ case VK_L:
+ case VK_M:
+ case VK_N:
+ case VK_O:
+ case VK_P:
+ case VK_Q:
+ case VK_R:
+ case VK_S:
+ case VK_T:
+ case VK_U:
+ case VK_V:
+ case VK_W:
+ case VK_X:
+ case VK_Y:
+ case VK_Z:
+ case VK_OPEN_BRACKET:
+ case VK_BACK_SLASH:
+ case VK_CLOSE_BRACKET:
+ return "" + (char) keyCode;
+ case VK_NUMPAD0:
+ case VK_NUMPAD1:
+ case VK_NUMPAD2:
+ case VK_NUMPAD3:
+ case VK_NUMPAD4:
+ case VK_NUMPAD5:
+ case VK_NUMPAD6:
+ case VK_NUMPAD7:
+ case VK_NUMPAD8:
+ case VK_NUMPAD9:
+ return "NumPad-" + (keyCode - VK_NUMPAD0);
+ case VK_F1:
+ case VK_F2:
+ case VK_F3:
+ case VK_F4:
+ case VK_F5:
+ case VK_F6:
+ case VK_F7:
+ case VK_F8:
+ case VK_F9:
+ case VK_F10:
+ case VK_F11:
+ case VK_F12:
+ return "F" + (keyCode - (VK_F1 - 1));
+ case VK_F13:
+ case VK_F14:
+ case VK_F15:
+ case VK_F16:
+ case VK_F17:
+ case VK_F18:
+ case VK_F19:
+ case VK_F20:
+ case VK_F21:
+ case VK_F22:
+ case VK_F23:
+ case VK_F24:
+ return "F" + (keyCode - (VK_F13 - 13));
+ default:
+ // This is funky on negative numbers, but that's Sun's fault.
+ return "Unknown keyCode: 0x" + (keyCode < 0 ? "-" : "")
+ + Integer.toHexString(Math.abs(keyCode));
+ }
+ }
+
+ /**
+ * Returns a string describing the modifiers, such as "Shift" or
+ * "Ctrl+Button1".
+ *
+ * XXX Sun claims this can be localized via the awt.properties file - how
+ * do we implement that?
+ *
+ * @param modifiers the old-style modifiers to convert to text
+ * @return a string representation of the modifiers in this bitmask
+ */
+ public static String getKeyModifiersText(int modifiers)
+ {
+ return getModifiersExText(EventModifier.extend(modifiers
+ & EventModifier.OLD_MASK));
+ }
+
+ /**
+ * Tests whether or not this key is an action key. An action key typically
+ * does not fire a KEY_TYPED event, and is not a modifier.
+ *
+ * @return true if this is an action key
+ */
+ public boolean isActionKey()
+ {
+ switch (keyCode)
+ {
+ case VK_PAUSE:
+ case VK_CAPS_LOCK:
+ case VK_KANA:
+ case VK_FINAL:
+ case VK_KANJI:
+ case VK_CONVERT:
+ case VK_NONCONVERT:
+ case VK_ACCEPT:
+ case VK_MODECHANGE:
+ case VK_PAGE_UP:
+ case VK_PAGE_DOWN:
+ case VK_END:
+ case VK_HOME:
+ case VK_LEFT:
+ case VK_UP:
+ case VK_RIGHT:
+ case VK_DOWN:
+ case VK_F1:
+ case VK_F2:
+ case VK_F3:
+ case VK_F4:
+ case VK_F5:
+ case VK_F6:
+ case VK_F7:
+ case VK_F8:
+ case VK_F9:
+ case VK_F10:
+ case VK_F11:
+ case VK_F12:
+ case VK_NUM_LOCK:
+ case VK_SCROLL_LOCK:
+ case VK_PRINTSCREEN:
+ case VK_INSERT:
+ case VK_HELP:
+ case VK_KP_UP:
+ case VK_KP_DOWN:
+ case VK_KP_LEFT:
+ case VK_KP_RIGHT:
+ case VK_ALPHANUMERIC:
+ case VK_KATAKANA:
+ case VK_HIRAGANA:
+ case VK_FULL_WIDTH:
+ case VK_HALF_WIDTH:
+ case VK_ROMAN_CHARACTERS:
+ case VK_ALL_CANDIDATES:
+ case VK_PREVIOUS_CANDIDATE:
+ case VK_CODE_INPUT:
+ case VK_JAPANESE_KATAKANA:
+ case VK_JAPANESE_HIRAGANA:
+ case VK_JAPANESE_ROMAN:
+ case VK_KANA_LOCK:
+ case VK_INPUT_METHOD_ON_OFF:
+ case VK_F13:
+ case VK_F14:
+ case VK_F15:
+ case VK_F16:
+ case VK_F17:
+ case VK_F18:
+ case VK_F19:
+ case VK_F20:
+ case VK_F21:
+ case VK_F22:
+ case VK_F23:
+ case VK_F24:
+ case VK_STOP:
+ case VK_AGAIN:
+ case VK_PROPS:
+ case VK_UNDO:
+ case VK_COPY:
+ case VK_PASTE:
+ case VK_FIND:
+ case VK_CUT:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Returns a string identifying the event. This is formatted as the
+ * field name of the id type, followed by the keyCode, then the
+ * keyChar, modifiers (if any), extModifiers (if any), and
+ * keyLocation.
+ *
+ * @return a string identifying the event
+ */
+ public String paramString()
+ {
+ CPStringBuilder s = new CPStringBuilder();
+
+ switch (id)
+ {
+ case KEY_PRESSED:
+ s.append("KEY_PRESSED");
+ break;
+ case KEY_RELEASED:
+ s.append("KEY_RELEASED");
+ break;
+ case KEY_TYPED:
+ s.append("KEY_TYPED");
+ break;
+ default:
+ s.append("unknown type");
+ }
+
+ s.append(",keyCode=").append(keyCode);
+
+ s.append(",keyText=").append(getKeyText(keyCode));
+
+ s.append(",keyChar=");
+ if (isActionKey()
+ || keyCode == VK_SHIFT
+ || keyCode == VK_CONTROL
+ || keyCode == VK_ALT)
+ s.append("Undefined keyChar");
+ else
+ {
+ /* This output string must be selected by examining keyChar
+ * rather than keyCode, because key code information is not
+ * included in KEY_TYPED events.
+ */
+ if (keyChar == VK_BACK_SPACE
+ || keyChar == VK_TAB
+ || keyChar == VK_ENTER
+ || keyChar == VK_ESCAPE
+ || keyChar == VK_DELETE)
+ s.append(getKeyText(keyChar));
+ else
+ s.append("'").append(keyChar).append("'");
+ }
+
+ if ((modifiers & CONVERT_MASK) != 0)
+ s.append(",modifiers=").append(getModifiersExText(modifiers
+ & CONVERT_MASK));
+ if (modifiers != 0)
+ s.append(",extModifiers=").append(getModifiersExText(modifiers));
+
+ s.append(",keyLocation=KEY_LOCATION_");
+ switch (keyLocation)
+ {
+ case KEY_LOCATION_UNKNOWN:
+ s.append("UNKNOWN");
+ break;
+ case KEY_LOCATION_STANDARD:
+ s.append("STANDARD");
+ break;
+ case KEY_LOCATION_LEFT:
+ s.append("LEFT");
+ break;
+ case KEY_LOCATION_RIGHT:
+ s.append("RIGHT");
+ break;
+ case KEY_LOCATION_NUMPAD:
+ s.append("NUMPAD");
+ }
+
+ return s.toString();
+ }
+
+ /**
+ * Reads in the object from a serial stream.
+ *
+ * @param s the stream to read from
+ * @throws IOException if deserialization fails
+ * @throws ClassNotFoundException if deserialization fails
+ * @serialData default, except that the modifiers are converted to new style
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ modifiersEx = EventModifier.extend(modifiers) & EventModifier.NEW_MASK;
+ }
+} // class KeyEvent
diff --git a/libjava/classpath/java/awt/event/KeyListener.java b/libjava/classpath/java/awt/event/KeyListener.java
new file mode 100644
index 000000000..5c0a640f6
--- /dev/null
+++ b/libjava/classpath/java/awt/event/KeyListener.java
@@ -0,0 +1,77 @@
+/* KeyListener.java -- listen for keyboard presses
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that wish to receive keyboard events. To
+ * watch a subset of these events, use a KeyAdapter.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see KeyAdapter
+ * @see KeyEvent
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface KeyListener extends EventListener
+{
+ /**
+ * This method is called when a key is typed. A key is considered typed
+ * when it and all modifiers have been pressed and released, mapping to
+ * a single virtual key.
+ *
+ * @param event the <code>KeyEvent</code> indicating that a key was typed
+ */
+ void keyTyped(KeyEvent event);
+
+ /**
+ * This method is called when a key is pressed.
+ *
+ * @param event the <code>KeyEvent</code> indicating the key press
+ */
+ void keyPressed(KeyEvent event);
+
+ /**
+ * This method is called when a key is released.
+ *
+ * @param event the <code>KeyEvent</code> indicating the key release
+ */
+ void keyReleased(KeyEvent event);
+} // interface KeyListener
diff --git a/libjava/classpath/java/awt/event/MouseAdapter.java b/libjava/classpath/java/awt/event/MouseAdapter.java
new file mode 100644
index 000000000..9f40c285a
--- /dev/null
+++ b/libjava/classpath/java/awt/event/MouseAdapter.java
@@ -0,0 +1,106 @@
+/* MouseAdapter.java -- convenience class for writing mouse listeners
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+/**
+ * This class implements <code>MouseListener</code> and implements all methods
+ * with empty bodies. This allows a listener interested in implementing only
+ * a subset of the <code>MouseListener</code> interface to extend this class
+ * and override only the desired methods.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see MouseEvent
+ * @see MouseListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class MouseAdapter implements MouseListener
+{
+ /**
+ * Do nothing default constructor for subclasses.
+ */
+ public MouseAdapter()
+ {
+ }
+
+ /**
+ * Implements this method in the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void mouseClicked(MouseEvent event)
+ {
+ }
+
+ /**
+ * Implements this method in the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void mousePressed(MouseEvent event)
+ {
+ }
+
+ /**
+ * Implements this method in the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void mouseReleased(MouseEvent event)
+ {
+ }
+
+ /**
+ * Implements this method in the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void mouseEntered(MouseEvent event)
+ {
+ }
+
+ /**
+ * Implements this method in the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void mouseExited(MouseEvent event)
+ {
+ }
+} // class MouseAdapter
diff --git a/libjava/classpath/java/awt/event/MouseEvent.java b/libjava/classpath/java/awt/event/MouseEvent.java
new file mode 100644
index 000000000..64142ecc6
--- /dev/null
+++ b/libjava/classpath/java/awt/event/MouseEvent.java
@@ -0,0 +1,502 @@
+/* MouseEvent.java -- a mouse event
+ Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import gnu.java.awt.EventModifier;
+import gnu.java.lang.CPStringBuilder;
+
+import java.awt.Component;
+import java.awt.Point;
+import java.awt.PopupMenu;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+
+/**
+ * This event is generated for a mouse event. There are three main categories
+ * of mouse events: Regular events include pressing, releasing, and clicking
+ * buttons, as well as moving over the boundary of the unobscured portion of
+ * a component. Motion events include movement and dragging. Wheel events are
+ * covered separately by the subclass MouseWheelEvent.
+ *
+ * <p>A mouse event is tied to the unobstructed visible component that the
+ * mouse cursor was over at the time of the action. The button that was
+ * most recently pressed is the only one that shows up in
+ * <code>getModifiers</code>, and is returned by <code>getButton</code>,
+ * while all buttons that are down show up in <code>getModifiersEx</code>.
+ *
+ * <p>Drag events may be cut short if native drag-and-drop operations steal
+ * the event. Likewise, if a mouse drag exceeds the bounds of a window or
+ * virtual device, some platforms may clip the path to fit in the bounds of
+ * the component.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see MouseAdapter
+ * @see MouseListener
+ * @see MouseMotionAdapter
+ * @see MouseMotionListener
+ * @see MouseWheelListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class MouseEvent extends InputEvent
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -991214153494842848L;
+
+ /** This is the first id in the range of event ids used by this class. */
+ public static final int MOUSE_FIRST = 500;
+
+ /** This is the last id in the range of event ids used by this class. */
+ public static final int MOUSE_LAST = 507;
+
+ /** This event id indicates that the mouse was clicked. */
+ public static final int MOUSE_CLICKED = 500;
+
+ /** This event id indicates that the mouse was pressed. */
+ public static final int MOUSE_PRESSED = 501;
+
+ /** This event id indicates that the mouse was released. */
+ public static final int MOUSE_RELEASED = 502;
+
+ /** This event id indicates that the mouse was moved. */
+ public static final int MOUSE_MOVED = 503;
+
+ /** This event id indicates that the mouse entered a component. */
+ public static final int MOUSE_ENTERED = 504;
+
+ /** This event id indicates that the mouse exited a component. */
+ public static final int MOUSE_EXITED = 505;
+
+ /**
+ * This indicates that no button changed state.
+ *
+ * @see #getButton()
+ * @since 1.4
+ */
+ public static final int NOBUTTON = 0;
+
+ /**
+ * This indicates that button 1 changed state.
+ *
+ * @see #getButton()
+ * @since 1.4
+ */
+ public static final int BUTTON1 = 1;
+
+ /**
+ * This indicates that button 2 changed state.
+ *
+ * @see #getButton()
+ * @since 1.4
+ */
+ public static final int BUTTON2 = 2;
+
+ /**
+ * This indicates that button 3 changed state.
+ *
+ * @see #getButton()
+ * @since 1.4
+ */
+ public static final int BUTTON3 = 3;
+
+ /** This event id indicates that the mouse was dragged over a component. */
+ public static final int MOUSE_DRAGGED = 506;
+
+ /**
+ * This event id indicates that the mouse wheel was rotated.
+ *
+ * @since 1.4
+ */
+ public static final int MOUSE_WHEEL = 507;
+
+ /**
+ * The X coordinate of the mouse cursor at the time of the event.
+ *
+ * @see #getX()
+ * @serial the x coordinate
+ */
+ private int x;
+
+ /**
+ * The Y coordinate of the mouse cursor at the time of the event.
+ *
+ * @see #getY()
+ * @serial the y coordinate
+ */
+ private int y;
+
+ /**
+ * The screen position of that mouse event, X coordinate.
+ */
+ private int absX;
+
+ /**
+ * The screen position of that mouse event, Y coordinate.
+ */
+ private int absY;
+
+ /**
+ * The number of clicks that took place. For MOUSE_CLICKED, MOUSE_PRESSED,
+ * and MOUSE_RELEASED, this will be at least 1; otherwise it is 0.
+ *
+ * see #getClickCount()
+ * @serial the number of clicks
+ */
+ private final int clickCount;
+
+ /**
+ * Indicates which mouse button changed state. Can only be one of
+ * {@link #NOBUTTON}, {@link #BUTTON1}, {@link #BUTTON2}, or
+ * {@link #BUTTON3}.
+ *
+ * @see #getButton()
+ * @since 1.4
+ */
+ private int button;
+
+ /**
+ * Whether or not this event should trigger a popup menu.
+ *
+ * @see PopupMenu
+ * @see #isPopupTrigger()
+ * @serial true if this is a popup trigger
+ */
+ private final boolean popupTrigger;
+
+ /**
+ * Initializes a new instance of <code>MouseEvent</code> with the specified
+ * information. Note that an invalid id leads to unspecified results.
+ *
+ * @param source the source of the event
+ * @param id the event id
+ * @param when the timestamp of when the event occurred
+ * @param modifiers the modifier keys during the event, in old or new style
+ * @param x the X coordinate of the mouse point
+ * @param y the Y coordinate of the mouse point
+ * @param clickCount the number of mouse clicks for this event
+ * @param popupTrigger true if this event triggers a popup menu
+ * @param button the most recent mouse button to change state
+ * @throws IllegalArgumentException if source is null or button is invalid
+ * @since 1.4
+ */
+ public MouseEvent(Component source, int id, long when, int modifiers,
+ int x, int y, int clickCount, boolean popupTrigger,
+ int button)
+ {
+ this(source, id, when, modifiers, x, y, 0, 0, clickCount, popupTrigger,
+ button);
+ }
+
+ /**
+ * Initializes a new instance of <code>MouseEvent</code> with the specified
+ * information. Note that an invalid id leads to unspecified results.
+ *
+ * @param source the source of the event
+ * @param id the event id
+ * @param when the timestamp of when the event occurred
+ * @param modifiers the modifier keys during the event, in old or new style
+ * @param x the X coordinate of the mouse point
+ * @param y the Y coordinate of the mouse point
+ * @param clickCount the number of mouse clicks for this event
+ * @param popupTrigger true if this event triggers a popup menu
+ * @throws IllegalArgumentException if source is null
+ */
+ public MouseEvent(Component source, int id, long when, int modifiers,
+ int x, int y, int clickCount, boolean popupTrigger)
+ {
+ this(source, id, when, modifiers, x, y, clickCount, popupTrigger,
+ NOBUTTON);
+ }
+
+ /**
+ * Creates a new MouseEvent. This is like the other constructors and adds
+ * specific absolute coordinates.
+ *
+ * @param source the source of the event
+ * @param id the event id
+ * @param when the timestamp of when the event occurred
+ * @param modifiers the modifier keys during the event, in old or new style
+ * @param x the X coordinate of the mouse point
+ * @param y the Y coordinate of the mouse point
+ * @param absX the absolute X screen coordinate of this event
+ * @param absY the absolute Y screen coordinate of this event
+ * @param clickCount the number of mouse clicks for this event
+ * @param popupTrigger true if this event triggers a popup menu
+ * @param button the most recent mouse button to change state
+ *
+ * @throws IllegalArgumentException if source is null or button is invalid
+ *
+ * @since 1.6
+ */
+ public MouseEvent(Component source, int id, long when, int modifiers,
+ int x, int y, int absX, int absY, int clickCount,
+ boolean popupTrigger, int button)
+ {
+ super(source, id, when, modifiers);
+
+ this.x = x;
+ this.y = y;
+ this.clickCount = clickCount;
+ this.popupTrigger = popupTrigger;
+ this.button = button;
+ if (button < NOBUTTON || button > BUTTON3)
+ throw new IllegalArgumentException();
+ if ((modifiers & EventModifier.OLD_MASK) != 0)
+ {
+ if ((modifiers & BUTTON1_MASK) != 0)
+ this.button = BUTTON1;
+ else if ((modifiers & BUTTON2_MASK) != 0)
+ this.button = BUTTON2;
+ else if ((modifiers & BUTTON3_MASK) != 0)
+ this.button = BUTTON3;
+ }
+ // clear the mouse button modifier masks if this is a button
+ // release event.
+ if (id == MOUSE_RELEASED)
+ this.modifiersEx &= ~(BUTTON1_DOWN_MASK
+ | BUTTON2_DOWN_MASK
+ | BUTTON3_DOWN_MASK);
+
+ this.absX = absX;
+ this.absY = absY;
+ }
+
+ /**
+ * This method returns the X coordinate of the mouse position. This is
+ * relative to the source component.
+ *
+ * @return the x coordinate
+ */
+ public int getX()
+ {
+ return x;
+ }
+
+ /**
+ * This method returns the Y coordinate of the mouse position. This is
+ * relative to the source component.
+ *
+ * @return the y coordinate
+ */
+ public int getY()
+ {
+ return y;
+ }
+
+ /**
+ * @since 1.6
+ */
+ public Point getLocationOnScreen()
+ {
+ return new Point(absX, absY);
+ }
+
+ /**
+ * @since 1.6
+ */
+ public int getXOnScreen()
+ {
+ return absX;
+ }
+
+ /**
+ * @since 1.6
+ */
+ public int getYOnScreen()
+ {
+ return absY;
+ }
+
+ /**
+ * This method returns a <code>Point</code> for the x,y position of
+ * the mouse pointer. This is relative to the source component.
+ *
+ * @return a <code>Point</code> for the event position
+ */
+ public Point getPoint()
+ {
+ return new Point(x, y);
+ }
+
+ /**
+ * Translates the event coordinates by the specified x and y offsets.
+ *
+ * @param dx the value to add to the X coordinate of this event
+ * @param dy the value to add to the Y coordiante of this event
+ */
+ public void translatePoint(int dx, int dy)
+ {
+ x += dx;
+ y += dy;
+ }
+
+ /**
+ * This method returns the number of mouse clicks associated with this
+ * event.
+ *
+ * @return the number of mouse clicks for this event
+ */
+ public int getClickCount()
+ {
+ return clickCount;
+ }
+
+ /**
+ * Returns which button, if any, was the most recent to change state. This
+ * will be one of {@link #NOBUTTON}, {@link #BUTTON1}, {@link #BUTTON2}, or
+ * {@link #BUTTON3}.
+ *
+ * @return the button that changed state
+ * @since 1.4
+ */
+ public int getButton()
+ {
+ return button;
+ }
+
+ /**
+ * This method tests whether or not the event is a popup menu trigger. This
+ * should be checked in both MousePressed and MouseReleased to be
+ * cross-platform compatible, as different systems have different popup
+ * triggers.
+ *
+ * @return true if the event is a popup menu trigger
+ */
+ public boolean isPopupTrigger()
+ {
+ return popupTrigger;
+ }
+
+ /**
+ * Returns a string describing the modifiers, such as "Shift" or
+ * "Ctrl+Button1".
+ *
+ * XXX Sun claims this can be localized via the awt.properties file - how
+ * do we implement that?
+ *
+ * @param modifiers the old-style modifiers to convert to text
+ * @return a string representation of the modifiers in this bitmask
+ */
+ public static String getMouseModifiersText(int modifiers)
+ {
+ modifiers &= EventModifier.OLD_MASK;
+ if ((modifiers & BUTTON2_MASK) != 0)
+ modifiers |= BUTTON2_DOWN_MASK;
+ if ((modifiers & BUTTON3_MASK) != 0)
+ modifiers |= BUTTON3_DOWN_MASK;
+ return getModifiersExText(EventModifier.extend(modifiers));
+ }
+
+ /**
+ * Returns a string identifying this event. This is formatted as the field
+ * name of the id type, followed by the (x,y) point, the most recent button
+ * changed, modifiers (if any), extModifiers (if any), and clickCount.
+ *
+ * @return a string identifying this event
+ */
+ public String paramString()
+ {
+ CPStringBuilder s = new CPStringBuilder();
+ switch (id)
+ {
+ case MOUSE_CLICKED:
+ s.append("MOUSE_CLICKED,(");
+ break;
+ case MOUSE_PRESSED:
+ s.append("MOUSE_PRESSED,(");
+ break;
+ case MOUSE_RELEASED:
+ s.append("MOUSE_RELEASED,(");
+ break;
+ case MOUSE_MOVED:
+ s.append("MOUSE_MOVED,(");
+ break;
+ case MOUSE_ENTERED:
+ s.append("MOUSE_ENTERED,(");
+ break;
+ case MOUSE_EXITED:
+ s.append("MOUSE_EXITED,(");
+ break;
+ case MOUSE_DRAGGED:
+ s.append("MOUSE_DRAGGED,(");
+ break;
+ case MOUSE_WHEEL:
+ s.append("MOUSE_WHEEL,(");
+ break;
+ default:
+ s.append("unknown type,(");
+ }
+ s.append(x).append(',').append(y).append("),button=").append(button);
+ // FIXME: need a mauve test for this method
+ if (modifiersEx != 0)
+ s.append(",extModifiers=").append(getModifiersExText(modifiersEx));
+
+ s.append(",clickCount=").append(clickCount);
+ s.append(",consumed=").append(consumed);
+
+ return s.toString();
+ }
+
+ /**
+ * Reads in the object from a serial stream.
+ *
+ * @param s the stream to read from
+ * @throws IOException if deserialization fails
+ * @throws ClassNotFoundException if deserialization fails
+ * @serialData default, except that the modifiers are converted to new style
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ if ((modifiers & EventModifier.OLD_MASK) != 0)
+ {
+ if ((modifiers & BUTTON1_MASK) != 0)
+ button = BUTTON1;
+ else if ((modifiers & BUTTON2_MASK) != 0)
+ button = BUTTON2;
+ else if ((modifiers & BUTTON3_MASK) != 0)
+ button = BUTTON3;
+ modifiersEx = EventModifier.extend(modifiers) & EventModifier.NEW_MASK;
+ }
+ }
+} // class MouseEvent
diff --git a/libjava/classpath/java/awt/event/MouseListener.java b/libjava/classpath/java/awt/event/MouseListener.java
new file mode 100644
index 000000000..735ca6b5a
--- /dev/null
+++ b/libjava/classpath/java/awt/event/MouseListener.java
@@ -0,0 +1,94 @@
+/* MouseListener.java -- listen for mouse clicks and crossing component edges
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that wish to receive mouse events other than
+ * simple motion events. This includes clicks (but not mouse wheel events),
+ * and crossing component boundaries without change in button status. To
+ * track moves and drags, use MouseMotionListener, and to track wheel events,
+ * use MouseWheelListener. To watch a subset of these events, use a
+ * MouseAdapter.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see MouseAdapter
+ * @see MouseEvent
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface MouseListener extends EventListener
+{
+ /**
+ * This method is called when the mouse is clicked (pressed and released
+ * in short succession) on a component.
+ *
+ * @param event the <code>MouseEvent</code> indicating the click
+ */
+ void mouseClicked(MouseEvent event);
+
+ /**
+ * This method is called when the mouse is pressed over a component.
+ *
+ * @param event the <code>MouseEvent</code> for the press
+ */
+ void mousePressed(MouseEvent event);
+
+ /**
+ * This method is called when the mouse is released over a component.
+ *
+ * @param event the <code>MouseEvent</code> for the release
+ */
+ void mouseReleased(MouseEvent event);
+
+ /**
+ * This method is called when the mouse enters a component.
+ *
+ * @param event the <code>MouseEvent</code> for the entry
+ */
+ void mouseEntered(MouseEvent event);
+
+ /**
+ * This method is called when the mouse exits a component.
+ *
+ * @param event the <code>MouseEvent</code> for the exit
+ */
+ void mouseExited(MouseEvent event);
+} // interface MouseListener
diff --git a/libjava/classpath/java/awt/event/MouseMotionAdapter.java b/libjava/classpath/java/awt/event/MouseMotionAdapter.java
new file mode 100644
index 000000000..8a295f66c
--- /dev/null
+++ b/libjava/classpath/java/awt/event/MouseMotionAdapter.java
@@ -0,0 +1,79 @@
+/* MouseMotionAdapter.java -- convenience class for mouse motion listeners
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+/**
+ * This class implements <code>MouseMotionListener</code> and implements all
+ * methods with empty bodies. This allows a listener interested in
+ * implementing only a subset of the <code>MouseMotionListener</code>
+ * interface to extend this class and override only the desired methods.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see MouseEvent
+ * @see MouseMotionListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class MouseMotionAdapter implements MouseMotionListener
+{
+ /**
+ * Do nothing default constructor for subclasses.
+ */
+ public MouseMotionAdapter()
+ {
+ }
+
+ /**
+ * Implement this method in the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void mouseDragged(MouseEvent event)
+ {
+ }
+
+ /**
+ * Implement this method in the interface with an empty body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void mouseMoved(MouseEvent event)
+ {
+ }
+} // class MouseMotionAdapter
diff --git a/libjava/classpath/java/awt/event/MouseMotionListener.java b/libjava/classpath/java/awt/event/MouseMotionListener.java
new file mode 100644
index 000000000..ba2c5698b
--- /dev/null
+++ b/libjava/classpath/java/awt/event/MouseMotionListener.java
@@ -0,0 +1,72 @@
+/* MouseMotionListener.java -- listen to mouse motion events
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that wish to be notified of mouse movements.
+ * This includes moves and drags, but not crossing component boundaries. To
+ * track other mouse events, use MouseListener or MouseWheelListener. To
+ * watch a subset of these events, use a MouseMotionAdapter.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see MouseMotionAdapter
+ * @see MouseEvent
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface MouseMotionListener extends EventListener
+{
+ /**
+ * This method is called when the mouse is moved over a component
+ * while a button has been pressed.
+ *
+ * @param event the <code>MouseEvent</code> indicating the motion
+ */
+ void mouseDragged(MouseEvent event);
+
+ /**
+ * This method is called when the mouse is moved over a component
+ * while no button is pressed.
+ *
+ * @param event the <code>MouseEvent</code> indicating the motion
+ */
+ void mouseMoved(MouseEvent event);
+} // interface MouseMotionListener
diff --git a/libjava/classpath/java/awt/event/MouseWheelEvent.java b/libjava/classpath/java/awt/event/MouseWheelEvent.java
new file mode 100644
index 000000000..1ca946582
--- /dev/null
+++ b/libjava/classpath/java/awt/event/MouseWheelEvent.java
@@ -0,0 +1,232 @@
+/* MouseWheelEvent.java -- a mouse wheel event
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.Adjustable;
+import java.awt.Component;
+import java.awt.Rectangle;
+import java.awt.ScrollPane;
+
+import javax.swing.JScrollPane;
+import javax.swing.Scrollable;
+
+/**
+ * This event is generated for a mouse wheel rotation. The wheel (the middle
+ * mouse button on most modern mice) can be rotated towards or away from the
+ * user, and is often used for scrolling.
+ *
+ * <p>Because of the special use for scrolling components, MouseWheelEvents
+ * often affect a different component than the one located at the point of
+ * the event. If the component under the mouse cursor does not accept wheel
+ * events, the event is passed to the first ancestor container which does. This
+ * is often a ScrollPane, which knows how to scroll. If an AWT component is
+ * built from a native widget that knows how to use mouse wheel events, that
+ * component will consume the event.
+ *
+ * <p>The two most common scroll types are "units" (lines at a time) or
+ * "blocks" (pages at a time). The initial setting is taken from the platform,
+ * although the user can adjust the setting at any time.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see MouseWheelListener
+ * @see ScrollPane
+ * @see ScrollPane#setWheelScrollingEnabled(boolean)
+ * @see JScrollPane
+ * @see JScrollPane#setWheelScrollingEnabled(boolean)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public class MouseWheelEvent extends MouseEvent
+{
+ /**
+ * Compatible with JDK 1.4+.
+ */
+ private static final long serialVersionUID = 6459879390515399677L;
+
+ /**
+ * Indicates scrolling by units (lines).
+ *
+ * @see #getScrollType()
+ */
+ public static final int WHEEL_UNIT_SCROLL = 0;
+
+ /**
+ * Indicates scrolling by blocks (pages).
+ *
+ * @see #getScrollType()
+ */
+ public static final int WHEEL_BLOCK_SCROLL = 1;
+
+ /**
+ * Indicates what scroll type should take place. This should be limited
+ * to {@link #WHEEL_UNIT_SCROLL} and {@link #WHEEL_BLOCK_SCROLL}.
+ *
+ * @serial the scroll type
+ */
+ private final int scrollType;
+
+ /**
+ * Indicates the scroll amount. This is only meaningful if scrollType is
+ * WHEEL_UNIT_SCROLL.
+ *
+ * @serial the number of lines to scroll
+ */
+ private final int scrollAmount;
+
+ /**
+ * Indicates how far the mouse wheel was rotated.
+ *
+ * @serial the rotation amount
+ */
+ private final int wheelRotation;
+
+ /**
+ * Initializes a new instance of <code>MouseWheelEvent</code> with the
+ * specified information. Note that an invalid id leads to unspecified
+ * results.
+ *
+ * @param source the source of the event
+ * @param id the event id
+ * @param when the timestamp of when the event occurred
+ * @param modifiers any modifier bits for this event
+ * @param x the X coordinate of the mouse point
+ * @param y the Y coordinate of the mouse point
+ * @param clickCount the number of mouse clicks for this event
+ * @param popupTrigger true if this event triggers a popup menu
+ * @param scrollType one of {@link #WHEEL_UNIT_SCROLL},
+ * {@link #WHEEL_BLOCK_SCROLL}
+ * @param scrollAmount the number of units to scroll, ignored for block type
+ * @param wheelRotation the number of rotation "clicks"
+ * @throws IllegalArgumentException if source is null
+ * @see MouseEvent#MouseEvent(Component, int, long, int, int, int, int,
+ * boolean)
+ */
+ public MouseWheelEvent(Component source, int id, long when, int modifiers,
+ int x, int y, int clickCount, boolean popupTrigger,
+ int scrollType, int scrollAmount, int wheelRotation)
+ {
+ super(source, id, when, modifiers, x, y, clickCount, popupTrigger);
+ this.scrollType = scrollType;
+ this.scrollAmount = scrollAmount;
+ this.wheelRotation = wheelRotation;
+ }
+
+ /**
+ * This method returns the scrolling pattern this event requests. Legal
+ * values are {@link #WHEEL_UNIT_SCROLL} and {@link #WHEEL_BLOCK_SCROLL}.
+ *
+ * @return the scroll type
+ * @see Adjustable#getUnitIncrement()
+ * @see Adjustable#getBlockIncrement()
+ * @see Scrollable#getScrollableUnitIncrement(Rectangle, int, int)
+ * @see Scrollable#getScrollableBlockIncrement(Rectangle, int, int)
+ */
+ public int getScrollType()
+ {
+ return scrollType;
+ }
+
+ /**
+ * Returns the number of units to scroll in response to this event. This
+ * only makes sense when the scroll type is WHEEL_UNIT_SCROLL.
+ *
+ * @return the number of scroll units, if defined
+ * @see #getScrollType()
+ */
+ public int getScrollAmount()
+ {
+ return scrollAmount;
+ }
+
+ /**
+ * Gets the number of "clicks" the wheel was rotated. Negative values move
+ * up (away) from the user, positive values move down (towards) the user.
+ *
+ * @return the number of rotation clicks
+ */
+ public int getWheelRotation()
+ {
+ return wheelRotation;
+ }
+
+ /**
+ * This is a convenience method which aids in a common listener for scrolling
+ * a scrollpane (although this is already built into ScrollPane and
+ * JScrollPane). This method only makes sense when getScrollType() returns
+ * WHEEL_UNIT_SCROLL.
+ *
+ * <p>This accounts for direction of scroll and amount of wheel movement, as
+ * interpreted by the platform settings.
+ *
+ * @return the number of units to scroll
+ * @see #getScrollType()
+ * @see #getScrollAmount()
+ * @see MouseWheelListener
+ * @see Adjustable
+ * @see Adjustable#getUnitIncrement()
+ * @see Scrollable
+ * @see Scrollable#getScrollableUnitIncrement(Rectangle, int, int)
+ * @see ScrollPane
+ * @see ScrollPane#setWheelScrollingEnabled(boolean)
+ * @see JScrollPane
+ * @see JScrollPane#setWheelScrollingEnabled(boolean)
+ */
+ public int getUnitsToScroll()
+ {
+ return wheelRotation * scrollAmount;
+ }
+
+ /**
+ * Returns a string identifying this event. For mouse wheel events, this
+ * is <code>super.paramString() + ",scrollType=WHEEL_" +
+ * (getScrollType() == WHEEL_UNIT_SCROLL ? "UNIT" : "BLOCK")
+ * + "_SCROLL,scrollAmount=" + getScrollAmount() + ",wheelRotation="
+ * + getWheelRotation()</code>.
+ *
+ * @return a string identifying this event
+ */
+ public String paramString()
+ {
+ return super.paramString() + ",scrollType="
+ + (scrollType == WHEEL_UNIT_SCROLL ? "WHEEL_UNIT_SCROLL"
+ : scrollType == WHEEL_BLOCK_SCROLL ? "WHEEL_BLOCK_SCROLL"
+ : "unknown scroll type")
+ + ",scrollAmount=" + scrollAmount + ",wheelRotation=" + wheelRotation;
+ }
+} // class MouseWheelEvent
diff --git a/libjava/classpath/java/awt/event/MouseWheelListener.java b/libjava/classpath/java/awt/event/MouseWheelListener.java
new file mode 100644
index 000000000..1125582e1
--- /dev/null
+++ b/libjava/classpath/java/awt/event/MouseWheelListener.java
@@ -0,0 +1,60 @@
+/* MouseWheelListener.java -- listen for mouse wheel events
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that wish to receive mouse wheel events. For
+ * other events, use MouseListener or MouseMotionListener.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see MouseWheelEvent
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public interface MouseWheelListener extends EventListener
+{
+ /**
+ * This method is called when the mouse wheel is rotated.
+ *
+ * @param event the <code>MouseWheelEvent</code> indicating the rotation
+ */
+ void mouseWheelMoved(MouseWheelEvent event);
+} // interface MouseWheelListener
diff --git a/libjava/classpath/java/awt/event/PaintEvent.java b/libjava/classpath/java/awt/event/PaintEvent.java
new file mode 100644
index 000000000..bb89c3722
--- /dev/null
+++ b/libjava/classpath/java/awt/event/PaintEvent.java
@@ -0,0 +1,127 @@
+/* PaintEvent.java -- an area of the screen needs to be repainted
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.Component;
+import java.awt.Rectangle;
+
+/**
+ * This event is generated when an area of the screen needs to be painted.
+ * This event is not meant for users, but exists to allow proper serialization
+ * behavior in the EventQueue with user-accessible events.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class PaintEvent extends ComponentEvent
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 1267492026433337593L;
+
+ /** This is the first id in the range of event ids used by this class. */
+ public static final int PAINT_FIRST = 800;
+
+ /** This is the last id in the range of event ids used by this class. */
+ public static final int PAINT_LAST = 801;
+
+ /** This id is for paint event types. */
+ public static final int PAINT = 800;
+
+ /** This id is for update event types. */
+ public static final int UPDATE = 801;
+
+ /**
+ * This is the rectange to be painted or updated.
+ *
+ * @see #getUpdateRect()
+ * @see #setUpdateRect(Rectangle)
+ * @serial the non-null rectangle to be painted
+ */
+ private Rectangle updateRect;
+
+ /**
+ * Initializes a new instance of <code>PaintEvent</code> with the specified
+ * source, id, and update region. Note that an invalid id leads to
+ * unspecified results.
+ *
+ * @param source the event source
+ * @param id the event id
+ * @param updateRect the rectangle to repaint
+ * @throws IllegalArgumentException if source is null
+ */
+ public PaintEvent(Component source, int id, Rectangle updateRect)
+ {
+ super(source, id);
+ this.updateRect = updateRect;
+ }
+
+ /**
+ * Returns the rectange to be updated for this event.
+ *
+ * @return the rectangle to update
+ */
+ public Rectangle getUpdateRect()
+ {
+ return updateRect;
+ }
+
+ /**
+ * Sets the rectangle to be updated for this event.
+ *
+ * @param updateRect the new update rectangle for this event
+ */
+ public void setUpdateRect(Rectangle updateRect)
+ {
+ this.updateRect = updateRect;
+ }
+
+ /**
+ * Returns a string identifying this event.
+ *
+ * @return a string identifying this event
+ */
+ public String paramString()
+ {
+ return (id == PAINT ? "PAINT,updateRect=" : id == UPDATE
+ ? "UPDATE,updateRect=" : "unknown type,updateRect=") + updateRect;
+ }
+} // class PaintEvent
diff --git a/libjava/classpath/java/awt/event/TextEvent.java b/libjava/classpath/java/awt/event/TextEvent.java
new file mode 100644
index 000000000..0288abbb7
--- /dev/null
+++ b/libjava/classpath/java/awt/event/TextEvent.java
@@ -0,0 +1,93 @@
+/* TextEvent.java -- event for text changes
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.AWTEvent;
+import java.awt.TextComponent;
+
+/**
+ * This event is generated when a text box changes contents. This is an
+ * abstraction that distills a large number of individual mouse or keyboard
+ * events into a simpler "text changed" event.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see TextComponent
+ * @see TextListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class TextEvent extends AWTEvent
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 6269902291250941179L;
+
+ /** This is the first id in the range of event ids used by this class. */
+ public static final int TEXT_FIRST = 900;
+
+ /** This is the last id in the range of event ids used by this class. */
+ public static final int TEXT_LAST = 900;
+
+ /** This event id indicates that the text of an object has changed. */
+ public static final int TEXT_VALUE_CHANGED = 900;
+
+ /**
+ * Initializes a new instance of <code>TextEvent</code> with the specified
+ * source and id. Note that an invalid id leads to unspecified results.
+ *
+ * @param source the (TextComponent) object that generated this event
+ * @param id the event id
+ * @throws IllegalArgumentException if source is null
+ */
+ public TextEvent(Object source, int id)
+ {
+ super(source, id);
+ }
+
+ /**
+ * Returns a string identifying this event. This is "TEXT_VALUE_CHANGED".
+ *
+ * @return a string identifying this event
+ */
+ public String paramString()
+ {
+ return id == TEXT_VALUE_CHANGED ? "TEXT_VALUE_CHANGED" : "unknown type";
+ }
+} // class TextEvent
diff --git a/libjava/classpath/java/awt/event/TextListener.java b/libjava/classpath/java/awt/event/TextListener.java
new file mode 100644
index 000000000..bcdd7fa7a
--- /dev/null
+++ b/libjava/classpath/java/awt/event/TextListener.java
@@ -0,0 +1,60 @@
+/* TextListener.java -- listen for text changes
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that wish to be notified when text changes
+ * in a component.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see TextEvent
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface TextListener extends EventListener
+{
+ /**
+ * This method is called when the text being monitored changes.
+ *
+ * @param event the <code>TextEvent</code> indicating the change
+ */
+ void textValueChanged(TextEvent event);
+} // interface TextListener
diff --git a/libjava/classpath/java/awt/event/WindowAdapter.java b/libjava/classpath/java/awt/event/WindowAdapter.java
new file mode 100644
index 000000000..708de588c
--- /dev/null
+++ b/libjava/classpath/java/awt/event/WindowAdapter.java
@@ -0,0 +1,156 @@
+/* WindowAdapter.java -- convenience class for writing window listeners
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+/**
+ * This class implements <code>WindowListener</code>,
+ * <code>WindowStateListener</code>, and <code>WindowFocusListener</code>, and
+ * implements all methods with empty bodies. This allows a listener
+ * interested in listening to only a subset of any <code>WindowEvent</code>
+ * actions to extend this class and override only the desired methods.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see ComponentEvent
+ * @see ComponentListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class WindowAdapter
+ implements WindowListener, WindowStateListener, WindowFocusListener
+{
+ /**
+ * Do nothing default constructor for subclasses.
+ */
+ public WindowAdapter()
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void windowOpened(WindowEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void windowClosing(WindowEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void windowClosed(WindowEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void windowIconified(WindowEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void windowDeiconified(WindowEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void windowActivated(WindowEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ */
+ public void windowDeactivated(WindowEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ * @since 1.4
+ */
+ public void windowStateChanged(WindowEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ * @since 1.4
+ */
+ public void windowGainedFocus(WindowEvent event)
+ {
+ }
+
+ /**
+ * Implements this method from the interface with an empty method body.
+ *
+ * @param event the event, ignored in this implementation
+ * @since 1.4
+ */
+ public void windowLostFocus(WindowEvent event)
+ {
+ }
+} // class WindowAdapter
diff --git a/libjava/classpath/java/awt/event/WindowEvent.java b/libjava/classpath/java/awt/event/WindowEvent.java
new file mode 100644
index 000000000..b52fefcdc
--- /dev/null
+++ b/libjava/classpath/java/awt/event/WindowEvent.java
@@ -0,0 +1,314 @@
+/* WindowEvent.java -- window change event
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.awt.Frame;
+import java.awt.Window;
+
+/**
+ * This event is generated when there is a change in a window. This includes
+ * creation, closing, iconification, activation, and focus changes. There
+ * are three listeners, for three types of events: WindowListeners deal with
+ * the lifecycle of a window, WindowStateListeners deal with window state
+ * like maximization, and WindowFocusListeners deal with focus switching to
+ * or from a window.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see WindowAdapter
+ * @see WindowListener
+ * @see WindowFocusListener
+ * @see WindowStateListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class WindowEvent extends ComponentEvent
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = -1567959133147912127L;
+
+ /** This is the first id in the range of event ids used by this class. */
+ public static final int WINDOW_FIRST = 200;
+
+ /** This is the id for a window that is opened. */
+ public static final int WINDOW_OPENED = 200;
+
+ /** This is the id for a window that is about to close. */
+ public static final int WINDOW_CLOSING = 201;
+
+ /** This is the id for a window that finished closing. */
+ public static final int WINDOW_CLOSED = 202;
+
+ /** This is the id for a window that is iconified. */
+ public static final int WINDOW_ICONIFIED = 203;
+
+ /** This is the id for a window that is de-iconified. */
+ public static final int WINDOW_DEICONIFIED = 204;
+
+ /** This is the id for a window that is activated. */
+ public static final int WINDOW_ACTIVATED = 205;
+
+ /** This is the id for a window that is de-activated. */
+ public static final int WINDOW_DEACTIVATED = 206;
+
+ /**
+ * This is the id for a window becoming the focused window.
+ *
+ * @since 1.4
+ */
+ public static final int WINDOW_GAINED_FOCUS = 207;
+
+ /**
+ * This is the id for a window losing all focus.
+ *
+ * @since 1.4
+ */
+ public static final int WINDOW_LOST_FOCUS = 208;
+
+ /**
+ * This is the id for a window state change, such as maximization.
+ *
+ * @since 1.4
+ */
+ public static final int WINDOW_STATE_CHANGED = 209;
+
+ /** This is the last id in the range of event ids used by this class. */
+ public static final int WINDOW_LAST = 209;
+
+ /**
+ * The other Window involved in a focus or activation change. For
+ * WINDOW_ACTIVATED and WINDOW_GAINED_FOCUS events, this is the window that
+ * lost focus; for WINDOW_DEACTIVATED and WINDOW_LOST_FOCUS, this is the
+ * window that stole focus; and for other events (or when native
+ * implementation does not have the data available), this is null.
+ *
+ * @see #getOppositeWindow()
+ * @serial the opposite window, or null
+ * @since 1.4
+ */
+ private final Window opposite;
+
+ /**
+ * The former state of the window.
+ *
+ * @serial bitmask of the old window state
+ * @since 1.4
+ */
+ private final int oldState;
+
+ /**
+ * The present state of the window.
+ *
+ * @serial bitmask of the new window state
+ * @since 1.4
+ */
+ private final int newState;
+
+ /**
+ * Initializes a new instance of <code>WindowEvent</code> with the specified
+ * parameters. Note that an invalid id leads to unspecified results.
+ *
+ * @param source the window that generated this event
+ * @param id the event id
+ * @param opposite the window that received the opposite event, or null
+ * @param oldState the previous state of this window
+ * @param newState the new state of this window
+ * @throws IllegalArgumentException if source is null
+ * @since 1.4
+ */
+ public WindowEvent(Window source, int id, Window opposite,
+ int oldState, int newState)
+ {
+ super(source, id);
+ this.opposite = opposite;
+ this.oldState = oldState;
+ this.newState = newState;
+ }
+
+ /**
+ * Initializes a new instance of <code>WindowEvent</code> with the specified
+ * parameters. Note that an invalid id leads to unspecified results.
+ *
+ * @param source the window that generated this event
+ * @param id the event id
+ * @param opposite the window that received the opposite event, or null
+ * @throws IllegalArgumentException if source is null
+ * @since 1.4
+ */
+ public WindowEvent(Window source, int id, Window opposite)
+ {
+ this(source, id, opposite, 0, 0);
+ }
+
+ /**
+ * Initializes a new instance of <code>WindowEvent</code> with the specified
+ * parameters. Note that an invalid id leads to unspecified results.
+ *
+ * @param source the window that generated this event
+ * @param id the event id
+ * @param oldState the previous state of this window
+ * @param newState the new state of this window
+ * @throws IllegalArgumentException if source is null
+ * @since 1.4
+ */
+ public WindowEvent(Window source, int id, int oldState, int newState)
+ {
+ this(source, id, null, oldState, newState);
+ }
+
+ /**
+ * Initializes a new instance of <code>WindowEvent</code> with the specified
+ * parameters. Note that an invalid id leads to unspecified results.
+ *
+ * @param source the window that generated this event
+ * @param id the event id
+ * @throws IllegalArgumentException if source is null
+ */
+ public WindowEvent(Window source, int id)
+ {
+ this(source, id, null, 0, 0);
+ }
+
+ /**
+ * Returns the event source as a <code>Window</code>. If the source has
+ * subsequently been modified to a non-Window, this returns null.
+ *
+ * @return the event source as a <code>Window</code>
+ */
+ public Window getWindow()
+ {
+ return source instanceof Window ? (Window) source : null;
+ }
+
+ /**
+ * Returns the opposite window if this window was involved in an activation
+ * or focus change. For WINDOW_ACTIVATED and WINDOW_GAINED_FOCUS events,
+ * this is the window that lost focus; for WINDOW_DEACTIVATED and
+ * WINDOW_LOST_FOCUS, this is the window that stole focus; and for other
+ * events (or when native implementation does not have the data available),
+ * this is null.
+ *
+ * @return the opposite window, or null
+ * @since 1.4
+ */
+ public Window getOppositeWindow()
+ {
+ return opposite;
+ }
+
+ /**
+ * Returns the state of this window before the event. This is the bitwise
+ * or of fields in Frame: NORMAL, ICONIFIED, MAXIMIZED_HORIZ, MAXIMIZED_VERT,
+ * and MAXIMIZED_BOTH.
+ *
+ * @return the former state
+ * @see Frame#getExtendedState()
+ * @since 1.4
+ */
+ public int getOldState()
+ {
+ return oldState;
+ }
+
+ /**
+ * Returns the state of this window after the event. This is the bitwise
+ * or of fields in Frame: NORMAL, ICONIFIED, MAXIMIZED_HORIZ, MAXIMIZED_VERT,
+ * and MAXIMIZED_BOTH.
+ *
+ * @return the updated state
+ * @see Frame#getExtendedState()
+ * @since 1.4
+ */
+ public int getNewState()
+ {
+ return newState;
+ }
+
+ /**
+ * Returns a string that identifies this event. This is formatted as the
+ * field name of the id, followed by the opposite window, old state, and
+ * new state.
+ *
+ * @return a string that identifies this event
+ */
+ public String paramString()
+ {
+ CPStringBuilder s = new CPStringBuilder();
+ switch (id)
+ {
+ case WINDOW_OPENED:
+ s.append("WINDOW_OPENED,opposite=");
+ break;
+ case WINDOW_CLOSING:
+ s.append("WINDOW_CLOSING,opposite=");
+ break;
+ case WINDOW_CLOSED:
+ s.append("WINDOW_CLOSED,opposite=");
+ break;
+ case WINDOW_ICONIFIED:
+ s.append("WINDOW_ICONIFIED,opposite=");
+ break;
+ case WINDOW_DEICONIFIED:
+ s.append("WINDOW_DEICONIFIED,opposite=");
+ break;
+ case WINDOW_ACTIVATED:
+ s.append("WINDOW_ACTIVATED,opposite=");
+ break;
+ case WINDOW_DEACTIVATED:
+ s.append("WINDOW_DEACTIVATED,opposite=");
+ break;
+ case WINDOW_GAINED_FOCUS:
+ s.append("WINDOW_GAINED_FOCUS,opposite=");
+ break;
+ case WINDOW_LOST_FOCUS:
+ s.append("WINDOW_LOST_FOCUS,opposite=");
+ break;
+ case WINDOW_STATE_CHANGED:
+ s.append("WINDOW_STATE_CHANGED,opposite=");
+ break;
+ default:
+ s.append("unknown type,opposite=");
+ }
+ return s.append(opposite).append(",oldState=").append(oldState)
+ .append(",newState=").append(newState).toString();
+ }
+} // class WindowEvent
diff --git a/libjava/classpath/java/awt/event/WindowFocusListener.java b/libjava/classpath/java/awt/event/WindowFocusListener.java
new file mode 100644
index 000000000..738425353
--- /dev/null
+++ b/libjava/classpath/java/awt/event/WindowFocusListener.java
@@ -0,0 +1,68 @@
+/* WindowFocusListener.java -- listens for window focus events
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that wish to monitor events for window
+ * focus changes. To watch a subset of these events, use a WindowAdapter.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see WindowAdapter
+ * @see WindowEvent
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public interface WindowFocusListener extends EventListener
+{
+ /**
+ * This method is called when a window gains focus.
+ *
+ * @param event the <code>WindowEvent</code> indicating the focus change
+ */
+ void windowGainedFocus(WindowEvent event);
+
+ /**
+ * This method is called when a window loses focus.
+ *
+ * @param event the <code>WindowEvent</code> indicating the focus change
+ */
+ void windowLostFocus(WindowEvent event);
+} // interface WindowFocusListener
diff --git a/libjava/classpath/java/awt/event/WindowListener.java b/libjava/classpath/java/awt/event/WindowListener.java
new file mode 100644
index 000000000..52213eb3d
--- /dev/null
+++ b/libjava/classpath/java/awt/event/WindowListener.java
@@ -0,0 +1,109 @@
+/* WindowListener.java -- listens for window events
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.awt.Frame;
+import java.awt.Image;
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that wish to monitor events for window
+ * changes. To watch a subset of these events, use a WindowAdapter.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @see WindowAdapter
+ * @see WindowEvent
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface WindowListener extends EventListener
+{
+ /**
+ * This method is called when the window is made visible.
+ *
+ * @param event the <code>WindowEvent</code> indicating the change
+ */
+ void windowOpened(WindowEvent event);
+
+ /**
+ * This method is called when the user calls the system menu close
+ * function, giving the program a chance to cancel the close.
+ *
+ * @param event the <code>WindowEvent</code> indicating the close attempt
+ */
+ void windowClosing(WindowEvent event);
+
+ /**
+ * This method is called when the window is closed.
+ *
+ * @param event the <code>WindowEvent</code> indicating the dispose
+ */
+ void windowClosed(WindowEvent event);
+
+ /**
+ * This method is called when the window is iconified.
+ *
+ * @param event the <code>WindowEvent</code> indicating the iconification
+ * @see Frame#setIconImage(Image)
+ */
+ void windowIconified(WindowEvent event);
+
+ /**
+ * This method is called when the window is deiconified.
+ *
+ * @param event the <code>WindowEvent</code> indicating the deiconification
+ */
+ void windowDeiconified(WindowEvent event);
+
+ /**
+ * This method is called when a window is activated. Only Frames and Dialogs
+ * can be active, and the active window always contains the component with
+ * focus.
+ *
+ * @param event the <code>WindowEvent</code> indicating the activation
+ */
+ void windowActivated(WindowEvent event);
+
+ /**
+ * This method is called when the window is deactivated.
+ *
+ * @param event the <code>WindowEvent</code> indicating the deactivation
+ */
+ void windowDeactivated(WindowEvent event);
+} // interface WindowListener
diff --git a/libjava/classpath/java/awt/event/WindowStateListener.java b/libjava/classpath/java/awt/event/WindowStateListener.java
new file mode 100644
index 000000000..9bc6174fd
--- /dev/null
+++ b/libjava/classpath/java/awt/event/WindowStateListener.java
@@ -0,0 +1,62 @@
+/* WindowStateListener.java -- listens for window state changes
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.event;
+
+import java.util.EventListener;
+
+/**
+ * This interface is for classes that wish to monitor events for window
+ * state changes.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see WindowAdapter
+ * @see WindowEvent
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public interface WindowStateListener extends EventListener
+{
+ /**
+ * This method is called when the window state is changed, because of
+ * iconification or maximization.
+ *
+ * @param event the <code>WindowEvent</code> indicating the change
+ */
+ void windowStateChanged(WindowEvent event);
+} // interface WindowStateListener
diff --git a/libjava/classpath/java/awt/event/package.html b/libjava/classpath/java/awt/event/package.html
new file mode 100644
index 000000000..77662a3fb
--- /dev/null
+++ b/libjava/classpath/java/awt/event/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt.event package.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - java.awt.event</title></head>
+
+<body>
+<p>Listeners and adapters for different kinds of AWT events.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/font/FontRenderContext.java b/libjava/classpath/java/awt/font/FontRenderContext.java
new file mode 100644
index 000000000..8d530ec5f
--- /dev/null
+++ b/libjava/classpath/java/awt/font/FontRenderContext.java
@@ -0,0 +1,137 @@
+/* FontRenderContext.java
+ Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+import java.awt.geom.AffineTransform;
+
+/**
+ * @author Michael Koch
+ */
+public class FontRenderContext
+{
+ private AffineTransform affineTransform;
+ private boolean isAntiAliased;
+ private boolean usesFractionalMetrics;
+
+ /**
+ * Construct a new <code>FontRenderContext</code>.
+ */
+ protected FontRenderContext()
+ {
+ // Do nothing here.
+ }
+
+ /**
+ * Construct a new <code>FontRenderContext</code>.
+ */
+ public FontRenderContext (AffineTransform tx, boolean isAntiAliased,
+ boolean usesFractionalMetrics)
+ {
+ if (tx != null
+ && !tx.isIdentity ())
+ {
+ this.affineTransform = new AffineTransform (tx);
+ }
+
+ this.isAntiAliased = isAntiAliased;
+ this.usesFractionalMetrics = usesFractionalMetrics;
+ }
+
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof FontRenderContext))
+ return false;
+
+ return equals ((FontRenderContext) obj);
+ }
+
+ public boolean equals (FontRenderContext rhs)
+ {
+ if (rhs == null)
+ return false;
+
+ if (affineTransform == null && rhs.affineTransform != null
+ || affineTransform != null && rhs.affineTransform == null)
+ return false;
+
+ return ((affineTransform == rhs.affineTransform
+ || affineTransform.equals (rhs.getTransform ()))
+ && isAntiAliased == rhs.isAntiAliased ()
+ && usesFractionalMetrics == rhs.usesFractionalMetrics ());
+ }
+
+
+ /**
+ * Retrieves the affine transform for scaling typographical points
+ * to raster pixels.
+ *
+ * @return a clone of the transform object.
+ */
+ public AffineTransform getTransform ()
+ {
+ if (affineTransform == null)
+ return new AffineTransform ();
+ else
+ return new AffineTransform (affineTransform);
+ }
+
+
+ /**
+ * Returns the hash code of the font render context.
+ */
+ public int hashCode ()
+ {
+ int code = ( isAntiAliased ? 1 : 0 ) + ( usesFractionalMetrics ? 2 : 0 );
+
+ if( affineTransform != null && !affineTransform.isIdentity() )
+ code ^= affineTransform.hashCode();
+
+ return code;
+ }
+
+ public boolean isAntiAliased ()
+ {
+ return isAntiAliased;
+ }
+
+ public boolean usesFractionalMetrics ()
+ {
+ return usesFractionalMetrics;
+ }
+}
diff --git a/libjava/classpath/java/awt/font/GlyphJustificationInfo.java b/libjava/classpath/java/awt/font/GlyphJustificationInfo.java
new file mode 100644
index 000000000..cfa64f05e
--- /dev/null
+++ b/libjava/classpath/java/awt/font/GlyphJustificationInfo.java
@@ -0,0 +1,77 @@
+/* GlyphJustificationInfo.java
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+/**
+ * @author Michael Koch
+ */
+public final class GlyphJustificationInfo
+{
+ public static final int PRIORITY_KASHIDA = 0;
+ public static final int PRIORITY_WHITESPACE = 1;
+ public static final int PRIORITY_INTERCHAR = 2;
+ public static final int PRIORITY_NONE = 3;
+
+ public final float weight;
+ public final int growPriority;
+ public final boolean growAbsorb;
+ public final float growLeftLimit;
+ public final float growRightLimit;
+ public final int shrinkPriority;
+ public final boolean shrinkAbsorb;
+ public final float shrinkLeftLimit;
+ public final float shrinkRightLimit;
+
+ public GlyphJustificationInfo (float weight, boolean growAbsorb,
+ int growPriority, float growLeftLimit,
+ float growRightLimit, boolean shrinkAbsorb,
+ int shrinkPriority, float shrinkLeftLimit,
+ float shrinkRightLimit)
+ {
+ this.weight = weight;
+ this.growAbsorb = growAbsorb;
+ this.growPriority = growPriority;
+ this.growLeftLimit = growLeftLimit;
+ this.growRightLimit = growRightLimit;
+ this.shrinkAbsorb = shrinkAbsorb;
+ this.shrinkPriority = shrinkPriority;
+ this.shrinkLeftLimit = shrinkLeftLimit;
+ this.shrinkRightLimit = shrinkRightLimit;
+ }
+}
diff --git a/libjava/classpath/java/awt/font/GlyphMetrics.java b/libjava/classpath/java/awt/font/GlyphMetrics.java
new file mode 100644
index 000000000..b41b7f45b
--- /dev/null
+++ b/libjava/classpath/java/awt/font/GlyphMetrics.java
@@ -0,0 +1,138 @@
+/* GlyphMetrics.java
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+import java.awt.geom.Rectangle2D;
+
+/**
+ * @author Michael Koch
+ */
+public final class GlyphMetrics
+{
+ public static final byte COMBINING = 2;
+ public static final byte COMPONENT = 3;
+ public static final byte LIGATURE = 1;
+ public static final byte STANDARD = 0;
+ public static final byte WHITESPACE = 4;
+
+ private boolean horizontal;
+ private float advanceX;
+ private float advanceY;
+ private Rectangle2D bounds;
+ private byte glyphType;
+
+ public GlyphMetrics (boolean horizontal, float advanceX, float advanceY,
+ Rectangle2D bounds, byte glyphType)
+ {
+ this.horizontal = horizontal;
+ this.advanceX = advanceX;
+ this.advanceY = advanceY;
+ this.bounds = bounds;
+ this.glyphType = glyphType;
+ }
+
+ public GlyphMetrics (float advance, Rectangle2D bounds, byte glyphType)
+ {
+ this (true, advance, advance, bounds, glyphType);
+ }
+
+ public float getAdvance ()
+ {
+ return horizontal ? advanceX : advanceY;
+ }
+
+ public float getAdvanceX ()
+ {
+ return advanceX;
+ }
+
+ public float getAdvanceY ()
+ {
+ return advanceY;
+ }
+
+ public Rectangle2D getBounds2D ()
+ {
+ return bounds;
+ }
+
+ public float getLSB()
+ {
+ if (horizontal)
+ return (float) bounds.getX();
+ return (float) bounds.getY();
+ }
+
+ public float getRSB()
+ {
+ if (horizontal)
+ return (float) (advanceX - (bounds.getX() + bounds.getWidth()));
+ return (float) (advanceY - (bounds.getY() + bounds.getHeight()));
+ }
+
+ public int getType ()
+ {
+ return glyphType;
+ }
+
+ public boolean isCombining ()
+ {
+ return (glyphType == COMBINING);
+ }
+
+ public boolean isComponent ()
+ {
+ return (glyphType == COMPONENT);
+ }
+
+ public boolean isLigature()
+ {
+ return (glyphType == LIGATURE);
+ }
+
+ public boolean isStandard()
+ {
+ return (glyphType == STANDARD);
+ }
+
+ public boolean isWhitespace()
+ {
+ return (glyphType == WHITESPACE);
+ }
+}
diff --git a/libjava/classpath/java/awt/font/GlyphVector.java b/libjava/classpath/java/awt/font/GlyphVector.java
new file mode 100644
index 000000000..4a87f4c62
--- /dev/null
+++ b/libjava/classpath/java/awt/font/GlyphVector.java
@@ -0,0 +1,174 @@
+/* GlyphVector.java
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+import java.awt.Font;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * @author Lillian Angel (langel at redhat dot com)
+ * @author Michael Koch
+ */
+public abstract class GlyphVector implements Cloneable
+{
+ public static final int FLAG_COMPLEX_GLYPHS = 8;
+ public static final int FLAG_HAS_POSITION_ADJUSTMENTS = 2;
+ public static final int FLAG_HAS_TRANSFORMS = 1;
+ public static final int FLAG_MASK = 15;
+ public static final int FLAG_RUN_RTL = 4;
+
+ /**
+ * Constructs a <code>GlyphVector</code> object.
+ */
+ public GlyphVector ()
+ {
+ }
+
+ public abstract boolean equals (GlyphVector set);
+
+ public abstract Font getFont ();
+
+ public abstract FontRenderContext getFontRenderContext ();
+
+ public int getGlyphCharIndex (int glyphIndex)
+ {
+ return glyphIndex;
+ }
+
+ public int[] getGlyphCharIndices(int beginGlyphIndex, int numEntries,
+ int[] codeReturn)
+ {
+ if (codeReturn == null)
+ codeReturn = new int[numEntries];
+
+ int i = 0;
+ int j = beginGlyphIndex;
+ while (j < numEntries)
+ codeReturn[i++] = getGlyphCharIndex(j++);
+
+ return codeReturn;
+ }
+
+ public abstract int getGlyphCode (int glyphIndex);
+
+ public abstract int[] getGlyphCodes (int beginGlyphIndex, int numEntries,
+ int[] codeReturn);
+
+ public abstract GlyphJustificationInfo getGlyphJustificationInfo
+ (int glyphIndex);
+
+ public abstract Shape getGlyphLogicalBounds (int glyphIndex);
+
+ public abstract GlyphMetrics getGlyphMetrics (int glyphIndex);
+
+ public abstract Shape getGlyphOutline (int glyphIndex);
+
+ public Shape getGlyphOutline(int glyphIndex, float x, float y)
+ {
+ Shape s = getGlyphOutline(glyphIndex);
+
+ // This is the only way to translate the origin of a shape
+ AffineTransform at = AffineTransform.getTranslateInstance(x, y);
+ return at.createTransformedShape(s);
+ }
+
+ public Rectangle getGlyphPixelBounds(int index, FontRenderContext renderFRC,
+ float x, float y)
+ {
+ Rectangle bounds = new Rectangle();
+ Rectangle2D rect = getGlyphVisualBounds(index).getBounds2D();
+
+ bounds.x = (int) (rect.getX() + x);
+ bounds.y = (int) (rect.getY() + y);
+ bounds.width = (int) rect.getMaxX() - bounds.x;
+ bounds.height = (int) rect.getMaxY() - bounds.y;
+
+ return bounds;
+ }
+
+ public abstract Point2D getGlyphPosition (int glyphIndex);
+
+ public abstract float[] getGlyphPositions (int beginGlyphIndex,
+ int numEntries,
+ float[] positionReturn);
+
+ public abstract AffineTransform getGlyphTransform (int glyphIndex);
+
+ public abstract Shape getGlyphVisualBounds (int glyphIndex);
+
+ public int getLayoutFlags()
+ {
+ return 0;
+ }
+
+ public abstract Rectangle2D getLogicalBounds ();
+
+ public abstract int getNumGlyphs ();
+
+ public abstract Shape getOutline ();
+
+ public abstract Shape getOutline (float x, float y);
+
+ public Rectangle getPixelBounds (FontRenderContext renderFRC,
+ float x, float y)
+ {
+ Rectangle bounds = new Rectangle();
+ Rectangle2D rect = getVisualBounds();
+
+ bounds.x = (int) (rect.getX() + x);
+ bounds.y = (int) (rect.getY() + y);
+ bounds.width = (int) rect.getMaxX() - bounds.x;
+ bounds.height = (int) rect.getMaxY() - bounds.y;
+
+ return bounds;
+ }
+
+ public abstract Rectangle2D getVisualBounds ();
+
+ public abstract void performDefaultLayout ();
+
+ public abstract void setGlyphPosition (int glyphIndex, Point2D newPos);
+
+ public abstract void setGlyphTransform (int glyphIndex,
+ AffineTransform newTX);
+}
diff --git a/libjava/classpath/java/awt/font/GraphicAttribute.java b/libjava/classpath/java/awt/font/GraphicAttribute.java
new file mode 100644
index 000000000..edf0c204d
--- /dev/null
+++ b/libjava/classpath/java/awt/font/GraphicAttribute.java
@@ -0,0 +1,137 @@
+/* GraphicAttribute.java
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+import java.awt.Graphics2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * This class represents a graphic embedded in text.
+ *
+ * @author Michael Koch
+ * @author Lillian Angel (langel at redhat dot com)
+ */
+public abstract class GraphicAttribute
+{
+ public static final int BOTTOM_ALIGNMENT = - 2;
+ public static final int CENTER_BASELINE = 1;
+ public static final int HANGING_BASELINE = 2;
+ public static final int ROMAN_BASELINE = 0;
+ public static final int TOP_ALIGNMENT = - 1;
+
+ private int alignment;
+
+ /**
+ * Constructor.
+ *
+ * @param alignment - the alignment to use for the graphic
+ */
+ protected GraphicAttribute(int alignment)
+ {
+ if (alignment < BOTTOM_ALIGNMENT || alignment > HANGING_BASELINE)
+ throw new IllegalArgumentException("Invalid alignment");
+ this.alignment = alignment;
+ }
+
+ /**
+ * Draws the graphic.
+ *
+ * @param graphics - the graphics configuration to use
+ * @param x - the x location
+ * @param y - the y location
+ */
+ public abstract void draw(Graphics2D graphics, float x, float y);
+
+ /**
+ * Gets the distance from the origin of its graphic to the right side of the
+ * bounds of its graphic.
+ *
+ * @return the advance
+ */
+ public abstract float getAdvance();
+
+ /**
+ * Gets the positive distance from the origin of its graphic to the top of
+ * bounds.
+ *
+ * @return the ascent
+ */
+ public abstract float getAscent();
+
+ /**
+ * Gets the distance from the origin of its graphic to the bottom of the bounds.
+ *
+ * @return the descent
+ */
+ public abstract float getDescent();
+
+ /**
+ * Gets the alignment.
+ *
+ * @return the alignment
+ */
+ public final int getAlignment()
+ {
+ return alignment;
+ }
+
+ /**
+ * Returns a Rectangle2D that encloses the rendered area.
+ * Default bounds is the rectangle (0, -ascent, advance, ascent+descent).
+ *
+ * @return the bounds of the rendered area
+ */
+ public Rectangle2D getBounds()
+ {
+ float asc = getAscent();
+ return new Rectangle2D.Float(0, - asc, getAdvance(), asc + getDescent());
+ }
+
+ /**
+ * Returns the justification information for this object.
+ *
+ * @return the justification information
+ */
+ public GlyphJustificationInfo getJustificationInfo()
+ {
+ float adv = getAdvance();
+ return new GlyphJustificationInfo(adv, false, 2, adv / 3, adv / 3, false,
+ 1, 0, 0);
+ }
+}
diff --git a/libjava/classpath/java/awt/font/ImageGraphicAttribute.java b/libjava/classpath/java/awt/font/ImageGraphicAttribute.java
new file mode 100644
index 000000000..63fff4101
--- /dev/null
+++ b/libjava/classpath/java/awt/font/ImageGraphicAttribute.java
@@ -0,0 +1,187 @@
+/* ImageGraphicAttribute.java
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * This is an implementation of GraphicAttribute which draws images in a
+ * TextLayout.
+ *
+ * @author Lillian Angel
+ * @author Michael Koch
+ */
+public final class ImageGraphicAttribute
+ extends GraphicAttribute
+{
+ private Image image;
+ private float originX;
+ private float originY;
+
+ /**
+ * Constucts an instance from the specified Image. The origin is at (0, 0).
+ *
+ * @param image - image to construct from.
+ * @param alignment - the alignment
+ */
+ public ImageGraphicAttribute(Image image, int alignment)
+ {
+ this(image, alignment, 0, 0);
+ }
+
+ /**
+ * Constucts an instance from the specified Image. The origin is at (originX,
+ * originY).
+ *
+ * @param image - image to construct from
+ * @param alignment - the alignment
+ * @param originX - x point of origin
+ * @param originY - y point of origin
+ */
+ public ImageGraphicAttribute(Image image, int alignment, float originX,
+ float originY)
+ {
+ super(alignment);
+ this.image = image;
+ this.originX = originX;
+ this.originY = originY;
+ }
+
+ /**
+ * Draws the image at the specified location, relative to the
+ * origin.
+ *
+ * @param g - the graphics to use to render the image
+ * @param x - the x location
+ * @param y - the y location
+ */
+ public void draw(Graphics2D g, float x, float y)
+ {
+ g.drawImage(image, (int) (x - originX), (int) (y - originY), null);
+ }
+
+ /**
+ * Compares this to the specified Object
+ *
+ * @param obj - the object to compare
+ * @return true if the obj and this are equivalent
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof ImageGraphicAttribute))
+ return false;
+
+ return equals((ImageGraphicAttribute) obj);
+ }
+
+ /**
+ * Compares this to the ImageGraphicAttribute given, by
+ * comparing all fields and values.
+ *
+ * @param rhs - the ImageGraphicAttribute to compare
+ * @return true if the object given is equivalent to this
+ */
+ public boolean equals(ImageGraphicAttribute rhs)
+ {
+ return ((this == rhs) || ((this.getAscent() == rhs.getAscent())
+ && (this.getAdvance() == rhs.getAdvance())
+ && (this.getAlignment() == rhs.getAlignment())
+ && (this.getBounds().equals(rhs.getBounds()))
+ && (this.getDescent() == rhs.getDescent())
+ && (this.hashCode() == rhs.hashCode())
+ && (this.image.equals(rhs.image))
+ && (this.originX == rhs.originX)
+ && (this.originY == rhs.originY)));
+ }
+
+ /**
+ * Returns distance from the origin to the right edge of the image of this.
+ *
+ * @return the advance
+ */
+ public float getAdvance()
+ {
+ return Math.max(0, image.getWidth(null) - originX);
+ }
+
+ /**
+ * Returns the the distance from the top of the image to the origin of this.
+ *
+ * @return the ascent.
+ */
+ public float getAscent()
+ {
+ return Math.max(0, originY);
+ }
+
+ /**
+ * Gets the bounds of the object rendered, relative to the position.
+ *
+ * @return the bounds of the object rendered, relative to the position.
+ */
+ public Rectangle2D getBounds()
+ {
+ // This is equivalent to what Sun's JDK returns.
+ // I am not entirely sure why the origin is negative.
+ return new Rectangle2D.Float(- originX, - originY, image.getWidth(null),
+ image.getHeight(null));
+ }
+
+ /**
+ * Returns the distance from the origin to the bottom of the image.
+ *
+ * @return the descent
+ */
+ public float getDescent()
+ {
+ return Math.max(0, image.getHeight(null) - originY);
+ }
+
+ /**
+ * Gets the hash code for this image.
+ *
+ * @return the hash code
+ */
+ public int hashCode()
+ {
+ return image.hashCode();
+ }
+}
diff --git a/libjava/classpath/java/awt/font/LineBreakMeasurer.java b/libjava/classpath/java/awt/font/LineBreakMeasurer.java
new file mode 100644
index 000000000..d11f20d1f
--- /dev/null
+++ b/libjava/classpath/java/awt/font/LineBreakMeasurer.java
@@ -0,0 +1,148 @@
+/* LineBreakMeasurer.java
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+import java.text.AttributedCharacterIterator;
+import java.text.BreakIterator;
+
+public final class LineBreakMeasurer
+{
+ private AttributedCharacterIterator text;
+ private int position;
+ private TextMeasurer tm;
+ private int numChars;
+
+ public LineBreakMeasurer(AttributedCharacterIterator text,
+ BreakIterator breakIter, FontRenderContext frc)
+ {
+ this( text, frc );
+ }
+
+ public LineBreakMeasurer(AttributedCharacterIterator text,
+ FontRenderContext frc)
+ {
+ this.text = text;
+ position = 0;
+ numChars = text.getEndIndex();
+ tm = new TextMeasurer( text, frc );
+ }
+
+ public void deleteChar(AttributedCharacterIterator newParagraph,
+ int deletePos)
+ {
+ tm.deleteChar( newParagraph, deletePos );
+ position = 0;
+ }
+
+ public void insertChar(AttributedCharacterIterator newParagraph,
+ int insertPos)
+ {
+ tm.insertChar( newParagraph, insertPos );
+ position = 0;
+ }
+
+ public TextLayout nextLayout(float wrappingWidth)
+ {
+ return nextLayout( wrappingWidth, numChars, false );
+ }
+
+ public TextLayout nextLayout(float wrappingWidth, int offsetLimit,
+ boolean requireNextWord)
+ {
+ int next = nextOffset( wrappingWidth, offsetLimit, requireNextWord );
+ TextLayout tl = tm.getLayout( position, next );
+ position = next;
+ return tl;
+ }
+
+ public int nextOffset(float wrappingWidth)
+ {
+ return nextOffset( wrappingWidth, numChars, false );
+ }
+
+ public int nextOffset(float wrappingWidth, int offsetLimit,
+ boolean requireNextWord)
+ {
+ int guessOffset = tm.getLineBreakIndex(position, wrappingWidth);
+ if( offsetLimit > numChars )
+ offsetLimit = numChars;
+
+ if( guessOffset > offsetLimit )
+ {
+ text.setIndex( offsetLimit );
+ return offsetLimit;
+ }
+
+ text.setIndex( guessOffset );
+
+ // If we're on a breaking character, return directly
+ if( Character.isWhitespace( text.current() ) )
+ return guessOffset;
+
+ // Otherwise jump forward or backward to the last such char.
+ if( !requireNextWord )
+ while( !Character.isWhitespace( text.previous() ) &&
+ guessOffset > position )
+ guessOffset--;
+ else
+ while( !Character.isWhitespace( text.next() ) &&
+ guessOffset < offsetLimit )
+ guessOffset++;
+
+ if( guessOffset > offsetLimit )
+ {
+ text.setIndex( offsetLimit );
+ return offsetLimit;
+ }
+
+ text.setIndex( guessOffset );
+
+ return guessOffset;
+ }
+
+ public void setPosition(int newPosition)
+ {
+ position = newPosition;
+ }
+
+ public int getPosition()
+ {
+ return position;
+ }
+}
diff --git a/libjava/classpath/java/awt/font/LineMetrics.java b/libjava/classpath/java/awt/font/LineMetrics.java
new file mode 100644
index 000000000..d43fd98bb
--- /dev/null
+++ b/libjava/classpath/java/awt/font/LineMetrics.java
@@ -0,0 +1,67 @@
+/* LineMetrics.java -- Information about about a line display characteristics
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+/**
+ * @author Michael Koch
+ */
+public abstract class LineMetrics
+{
+ public abstract float getAscent();
+
+ public abstract int getBaselineIndex();
+
+ public abstract float[] getBaselineOffsets();
+
+ public abstract float getDescent();
+
+ public abstract float getHeight();
+
+ public abstract float getLeading();
+
+ public abstract int getNumChars();
+
+ public abstract float getStrikethroughOffset();
+
+ public abstract float getStrikethroughThickness();
+
+ public abstract float getUnderlineOffset();
+
+ public abstract float getUnderlineThickness();
+}
diff --git a/libjava/classpath/java/awt/font/MultipleMaster.java b/libjava/classpath/java/awt/font/MultipleMaster.java
new file mode 100644
index 000000000..1be44bd75
--- /dev/null
+++ b/libjava/classpath/java/awt/font/MultipleMaster.java
@@ -0,0 +1,61 @@
+/* MultipleMaster.java
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+import java.awt.Font;
+
+/**
+ * @author Michael Koch
+ */
+public interface MultipleMaster
+{
+ Font deriveMMFont (float[] axes);
+
+ Font deriveMMFont (float[] glyphWidths, float avgStemWidth,
+ float typicalCapHeight, float typicalXHeight,
+ float italicAngle);
+
+ float[] getDesignAxisDefaults();
+
+ String[] getDesignAxisNames();
+
+ float[] getDesignAxisRanges();
+
+ int getNumDesignAxes();
+}
diff --git a/libjava/classpath/java/awt/font/NumericShaper.java b/libjava/classpath/java/awt/font/NumericShaper.java
new file mode 100644
index 000000000..add1c6a44
--- /dev/null
+++ b/libjava/classpath/java/awt/font/NumericShaper.java
@@ -0,0 +1,425 @@
+/* NumericShaper.java
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+import java.io.Serializable;
+import java.lang.Character.UnicodeBlock;
+
+/**
+ * This class handles numeric shaping. A shaper can either be contextual
+ * or not. A non-contextual shaper will always translate ASCII digits
+ * in its input into the target Unicode range. A contextual shaper will
+ * change the target Unicode range depending on the characters it has
+ * previously processed.
+ *
+ * @author Michael Koch
+ * @author Tom Tromey
+ *
+ * @since 1.4
+ * @specnote This class does not handle LIMBU or OSMANYA.
+ * @specnote The JDK does not seem to properly handle ranges without a
+ * digit zero, such as TAMIL. This implementation does.
+ */
+public final class NumericShaper implements Serializable
+{
+ private static final long serialVersionUID = -8022764705923730308L;
+
+ /** Convenience constant representing all the valid Unicode ranges. */
+ public static final int ALL_RANGES = 524287;
+
+ /**
+ * Constant representing the Unicode ARABIC range. Shaping done
+ * using this range will translate to the arabic decimal characters.
+ * Use EASTERN_ARABIC if you want to shape to the eastern arabic
+ * (also known as the extended arabic) decimal characters.
+ */
+ public static final int ARABIC = 2;
+
+ /** Constant representing the Unicode BENGALI range. */
+ public static final int BENGALI = 16;
+
+ /** Constant representing the Unicode DEVANAGARI range. */
+ public static final int DEVANAGARI = 8;
+
+ /**
+ * Constant representing the Unicode extended arabic range.
+ * In Unicode there are two different sets of arabic digits;
+ * this selects the extended or eastern set.
+ */
+ public static final int EASTERN_ARABIC = 4;
+
+ /**
+ * Constant representing the Unicode ETHIOPIC range. Note that
+ * there is no digit zero in this range; an ASCII digit zero
+ * is left unchanged when shaping to this range.
+ */
+ public static final int ETHIOPIC = 65536;
+
+ /**
+ * Constant representing the Unicode EUROPEAN range. For
+ * contextual shaping purposes, characters in the various
+ * extended Latin character blocks are recognized as EUROPEAN.
+ */
+ public static final int EUROPEAN = 1;
+
+ /** Constant representing the Unicode GUJARATI range. */
+ public static final int GUJARATI = 64;
+
+ /** Constant representing the Unicode GURMUKHI range. */
+ public static final int GURMUKHI = 32;
+
+ /** Constant representing the Unicode KANNADA range. */
+ public static final int KANNADA = 1024;
+
+ /** Constant representing the Unicode KHMER range. */
+ public static final int KHMER = 131072;
+
+ /** Constant representing the Unicode LAO range. */
+ public static final int LAO = 8192;
+
+ /** Constant representing the Unicode MALAYALAM range. */
+ public static final int MALAYALAM = 2048;
+
+ /** Constant representing the Unicode MONGOLIAN range. */
+ public static final int MONGOLIAN = 262144;
+
+ /** Constant representing the Unicode MYANMAR range. */
+ public static final int MYANMAR = 32768;
+
+ /** Constant representing the Unicode ORIYA range. */
+ public static final int ORIYA = 128;
+
+ /**
+ * Constant representing the Unicode TAMIL range. Note that
+ * there is no digit zero in this range; an ASCII digit zero
+ * is left unchanged when shaping to this range.
+ */
+ public static final int TAMIL = 256;
+
+ /** Constant representing the Unicode TELUGU range. */
+ public static final int TELUGU = 512;
+
+ /** Constant representing the Unicode THAI range. */
+ public static final int THAI = 4096;
+
+ /** Constant representing the Unicode TIBETAN range. */
+ public static final int TIBETAN = 16384;
+
+ /**
+ * This table holds the zero digits for each language. This is hard-coded
+ * because the values will not change and the table layout is tied to the
+ * other constants in this class in any case. In the two places where a
+ * language does not have a zero digit, the character immediately preceeding
+ * the one digit is used instead. These languages are special-cased in
+ * the shaping code.
+ */
+ private static final char[] zeroDigits =
+ {
+ '0', // EUROPEAN
+ '\u0660', // ARABIC
+ '\u06f0', // EASTERN_ARABIC
+ '\u0966', // DEVANAGARI
+ '\u09e6', // BENGALI
+ '\u0a66', // GURMUKHI
+ '\u0ae6', // GUJARATI
+ '\u0b66', // ORIYA
+ '\u0be6', // TAMIL - special case as there is no digit zero
+ '\u0c66', // TELUGU
+ '\u0ce6', // KANNADA
+ '\u0d66', // MALAYALAM
+ '\u0e50', // THAI
+ '\u0ed0', // LAO
+ '\u0f20', // TIBETAN
+ '\u1040', // MYANMAR
+ '\u1368', // ETHIOPIC - special case as there is no digit zero
+ '\u17e0', // KHMER
+ '\u1810' // MONGOLIAN
+ };
+
+ /**
+ * The default initial context for this shaper, specified as
+ * an integer from 0 to 18.
+ */
+ private int key;
+
+ /**
+ * The target ranges handled by this shaper. If the shaper
+ * is not contextual, the high bit of this field will be set.
+ * @specnote This was discovered by reading the serialization spec
+ */
+ private int mask;
+
+ /**
+ * Create a new numeric shaper. The key given is a constant from
+ * this class, the constructor turns it into its internal form.
+ * @param key the key to use, as one of the manifest constants
+ * @param mask a mask of languages to shape for
+ */
+ private NumericShaper (int key, int mask)
+ {
+ // This internal form is a bit goofy, but it is specified by
+ // the serialization spec.
+ this.key = Integer.numberOfTrailingZeros(key);
+ this.mask = mask;
+ }
+
+ /**
+ * Return an integer representing all the languages for which this
+ * shaper will shape. The result is taken by "or"ing together
+ * the constants representing the various languages.
+ */
+ public int getRanges ()
+ {
+ return mask & ALL_RANGES;
+ }
+
+ /**
+ * Return true if this shaper is contextual, false if it is not.
+ */
+ public boolean isContextual ()
+ {
+ return mask > 0;
+ }
+
+ /**
+ * Shape the text in the given array. The starting context will
+ * be the context passed to the shaper at creation time.
+ * @param text the text to shape
+ * @param start the index of the starting character of the array
+ * @param count the number of characters in the array
+ */
+ public void shape (char[] text, int start, int count)
+ {
+ shape (text, start, count, 1 << key);
+ }
+
+ /**
+ * Given a unicode block object, return corresponding language constant.
+ * If the block is not recognized, returns zero. Note that as there
+ * is no separate ARABIC block in Character, this case must
+ * be specially handled by the caller; EASTERN_ARABIC is preferred when
+ * both are specified.
+ * @param b the unicode block to classify
+ * @return the language constant, or zero if not recognized
+ */
+ private int classify(UnicodeBlock b)
+ {
+ if (b == null)
+ return 0;
+ // ARABIC is handled by the caller; from testing we know
+ // that EASTERN_ARABIC takes precedence.
+ if (b == UnicodeBlock.ARABIC)
+ return EASTERN_ARABIC;
+ if (b == UnicodeBlock.BENGALI)
+ return BENGALI;
+ if (b == UnicodeBlock.DEVANAGARI)
+ return DEVANAGARI;
+ if (b == UnicodeBlock.ETHIOPIC)
+ return ETHIOPIC;
+ if (b == UnicodeBlock.BASIC_LATIN
+ || b == UnicodeBlock.LATIN_1_SUPPLEMENT
+ || b == UnicodeBlock.LATIN_EXTENDED_A
+ || b == UnicodeBlock.LATIN_EXTENDED_ADDITIONAL
+ || b == UnicodeBlock.LATIN_EXTENDED_B)
+ return EUROPEAN;
+ if (b == UnicodeBlock.GUJARATI)
+ return GUJARATI;
+ if (b == UnicodeBlock.GURMUKHI)
+ return GURMUKHI;
+ if (b == UnicodeBlock.KANNADA)
+ return KANNADA;
+ if (b == UnicodeBlock.KHMER)
+ return KHMER;
+ if (b == UnicodeBlock.LAO)
+ return LAO;
+ if (b == UnicodeBlock.MALAYALAM)
+ return MALAYALAM;
+ if (b == UnicodeBlock.MONGOLIAN)
+ return MONGOLIAN;
+ if (b == UnicodeBlock.MYANMAR)
+ return MYANMAR;
+ if (b == UnicodeBlock.ORIYA)
+ return ORIYA;
+ if (b == UnicodeBlock.TAMIL)
+ return TAMIL;
+ if (b == UnicodeBlock.TELUGU)
+ return TELUGU;
+ if (b == UnicodeBlock.THAI)
+ return THAI;
+ if (b == UnicodeBlock.TIBETAN)
+ return TIBETAN;
+ return 0;
+ }
+
+ /**
+ * Shape the given text, using the indicated initial context.
+ * If this shaper is not a contextual shaper, then the given context
+ * will be ignored.
+ * @param text the text to shape
+ * @param start the index of the first character of the text to shape
+ * @param count the number of characters to shape in the text
+ * @param context the initial context
+ * @throws IllegalArgumentException if the initial context is invalid
+ */
+ public void shape (char[] text, int start, int count, int context)
+ {
+ int currentContext;
+ if (isContextual())
+ {
+ if (Integer.bitCount(context) != 1 || (context & ~ALL_RANGES) != 0)
+ throw new IllegalArgumentException("invalid context argument");
+ // If the indicated context is not one we are handling, reset it.
+ if ((context & mask) == 0)
+ currentContext = -1;
+ else
+ currentContext = Integer.numberOfTrailingZeros(context);
+ }
+ else
+ currentContext = key;
+
+ for (int i = 0; i < count; ++i)
+ {
+ char c = text[start + i];
+ if (c >= '0' && c <= '9')
+ {
+ if (currentContext >= 0)
+ {
+ // Shape into the current context.
+ if (c == '0'
+ && ((1 << currentContext) == TAMIL
+ || (1 << currentContext) == ETHIOPIC))
+ {
+ // No digit 0 in this context; do nothing.
+ }
+ else
+ text[start + i]
+ = (char) (zeroDigits[currentContext] + c - '0');
+ }
+ }
+ else if (isContextual())
+ {
+ // if c is in a group, set currentContext; else reset it.
+ int group = classify(UnicodeBlock.of(c));
+ // Specially handle ARABIC.
+ if (group == EASTERN_ARABIC && (mask & EASTERN_ARABIC) == 0
+ && (mask & ARABIC) != 0)
+ group = ARABIC;
+ if ((mask & group) != 0)
+ {
+ // The character was classified as being in a group
+ // we recognize, and it was selected by the shaper.
+ // So, change the context.
+ currentContext = Integer.numberOfTrailingZeros(group);
+ }
+ }
+ }
+ }
+
+ public boolean equals (Object obj)
+ {
+ if (! (obj instanceof NumericShaper))
+ return false;
+ NumericShaper tmp = (NumericShaper) obj;
+ return key == tmp.key && mask == tmp.mask;
+ }
+
+ public int hashCode ()
+ {
+ return key ^ mask;
+ }
+
+ public String toString ()
+ {
+ // For debugging only.
+ return "key=" + key + "; mask=" + mask;
+ }
+
+ /**
+ * Return a non-contextual shaper which can shape to a single range.
+ * All ASCII digits in the input text are translated to this language.
+ * @param singleRange the target language
+ * @return a non-contextual shaper for this language
+ * @throws IllegalArgumentException if the argument does not name a
+ * single language, as specified by the constants declared in this class
+ */
+ public static NumericShaper getShaper (int singleRange)
+ {
+ if (Integer.bitCount(singleRange) != 1)
+ throw new IllegalArgumentException("more than one bit set in argument");
+ if ((singleRange & ~ALL_RANGES) != 0)
+ throw new IllegalArgumentException("argument out of range");
+ return new NumericShaper(singleRange, Integer.MIN_VALUE | singleRange);
+ }
+
+ /**
+ * Return a contextual shaper which can shape to any of the indicated
+ * languages. The default initial context for this shaper is EUROPEAN.
+ * @param ranges the ranges to shape to
+ * @return a contextual shaper which will target any of these ranges
+ * @throws IllegalArgumentException if the argument specifies an
+ * unrecognized range
+ */
+ public static NumericShaper getContextualShaper (int ranges)
+ {
+ if ((ranges & ~ALL_RANGES) != 0)
+ throw new IllegalArgumentException("argument out of range");
+ return new NumericShaper(EUROPEAN, ranges);
+ }
+
+ /**
+ * Return a contextual shaper which can shape to any of the indicated
+ * languages. The default initial context for this shaper is given as
+ * an argument.
+ * @param ranges the ranges to shape to
+ * @param defaultContext the default initial context
+ * @return a contextual shaper which will target any of these ranges
+ * @throws IllegalArgumentException if the ranges argument specifies an
+ * unrecognized range, or if the defaultContext argument does not specify
+ * a single valid range
+ */
+ public static NumericShaper getContextualShaper (int ranges,
+ int defaultContext)
+ {
+ if (Integer.bitCount(defaultContext) != 1)
+ throw new IllegalArgumentException("more than one bit set in context");
+ if ((ranges & ~ALL_RANGES) != 0 || (defaultContext & ~ALL_RANGES) != 0)
+ throw new IllegalArgumentException("argument out of range");
+ return new NumericShaper(defaultContext, ranges);
+ }
+}
diff --git a/libjava/classpath/java/awt/font/OpenType.java b/libjava/classpath/java/awt/font/OpenType.java
new file mode 100644
index 000000000..e992d0700
--- /dev/null
+++ b/libjava/classpath/java/awt/font/OpenType.java
@@ -0,0 +1,111 @@
+/* OpenType.java
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+/**
+ * @author Michael Koch
+ */
+public interface OpenType
+{
+ int TAG_ACNT = 1633906292;
+ int TAG_AVAR = 1635148146;
+ int TAG_BASE = 1111577413;
+ int TAG_BDAT = 1650745716;
+ int TAG_BLOC = 1651273571;
+ int TAG_BSLN = 1651731566;
+ int TAG_CFF = 1128678944;
+ int TAG_CMAP = 1668112752;
+ int TAG_CVAR = 1668702578;
+ int TAG_CVT = 1668707360;
+ int TAG_DSIG = 1146308935;
+ int TAG_EBDT = 1161970772;
+ int TAG_EBLC = 1161972803;
+ int TAG_EBSC = 1161974595;
+ int TAG_FDSC = 1717859171;
+ int TAG_FEAT = 1717920116;
+ int TAG_FMTX = 1718449272;
+ int TAG_FPGM = 1718642541;
+ int TAG_FVAR = 1719034226;
+ int TAG_GASP = 1734439792;
+ int TAG_GDEF = 1195656518;
+ int TAG_GLYF = 1735162214;
+ int TAG_GPOS = 1196445523;
+ int TAG_GSUB = 1196643650;
+ int TAG_GVAR = 1735811442;
+ int TAG_HDMX = 1751412088;
+ int TAG_HEAD = 1751474532;
+ int TAG_HHEA = 1751672161;
+ int TAG_HMTX = 1752003704;
+ int TAG_JSTF = 1246975046;
+ int TAG_JUST = 1786082164;
+ int TAG_KERN = 1801810542;
+ int TAG_LCAR = 1818452338;
+ int TAG_LOCA = 1819239265;
+ int TAG_LTSH = 1280594760;
+ int TAG_MAXP = 1835104368;
+ int TAG_MMFX = 1296909912;
+ int TAG_MMSD = 1296913220;
+ int TAG_MORT = 1836020340;
+ int TAG_NAME = 1851878757;
+ int TAG_OPBD = 1836020340;
+ int TAG_OS2 = 1330851634;
+ int TAG_PCLT = 1346587732;
+ int TAG_POST = 1886352244;
+ int TAG_PREP = 1886545264;
+ int TAG_PROP = 1886547824;
+ int TAG_TRAK = 1953653099;
+ int TAG_TYP1 = 1954115633;
+ int TAG_VDMX = 1447316824;
+ int TAG_VHEA = 1986553185;
+ int TAG_VMTX = 1986884728;
+
+ byte[] getFontTable (int sfntTag);
+
+ byte[] getFontTable (int sfntTag, int offset, int count);
+
+ byte[] getFontTable (String strSfntTag);
+
+ byte[] getFontTable (String strSfntTag, int offset, int count);
+
+ int getFontTableSize (int sfntTag);
+
+ int getFontTableSize (String strSfntTag);
+
+ int getVersion ();
+}
diff --git a/libjava/classpath/java/awt/font/ShapeGraphicAttribute.java b/libjava/classpath/java/awt/font/ShapeGraphicAttribute.java
new file mode 100644
index 000000000..8d6891632
--- /dev/null
+++ b/libjava/classpath/java/awt/font/ShapeGraphicAttribute.java
@@ -0,0 +1,185 @@
+/* ShapeGraphicAttribute.java
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * This is an implementation of GraphicAttribute that draws shapes in a TextLayout.
+ *
+ * @author Lillian Angel (langel at redhat dot com)
+ */
+public final class ShapeGraphicAttribute extends GraphicAttribute
+{
+ /** True if the shape should be filled. */
+ public static final boolean FILL = false;
+
+ /** True if the shape should be stroked with a 1-pixel wide stroke. */
+ public static final boolean STROKE = true;
+
+ private Shape shape;
+ private boolean stroke;
+ private Rectangle2D bounds;
+
+ /**
+ * Constructor.
+ *
+ * @param shape - the Shape to render. The Shape is rendered with its origin.
+ * @param alignment - the alignment
+ * @param stroke - true if the Shape should be stroked; false if the Shape
+ * should be filled.
+ */
+ public ShapeGraphicAttribute(Shape shape, int alignment, boolean stroke)
+ {
+ super(alignment);
+ this.shape = shape;
+ this.stroke = stroke;
+ this.bounds = shape.getBounds2D();
+ }
+
+ /**
+ * Draws the graphic at the given location.
+ *
+ * @param graphics - the graphics to use.
+ * @param x - the x location to draw at.
+ * @param y - the y location to draw at.
+ */
+ public void draw(Graphics2D graphics, float x, float y)
+ {
+ graphics.translate(x, y);
+ if (stroke == STROKE)
+ graphics.draw(shape);
+ else
+ graphics.fill(shape);
+ graphics.translate(- x, - y);
+ }
+
+ /**
+ * Compares this ShapeGraphicAttribute to obj.
+ *
+ * @param obj - the object to compare.
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof ShapeGraphicAttribute))
+ return false;
+
+ return equals((ShapeGraphicAttribute) obj);
+ }
+
+ /**
+ * Compares this ShapeGraphicAttribute to rhs.
+ *
+ * @param rhs - the ShapeGraphicAttribute to compare.
+ */
+ public boolean equals(ShapeGraphicAttribute rhs)
+ {
+ return (this == rhs || (this.shape.equals(rhs.shape)
+ && getAlignment() == rhs.getAlignment()
+ && stroke == rhs.stroke
+ && getAdvance() == rhs.getAdvance()
+ && getAscent() == rhs.getAscent()
+ && getBounds().equals(rhs.getBounds())
+ && getDescent() == rhs.getDescent()
+ && hashCode() == rhs.hashCode()));
+ }
+
+ /**
+ * Gets the distance from the origin of its Shape to the right side of the
+ * bounds of its Shape.
+ *
+ * @return the advance
+ */
+ public float getAdvance()
+ {
+ return Math.max(0, (float) bounds.getMaxX());
+ }
+
+ /**
+ * Gets the positive distance from the origin of its Shape to the top of
+ * bounds.
+ *
+ * @return the ascent
+ */
+ public float getAscent()
+ {
+ return Math.max(0, -(float) bounds.getMinY());
+ }
+
+ /**
+ * Gets the distance from the origin of its Shape to the bottom of the bounds.
+ *
+ * @return the descent
+ */
+ public float getDescent()
+ {
+ return Math.max(0, (float) bounds.getMaxY());
+ }
+
+ /**
+ * Returns a Rectangle2D that encloses all of the bits drawn by this shape.
+ *
+ * @return the bounds of the shape.
+ */
+ public Rectangle2D getBounds()
+ {
+ Rectangle2D.Float bounds = new Rectangle2D.Float();
+ bounds.setRect(this.bounds);
+
+ if (stroke == STROKE)
+ {
+ bounds.width++;
+ bounds.height++;
+ }
+
+ return bounds;
+ }
+
+ /**
+ * Gets the hash code.
+ *
+ * @return the hash code.
+ */
+ public int hashCode()
+ {
+ return shape.hashCode();
+ }
+}
diff --git a/libjava/classpath/java/awt/font/TextAttribute.java b/libjava/classpath/java/awt/font/TextAttribute.java
new file mode 100644
index 000000000..bfade21bb
--- /dev/null
+++ b/libjava/classpath/java/awt/font/TextAttribute.java
@@ -0,0 +1,309 @@
+/* TextAttribute.java --
+ Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+import java.io.InvalidObjectException;
+import java.text.AttributedCharacterIterator;
+
+/**
+ * Attributes (and associated values) that can be used to define an
+ * {@link java.text.AttributedString}.
+ */
+public final class TextAttribute extends AttributedCharacterIterator.Attribute
+{
+ private static final long serialVersionUID = 7744112784117861702L;
+
+ /** A key for the background paint attribute. */
+ public static final TextAttribute BACKGROUND =
+ new TextAttribute("background");
+
+ /** A key for the BIDI_EMBEDDING attribute. */
+ public static final TextAttribute BIDI_EMBEDDING =
+ new TextAttribute("bidi_embedding");
+
+ /** A key for the CHAR_REPLACEMENT attribute. */
+ public static final TextAttribute CHAR_REPLACEMENT =
+ new TextAttribute("char_replacement");
+
+ /** A key for the FAMILY attribute. */
+ public static final TextAttribute FAMILY = new TextAttribute("family");
+
+ /** A key for the font attribute. */
+ public static final TextAttribute FONT = new TextAttribute("font");
+
+ /** A key for the foreground paint attribute. */
+ public static final TextAttribute FOREGROUND =
+ new TextAttribute("foreground");
+
+ /** A key for the INPUT_METHOD_HIGHLIGHT attribute. */
+ public static final TextAttribute INPUT_METHOD_HIGHLIGHT =
+ new TextAttribute("input method highlight");
+
+ /** A key for the INPUT_METHOD_UNDERLINE attribute. */
+ public static final TextAttribute INPUT_METHOD_UNDERLINE =
+ new TextAttribute("input method underline");
+
+ /** A key for the text justification attribute. */
+ public static final TextAttribute JUSTIFICATION =
+ new TextAttribute("justification");
+
+ /**
+ * A value that can be used with the {@link #JUSTIFICATION} attribute to
+ * indicate full justification of the text.
+ */
+ public static final Float JUSTIFICATION_FULL = new Float(1.0);
+
+ /**
+ * A value that can be used with the {@link #JUSTIFICATION} attribute to
+ * indicate no justification of the text.
+ */
+ public static final Float JUSTIFICATION_NONE = new Float(0.0);
+
+ /** A key for the NUMERIC_SHAPING attribute. */
+ public static final TextAttribute NUMERIC_SHAPING =
+ new TextAttribute("numeric_shaping");
+
+ /** A key for the POSTURE attribute. */
+ public static final TextAttribute POSTURE = new TextAttribute("posture");
+
+ /** A value that can be used with the {@link #POSTURE} attribute. */
+ public static final Float POSTURE_OBLIQUE = new Float(0.2);
+
+ /** A value that can be used with the {@link #POSTURE} attribute. */
+ public static final Float POSTURE_REGULAR = new Float(0.0);
+
+ /** A key for the RUN_DIRECTION attribute. */
+ public static final TextAttribute RUN_DIRECTION =
+ new TextAttribute("run_direction");
+
+ /** A value that can be used with the {@link #RUN_DIRECTION} attribute. */
+ public static final Boolean RUN_DIRECTION_LTR = Boolean.FALSE;
+
+ /** A value that can be used with the {@link #RUN_DIRECTION} attribute. */
+ public static final Boolean RUN_DIRECTION_RTL = Boolean.TRUE;
+
+ /** A key for the text size attribute. */
+ public static final TextAttribute SIZE = new TextAttribute("size");
+
+ /** A key for the STRIKETHROUGH attribute. */
+ public static final TextAttribute STRIKETHROUGH =
+ new TextAttribute("strikethrough");
+
+ /** A value that can be used with the {@link #STRIKETHROUGH} attribute. */
+ public static final Boolean STRIKETHROUGH_ON = Boolean.TRUE;
+
+ /** A key for the SUPERSCRIPT attribute. */
+ public static final TextAttribute SUPERSCRIPT =
+ new TextAttribute("superscript");
+
+ /** A value that can be used with the {@link #SUPERSCRIPT} attribute. */
+ public static final Integer SUPERSCRIPT_SUB = new Integer(-1);
+
+ /** A value that can be used with the {@link #SUPERSCRIPT} attribute. */
+ public static final Integer SUPERSCRIPT_SUPER = new Integer(1);
+
+ /** A key for the SWAP_COLORS attribute. */
+ public static final TextAttribute SWAP_COLORS =
+ new TextAttribute("swap_colors");
+
+ /** A value that can be used with the {@link #SWAP_COLORS} attribute. */
+ public static final Boolean SWAP_COLORS_ON = Boolean.TRUE;
+
+ /** A key for the TRANFORM attribute. */
+ public static final TextAttribute TRANSFORM = new TextAttribute("transform");
+
+ /** A key for the UNDERLINE attribute. */
+ public static final TextAttribute UNDERLINE = new TextAttribute("underline");
+
+ /** A value that can be used with the {@link #UNDERLINE} attribute. */
+ public static final Integer UNDERLINE_LOW_DASHED = new Integer(5);
+
+ /** A value that can be used with the {@link #UNDERLINE} attribute. */
+ public static final Integer UNDERLINE_LOW_DOTTED = new Integer(3);
+
+ /** A value that can be used with the {@link #UNDERLINE} attribute. */
+ public static final Integer UNDERLINE_LOW_GRAY = new Integer(4);
+
+ /** A value that can be used with the {@link #UNDERLINE} attribute. */
+ public static final Integer UNDERLINE_LOW_ONE_PIXEL = new Integer(1);
+
+ /** A value that can be used with the {@link #UNDERLINE} attribute. */
+ public static final Integer UNDERLINE_LOW_TWO_PIXEL = new Integer(2);
+
+ /** A value that can be used with the {@link #UNDERLINE} attribute. */
+ public static final Integer UNDERLINE_ON = new Integer(0);
+
+ /** A key for the WEIGHT attribute. */
+ public static final TextAttribute WEIGHT = new TextAttribute("weight");
+
+ /** A value that can be used with the {@link #WEIGHT} attribute. */
+ public static final Float WEIGHT_BOLD = new Float(2.0);
+
+ /** A value that can be used with the {@link #WEIGHT} attribute. */
+ public static final Float WEIGHT_DEMIBOLD = new Float(1.75);
+
+ /** A value that can be used with the {@link #WEIGHT} attribute. */
+ public static final Float WEIGHT_DEMILIGHT = new Float(0.875);
+
+ /** A value that can be used with the {@link #WEIGHT} attribute. */
+ public static final Float WEIGHT_EXTRA_LIGHT = new Float(0.5);
+
+ /** A value that can be used with the {@link #WEIGHT} attribute. */
+ public static final Float WEIGHT_EXTRABOLD = new Float(2.5);
+
+ /** A value that can be used with the {@link #WEIGHT} attribute. */
+ public static final Float WEIGHT_HEAVY = new Float(2.25);
+
+ /** A value that can be used with the {@link #WEIGHT} attribute. */
+ public static final Float WEIGHT_LIGHT = new Float(0.75);
+
+ /** A value that can be used with the {@link #WEIGHT} attribute. */
+ public static final Float WEIGHT_MEDIUM = new Float(1.5);
+
+ /** A value that can be used with the {@link #WEIGHT} attribute. */
+ public static final Float WEIGHT_REGULAR = new Float(1.0);
+
+ /** A value that can be used with the {@link #WEIGHT} attribute. */
+ public static final Float WEIGHT_SEMIBOLD = new Float(1.25);
+
+ /** A value that can be used with the {@link #WEIGHT} attribute. */
+ public static final Float WEIGHT_ULTRABOLD = new Float(2.75);
+
+ /** A key for the WIDTH attribute. */
+ public static final TextAttribute WIDTH = new TextAttribute("width");
+
+ /** A value that can be used with the {@link #WIDTH} attribute. */
+ public static final Float WIDTH_CONDENSED = new Float(0.75);
+
+ /** A value that can be used with the {@link #WIDTH} attribute. */
+ public static final Float WIDTH_EXTENDED = new Float(1.5);
+
+ /** A value that can be used with the {@link #WIDTH} attribute. */
+ public static final Float WIDTH_REGULAR = new Float(1.0);
+
+ /** A value that can be used with the {@link #WIDTH} attribute. */
+ public static final Float WIDTH_SEMI_CONDENSED = new Float(0.875);
+
+ /** A value that can be used with the {@link #WIDTH} attribute. */
+ public static final Float WIDTH_SEMI_EXTENDED = new Float(1.25);
+
+ /**
+ * Creates a new attribute.
+ *
+ * @param name the name.
+ */
+ protected TextAttribute(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * After deserialization, this method ensures that only one instance of
+ * each attribute is used.
+ *
+ * @return The (single) attribute instance.
+ *
+ * @throws InvalidObjectException if the attribute is not recognised.
+ */
+ protected Object readResolve()
+ throws InvalidObjectException
+ {
+ if (this.getName().equals("background"))
+ return BACKGROUND;
+
+ if (this.getName().equals("bidi_embedding"))
+ return BIDI_EMBEDDING;
+
+ if (this.getName().equals("char_replacement"))
+ return CHAR_REPLACEMENT;
+
+ if (this.getName().equals("family"))
+ return FAMILY;
+
+ if (this.getName().equals("font"))
+ return FONT;
+
+ if (this.getName().equals("foreground"))
+ return FOREGROUND;
+
+ if (this.getName().equals("input method highlight"))
+ return INPUT_METHOD_HIGHLIGHT;
+
+ if (this.getName().equals("input method underline"))
+ return INPUT_METHOD_UNDERLINE;
+
+ if (this.getName().equals("justification"))
+ return JUSTIFICATION;
+
+ if (this.getName().equals("numeric_shaping"))
+ return NUMERIC_SHAPING;
+
+ if (this.getName().equals("posture"))
+ return POSTURE;
+
+ if (this.getName().equals("run_direction"))
+ return RUN_DIRECTION;
+
+ if (this.getName().equals("size"))
+ return SIZE;
+
+ if (this.getName().equals("strikethrough"))
+ return STRIKETHROUGH;
+
+ if (this.getName().equals("superscript"))
+ return SUPERSCRIPT;
+
+ if (this.getName().equals("swap_colors"))
+ return SWAP_COLORS;
+
+ if (this.getName().equals("transform"))
+ return TRANSFORM;
+
+ if (this.getName().equals("underline"))
+ return UNDERLINE;
+
+ if (this.getName().equals("weight"))
+ return WEIGHT;
+
+ if (this.getName().equals("width"))
+ return WIDTH;
+
+ throw new InvalidObjectException("Can't resolve Attribute: " + getName());
+ }
+}
diff --git a/libjava/classpath/java/awt/font/TextHitInfo.java b/libjava/classpath/java/awt/font/TextHitInfo.java
new file mode 100644
index 000000000..17479b09e
--- /dev/null
+++ b/libjava/classpath/java/awt/font/TextHitInfo.java
@@ -0,0 +1,128 @@
+/* TextHitInfo.java --
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.font;
+
+/**
+ * @author John Leuner (jewel@debian.org)
+ */
+public final class TextHitInfo
+{
+ private int charIndex;
+ private boolean leadingEdge;
+
+ TextHitInfo (int charIndex, boolean leadingEdge)
+ {
+ this.charIndex = charIndex;
+ this.leadingEdge = leadingEdge;
+ }
+
+ public int getCharIndex()
+ {
+ return charIndex;
+ }
+
+ public boolean isLeadingEdge()
+ {
+ return leadingEdge;
+ }
+
+ public int getInsertionIndex()
+ {
+ return (leadingEdge ? charIndex : charIndex + 1);
+ }
+
+ public int hashCode()
+ {
+ return charIndex;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if(obj instanceof TextHitInfo)
+ return this.equals((TextHitInfo) obj);
+
+ return false;
+ }
+
+ public boolean equals(TextHitInfo hitInfo)
+ {
+ if (hitInfo == null)
+ return false;
+
+ return (charIndex == hitInfo.getCharIndex ())
+ && (leadingEdge == hitInfo.isLeadingEdge ());
+ }
+
+ public static TextHitInfo leading(int charIndex)
+ {
+ return new TextHitInfo (charIndex, true);
+ }
+
+ public static TextHitInfo trailing(int charIndex)
+ {
+ return new TextHitInfo (charIndex, false);
+ }
+
+ public static TextHitInfo beforeOffset(int offset)
+ {
+ return new TextHitInfo ((offset - 1), false);
+ }
+
+ public static TextHitInfo afterOffset(int offset)
+ {
+ return new TextHitInfo (offset, true);
+ }
+
+ public TextHitInfo getOtherHit()
+ {
+ return (leadingEdge ? trailing (charIndex - 1) : leading (charIndex + 1));
+ }
+
+ public TextHitInfo getOffsetHit(int offset)
+ {
+ return new TextHitInfo (charIndex + offset, leadingEdge);
+ }
+
+ public String toString()
+ {
+ return "TextHitInfo["
+ + charIndex
+ + (leadingEdge ? "L" : "T" )
+ + "]";
+ }
+}
diff --git a/libjava/classpath/java/awt/font/TextLayout.java b/libjava/classpath/java/awt/font/TextLayout.java
new file mode 100644
index 000000000..c4f174245
--- /dev/null
+++ b/libjava/classpath/java/awt/font/TextLayout.java
@@ -0,0 +1,1420 @@
+/* TextLayout.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Line2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Point2D;
+import java.text.CharacterIterator;
+import java.text.AttributedCharacterIterator;
+import java.text.Bidi;
+import java.util.ArrayList;
+import java.util.Map;
+
+/**
+ * @author Sven de Marothy
+ */
+public final class TextLayout implements Cloneable
+{
+ /**
+ * Holds the layout data that belongs to one run of characters.
+ */
+ private class Run
+ {
+ /**
+ * The actual glyph vector.
+ */
+ GlyphVector glyphVector;
+
+ /**
+ * The font for this text run.
+ */
+ Font font;
+
+ /**
+ * The start of the run.
+ */
+ int runStart;
+
+ /**
+ * The end of the run.
+ */
+ int runEnd;
+
+ /**
+ * The layout location of the beginning of the run.
+ */
+ float location;
+
+ /**
+ * Initializes the Run instance.
+ *
+ * @param gv the glyph vector
+ * @param start the start index of the run
+ * @param end the end index of the run
+ */
+ Run(GlyphVector gv, Font f, int start, int end)
+ {
+ glyphVector = gv;
+ font = f;
+ runStart = start;
+ runEnd = end;
+ }
+
+ /**
+ * Returns <code>true</code> when this run is left to right,
+ * <code>false</code> otherwise.
+ *
+ * @return <code>true</code> when this run is left to right,
+ * <code>false</code> otherwise
+ */
+ boolean isLeftToRight()
+ {
+ return (glyphVector.getLayoutFlags() & GlyphVector.FLAG_RUN_RTL) == 0;
+ }
+ }
+
+ /**
+ * The laid out character runs.
+ */
+ private Run[] runs;
+
+ private FontRenderContext frc;
+ private char[] string;
+ private int offset;
+ private int length;
+ private Rectangle2D boundsCache;
+ private LineMetrics lm;
+
+ /**
+ * The total advance of this text layout. This is cache for maximum
+ * performance.
+ */
+ private float totalAdvance = -1F;
+
+ /**
+ * The cached natural bounds.
+ */
+ private Rectangle2D naturalBounds;
+
+ /**
+ * Character indices.
+ * Fixt index is the glyphvector, second index is the (first) glyph.
+ */
+ private int[][] charIndices;
+
+ /**
+ * Base directionality, determined from the first char.
+ */
+ private boolean leftToRight;
+
+ /**
+ * Whether this layout contains whitespace or not.
+ */
+ private boolean hasWhitespace = false;
+
+ /**
+ * The {@link Bidi} object that is used for reordering and by
+ * {@link #getCharacterLevel(int)}.
+ */
+ private Bidi bidi;
+
+ /**
+ * Mpas the logical position of each individual character in the original
+ * string to its visual position.
+ */
+ private int[] logicalToVisual;
+
+ /**
+ * Maps visual positions of a character to its logical position
+ * in the original string.
+ */
+ private int[] visualToLogical;
+
+ /**
+ * The cached hashCode.
+ */
+ private int hash;
+
+ /**
+ * The default caret policy.
+ */
+ public static final TextLayout.CaretPolicy DEFAULT_CARET_POLICY =
+ new CaretPolicy();
+
+ /**
+ * Constructs a TextLayout.
+ */
+ public TextLayout (String str, Font font, FontRenderContext frc)
+ {
+ this.frc = frc;
+ string = str.toCharArray();
+ offset = 0;
+ length = this.string.length;
+ lm = font.getLineMetrics(this.string, offset, length, frc);
+
+ // Get base direction and whitespace info
+ getStringProperties();
+
+ if (Bidi.requiresBidi(string, offset, offset + length))
+ {
+ bidi = new Bidi(str, leftToRight ? Bidi.DIRECTION_LEFT_TO_RIGHT
+ : Bidi.DIRECTION_RIGHT_TO_LEFT );
+ int rc = bidi.getRunCount();
+ byte[] table = new byte[ rc ];
+ for(int i = 0; i < table.length; i++)
+ table[i] = (byte)bidi.getRunLevel(i);
+
+ runs = new Run[rc];
+ for(int i = 0; i < rc; i++)
+ {
+ int start = bidi.getRunStart(i);
+ int end = bidi.getRunLimit(i);
+ if(start != end) // no empty runs.
+ {
+ GlyphVector gv = font.layoutGlyphVector(frc,
+ string, start, end,
+ ((table[i] & 1) == 0) ? Font.LAYOUT_LEFT_TO_RIGHT
+ : Font.LAYOUT_RIGHT_TO_LEFT );
+ runs[i] = new Run(gv, font, start, end);
+ }
+ }
+ Bidi.reorderVisually( table, 0, runs, 0, runs.length );
+ // Clean up null runs.
+ ArrayList cleaned = new ArrayList(rc);
+ for (int i = 0; i < rc; i++)
+ {
+ if (runs[i] != null)
+ cleaned.add(runs[i]);
+ }
+ runs = new Run[cleaned.size()];
+ runs = (Run[]) cleaned.toArray(runs);
+ }
+ else
+ {
+ GlyphVector gv = font.layoutGlyphVector( frc, string, offset, length,
+ leftToRight ? Font.LAYOUT_LEFT_TO_RIGHT
+ : Font.LAYOUT_RIGHT_TO_LEFT );
+ Run run = new Run(gv, font, 0, length);
+ runs = new Run[]{ run };
+ }
+ setCharIndices();
+ setupMappings();
+ layoutRuns();
+ }
+
+ public TextLayout (String string,
+ Map<? extends AttributedCharacterIterator.Attribute, ?> attributes,
+ FontRenderContext frc)
+ {
+ this( string, new Font( attributes ), frc );
+ }
+
+ public TextLayout (AttributedCharacterIterator text, FontRenderContext frc)
+ {
+ // FIXME: Very rudimentary.
+ this(getText(text), getFont(text), frc);
+ }
+
+ /**
+ * Package-private constructor to make a textlayout from an existing one.
+ * This is used by TextMeasurer for returning sub-layouts, and it
+ * saves a lot of time in not having to relayout the text.
+ */
+ TextLayout(TextLayout t, int startIndex, int endIndex)
+ {
+ frc = t.frc;
+ boundsCache = null;
+ lm = t.lm;
+ leftToRight = t.leftToRight;
+
+ if( endIndex > t.getCharacterCount() )
+ endIndex = t.getCharacterCount();
+ string = t.string;
+ offset = startIndex + offset;
+ length = endIndex - startIndex;
+
+ int startingRun = t.charIndices[startIndex][0];
+ int nRuns = 1 + t.charIndices[endIndex - 1][0] - startingRun;
+
+ runs = new Run[nRuns];
+ for( int i = 0; i < nRuns; i++ )
+ {
+ Run run = t.runs[i + startingRun];
+ GlyphVector gv = run.glyphVector;
+ Font font = run.font;
+ // Copy only the relevant parts of the first and last runs.
+ int beginGlyphIndex = (i > 0) ? 0 : t.charIndices[startIndex][1];
+ int numEntries = ( i < nRuns - 1) ? gv.getNumGlyphs() :
+ 1 + t.charIndices[endIndex - 1][1] - beginGlyphIndex;
+
+ int[] codes = gv.getGlyphCodes(beginGlyphIndex, numEntries, null);
+ gv = font.createGlyphVector(frc, codes);
+ runs[i] = new Run(gv, font, run.runStart - startIndex,
+ run.runEnd - startIndex);
+ }
+ runs[nRuns - 1].runEnd = endIndex - 1;
+
+ setCharIndices();
+ setupMappings();
+ determineWhiteSpace();
+ layoutRuns();
+ }
+
+ private void setCharIndices()
+ {
+ charIndices = new int[ getCharacterCount() ][2];
+ int i = 0;
+ int currentChar = 0;
+ for(int run = 0; run < runs.length; run++)
+ {
+ currentChar = -1;
+ Run current = runs[run];
+ GlyphVector gv = current.glyphVector;
+ for( int gi = 0; gi < gv.getNumGlyphs(); gi++)
+ {
+ if( gv.getGlyphCharIndex( gi ) != currentChar )
+ {
+ charIndices[ i ][0] = run;
+ charIndices[ i ][1] = gi;
+ currentChar = gv.getGlyphCharIndex( gi );
+ i++;
+ }
+ }
+ }
+ }
+
+ /**
+ * Initializes the logicalToVisual and visualToLogial maps.
+ */
+ private void setupMappings()
+ {
+ int numChars = getCharacterCount();
+ logicalToVisual = new int[numChars];
+ visualToLogical = new int[numChars];
+ int lIndex = 0;
+ int vIndex = 0;
+ // We scan the runs in visual order and set the mappings accordingly.
+ for (int i = 0; i < runs.length; i++)
+ {
+ Run run = runs[i];
+ if (run.isLeftToRight())
+ {
+ for (lIndex = run.runStart; lIndex < run.runEnd; lIndex++)
+ {
+ logicalToVisual[lIndex] = vIndex;
+ visualToLogical[vIndex] = lIndex;
+ vIndex++;
+ }
+ }
+ else
+ {
+ for (lIndex = run.runEnd - 1; lIndex >= run.runStart; lIndex--)
+ {
+ logicalToVisual[lIndex] = vIndex;
+ visualToLogical[vIndex] = lIndex;
+ vIndex++;
+ }
+ }
+ }
+ }
+
+ private static String getText(AttributedCharacterIterator iter)
+ {
+ CPStringBuilder sb = new CPStringBuilder();
+ int idx = iter.getIndex();
+ for(char c = iter.first(); c != CharacterIterator.DONE; c = iter.next())
+ sb.append(c);
+ iter.setIndex( idx );
+ return sb.toString();
+ }
+
+ private static Font getFont(AttributedCharacterIterator iter)
+ {
+ Font f = (Font)iter.getAttribute(TextAttribute.FONT);
+ if( f == null )
+ {
+ int size;
+ Float i = (Float)iter.getAttribute(TextAttribute.SIZE);
+ if( i != null )
+ size = (int)i.floatValue();
+ else
+ size = 14;
+ f = new Font("Dialog", Font.PLAIN, size );
+ }
+ return f;
+ }
+
+ /**
+ * Scan the character run for the first strongly directional character,
+ * which in turn defines the base directionality of the whole layout.
+ */
+ private void getStringProperties()
+ {
+ boolean gotDirection = false;
+ int i = offset;
+ int endOffs = offset + length;
+ leftToRight = true;
+ while( i < endOffs && !gotDirection )
+ switch( Character.getDirectionality(string[i++]) )
+ {
+ case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
+ case Character.DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING:
+ case Character.DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE:
+ gotDirection = true;
+ break;
+
+ case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
+ case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
+ case Character.DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING:
+ case Character.DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE:
+ leftToRight = false;
+ gotDirection = true;
+ break;
+ }
+ determineWhiteSpace();
+ }
+
+ private void determineWhiteSpace()
+ {
+ // Determine if there's whitespace in the thing.
+ // Ignore trailing chars.
+ int i = offset + length - 1;
+ hasWhitespace = false;
+ while( i >= offset && Character.isWhitespace( string[i] ) )
+ i--;
+ // Check the remaining chars
+ while( i >= offset )
+ if( Character.isWhitespace( string[i--] ) )
+ hasWhitespace = true;
+ }
+
+ protected Object clone ()
+ {
+ return new TextLayout( this, 0, length);
+ }
+
+ public void draw (Graphics2D g2, float x, float y)
+ {
+ for(int i = 0; i < runs.length; i++)
+ {
+ Run run = runs[i];
+ GlyphVector gv = run.glyphVector;
+ g2.drawGlyphVector(gv, x, y);
+ Rectangle2D r = gv.getLogicalBounds();
+ x += r.getWidth();
+ }
+ }
+
+ public boolean equals (Object obj)
+ {
+ if( !( obj instanceof TextLayout) )
+ return false;
+
+ return equals( (TextLayout) obj );
+ }
+
+ public boolean equals (TextLayout tl)
+ {
+ if( runs.length != tl.runs.length )
+ return false;
+ // Compare all glyph vectors.
+ for( int i = 0; i < runs.length; i++ )
+ if( !runs[i].equals( tl.runs[i] ) )
+ return false;
+ return true;
+ }
+
+ public float getAdvance ()
+ {
+ if (totalAdvance == -1F)
+ {
+ totalAdvance = 0f;
+ for(int i = 0; i < runs.length; i++)
+ {
+ Run run = runs[i];
+ GlyphVector gv = run.glyphVector;
+ totalAdvance += gv.getLogicalBounds().getWidth();
+ }
+ }
+ return totalAdvance;
+ }
+
+ public float getAscent ()
+ {
+ return lm.getAscent();
+ }
+
+ public byte getBaseline ()
+ {
+ return (byte)lm.getBaselineIndex();
+ }
+
+ public float[] getBaselineOffsets ()
+ {
+ return lm.getBaselineOffsets();
+ }
+
+ public Shape getBlackBoxBounds (int firstEndpoint, int secondEndpoint)
+ {
+ if( secondEndpoint - firstEndpoint <= 0 )
+ return new Rectangle2D.Float(); // Hmm?
+
+ if( firstEndpoint < 0 || secondEndpoint > getCharacterCount())
+ return new Rectangle2D.Float();
+
+ GeneralPath gp = new GeneralPath();
+
+ int ri = charIndices[ firstEndpoint ][0];
+ int gi = charIndices[ firstEndpoint ][1];
+
+ double advance = 0;
+
+ for( int i = 0; i < ri; i++ )
+ {
+ Run run = runs[i];
+ GlyphVector gv = run.glyphVector;
+ advance += gv.getLogicalBounds().getWidth();
+ }
+
+ for( int i = ri; i <= charIndices[ secondEndpoint - 1 ][0]; i++ )
+ {
+ Run run = runs[i];
+ GlyphVector gv = run.glyphVector;
+ int dg;
+ if( i == charIndices[ secondEndpoint - 1 ][0] )
+ dg = charIndices[ secondEndpoint - 1][1];
+ else
+ dg = gv.getNumGlyphs() - 1;
+
+ for( int j = 0; j <= dg; j++ )
+ {
+ Rectangle2D r2 = (gv.getGlyphVisualBounds( j )).
+ getBounds2D();
+ Point2D p = gv.getGlyphPosition( j );
+ r2.setRect( advance + r2.getX(), r2.getY(),
+ r2.getWidth(), r2.getHeight() );
+ gp.append(r2, false);
+ }
+
+ advance += gv.getLogicalBounds().getWidth();
+ }
+ return gp;
+ }
+
+ public Rectangle2D getBounds()
+ {
+ if( boundsCache == null )
+ boundsCache = getOutline(new AffineTransform()).getBounds();
+ return boundsCache;
+ }
+
+ public float[] getCaretInfo (TextHitInfo hit)
+ {
+ return getCaretInfo(hit, getNaturalBounds());
+ }
+
+ public float[] getCaretInfo (TextHitInfo hit, Rectangle2D bounds)
+ {
+ float[] info = new float[2];
+ int index = hit.getCharIndex();
+ boolean leading = hit.isLeadingEdge();
+ // For the boundary cases we return the boundary runs.
+ Run run;
+
+ if (index >= length)
+ {
+ info[0] = getAdvance();
+ info[1] = 0;
+ }
+ else
+ {
+ if (index < 0)
+ {
+ run = runs[0];
+ index = 0;
+ leading = true;
+ }
+ else
+ run = findRunAtIndex(index);
+
+ int glyphIndex = index - run.runStart;
+ Shape glyphBounds = run.glyphVector.getGlyphLogicalBounds(glyphIndex);
+ Rectangle2D glyphRect = glyphBounds.getBounds2D();
+ if (isVertical())
+ {
+ if (leading)
+ info[0] = (float) glyphRect.getMinY();
+ else
+ info[0] = (float) glyphRect.getMaxY();
+ }
+ else
+ {
+ if (leading)
+ info[0] = (float) glyphRect.getMinX();
+ else
+ info[0] = (float) glyphRect.getMaxX();
+ }
+ info[0] += run.location;
+ info[1] = run.font.getItalicAngle();
+ }
+ return info;
+ }
+
+ public Shape getCaretShape(TextHitInfo hit)
+ {
+ return getCaretShape(hit, getBounds());
+ }
+
+ public Shape getCaretShape(TextHitInfo hit, Rectangle2D bounds)
+ {
+ // TODO: Handle vertical shapes somehow.
+ float[] info = getCaretInfo(hit);
+ float x1 = info[0];
+ float y1 = (float) bounds.getMinY();
+ float x2 = info[0];
+ float y2 = (float) bounds.getMaxY();
+ if (info[1] != 0)
+ {
+ // Shift x1 and x2 according to the slope.
+ x1 -= y1 * info[1];
+ x2 -= y2 * info[1];
+ }
+ GeneralPath path = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 2);
+ path.moveTo(x1, y1);
+ path.lineTo(x2, y2);
+ return path;
+ }
+
+ public Shape[] getCaretShapes(int offset)
+ {
+ return getCaretShapes(offset, getNaturalBounds());
+ }
+
+ public Shape[] getCaretShapes(int offset, Rectangle2D bounds)
+ {
+ return getCaretShapes(offset, bounds, DEFAULT_CARET_POLICY);
+ }
+
+ public Shape[] getCaretShapes(int offset, Rectangle2D bounds,
+ CaretPolicy policy)
+ {
+ // The RI returns a 2-size array even when there's only one
+ // shape in it.
+ Shape[] carets = new Shape[2];
+ TextHitInfo hit1 = TextHitInfo.afterOffset(offset);
+ int caretHit1 = hitToCaret(hit1);
+ TextHitInfo hit2 = hit1.getOtherHit();
+ int caretHit2 = hitToCaret(hit2);
+ if (caretHit1 == caretHit2)
+ {
+ carets[0] = getCaretShape(hit1);
+ carets[1] = null; // The RI returns null in this seldom case.
+ }
+ else
+ {
+ Shape caret1 = getCaretShape(hit1);
+ Shape caret2 = getCaretShape(hit2);
+ TextHitInfo strong = policy.getStrongCaret(hit1, hit2, this);
+ if (strong == hit1)
+ {
+ carets[0] = caret1;
+ carets[1] = caret2;
+ }
+ else
+ {
+ carets[0] = caret2;
+ carets[1] = caret1;
+ }
+ }
+ return carets;
+ }
+
+ public int getCharacterCount ()
+ {
+ return length;
+ }
+
+ public byte getCharacterLevel (int index)
+ {
+ byte level;
+ if( bidi == null )
+ level = 0;
+ else
+ level = (byte) bidi.getLevelAt(index);
+ return level;
+ }
+
+ public float getDescent ()
+ {
+ return lm.getDescent();
+ }
+
+ public TextLayout getJustifiedLayout (float justificationWidth)
+ {
+ TextLayout newLayout = (TextLayout)clone();
+
+ if( hasWhitespace )
+ newLayout.handleJustify( justificationWidth );
+
+ return newLayout;
+ }
+
+ public float getLeading ()
+ {
+ return lm.getLeading();
+ }
+
+ public Shape getLogicalHighlightShape (int firstEndpoint, int secondEndpoint)
+ {
+ return getLogicalHighlightShape( firstEndpoint, secondEndpoint,
+ getBounds() );
+ }
+
+ public Shape getLogicalHighlightShape (int firstEndpoint, int secondEndpoint,
+ Rectangle2D bounds)
+ {
+ if( secondEndpoint - firstEndpoint <= 0 )
+ return new Rectangle2D.Float(); // Hmm?
+
+ if( firstEndpoint < 0 || secondEndpoint > getCharacterCount())
+ return new Rectangle2D.Float();
+
+ Rectangle2D r = null;
+ int ri = charIndices[ firstEndpoint ][0];
+ int gi = charIndices[ firstEndpoint ][1];
+
+ double advance = 0;
+
+ for( int i = 0; i < ri; i++ )
+ advance += runs[i].glyphVector.getLogicalBounds().getWidth();
+
+ for( int i = ri; i <= charIndices[ secondEndpoint - 1 ][0]; i++ )
+ {
+ Run run = runs[i];
+ GlyphVector gv = run.glyphVector;
+ int dg; // last index in this run to use.
+ if( i == charIndices[ secondEndpoint - 1 ][0] )
+ dg = charIndices[ secondEndpoint - 1][1];
+ else
+ dg = gv.getNumGlyphs() - 1;
+
+ for(; gi <= dg; gi++ )
+ {
+ Rectangle2D r2 = (gv.getGlyphLogicalBounds( gi )).
+ getBounds2D();
+ if( r == null )
+ r = r2;
+ else
+ r = r.createUnion(r2);
+ }
+ gi = 0; // reset glyph index into run for next run.
+
+ advance += gv.getLogicalBounds().getWidth();
+ }
+
+ return r;
+ }
+
+ public int[] getLogicalRangesForVisualSelection (TextHitInfo firstEndpoint,
+ TextHitInfo secondEndpoint)
+ {
+ // Check parameters.
+ checkHitInfo(firstEndpoint);
+ checkHitInfo(secondEndpoint);
+
+ // Convert to visual and order correctly.
+ int start = hitToCaret(firstEndpoint);
+ int end = hitToCaret(secondEndpoint);
+ if (start > end)
+ {
+ // Swap start and end so that end >= start.
+ int temp = start;
+ start = end;
+ end = temp;
+ }
+
+ // Now walk through the visual indices and mark the included pieces.
+ boolean[] include = new boolean[length];
+ for (int i = start; i < end; i++)
+ {
+ include[visualToLogical[i]] = true;
+ }
+
+ // Count included runs.
+ int numRuns = 0;
+ boolean in = false;
+ for (int i = 0; i < length; i++)
+ {
+ if (include[i] != in) // At each run in/out point we toggle the in var.
+ {
+ in = ! in;
+ if (in) // At each run start we count up.
+ numRuns++;
+ }
+ }
+
+ // Put together the ranges array.
+ int[] ranges = new int[numRuns * 2];
+ int index = 0;
+ in = false;
+ for (int i = 0; i < length; i++)
+ {
+ if (include[i] != in)
+ {
+ ranges[index] = i;
+ index++;
+ in = ! in;
+ }
+ }
+ // If the last run ends at the very end, include that last bit too.
+ if (in)
+ ranges[index] = length;
+
+ return ranges;
+ }
+
+ public TextHitInfo getNextLeftHit(int offset)
+ {
+ return getNextLeftHit(offset, DEFAULT_CARET_POLICY);
+ }
+
+ public TextHitInfo getNextLeftHit(int offset, CaretPolicy policy)
+ {
+ if (policy == null)
+ throw new IllegalArgumentException("Null policy not allowed");
+ if (offset < 0 || offset > length)
+ throw new IllegalArgumentException("Offset out of bounds");
+
+ TextHitInfo hit1 = TextHitInfo.afterOffset(offset);
+ TextHitInfo hit2 = hit1.getOtherHit();
+
+ TextHitInfo strong = policy.getStrongCaret(hit1, hit2, this);
+ TextHitInfo next = getNextLeftHit(strong);
+ TextHitInfo ret = null;
+ if (next != null)
+ {
+ TextHitInfo next2 = getVisualOtherHit(next);
+ ret = policy.getStrongCaret(next2, next, this);
+ }
+ return ret;
+ }
+
+ public TextHitInfo getNextLeftHit (TextHitInfo hit)
+ {
+ checkHitInfo(hit);
+ int index = hitToCaret(hit);
+ TextHitInfo next = null;
+ if (index != 0)
+ {
+ index--;
+ next = caretToHit(index);
+ }
+ return next;
+ }
+
+ public TextHitInfo getNextRightHit(int offset)
+ {
+ return getNextRightHit(offset, DEFAULT_CARET_POLICY);
+ }
+
+ public TextHitInfo getNextRightHit(int offset, CaretPolicy policy)
+ {
+ if (policy == null)
+ throw new IllegalArgumentException("Null policy not allowed");
+ if (offset < 0 || offset > length)
+ throw new IllegalArgumentException("Offset out of bounds");
+
+ TextHitInfo hit1 = TextHitInfo.afterOffset(offset);
+ TextHitInfo hit2 = hit1.getOtherHit();
+
+ TextHitInfo next = getNextRightHit(policy.getStrongCaret(hit1, hit2, this));
+ TextHitInfo ret = null;
+ if (next != null)
+ {
+ TextHitInfo next2 = getVisualOtherHit(next);
+ ret = policy.getStrongCaret(next2, next, this);
+ }
+ return ret;
+ }
+
+ public TextHitInfo getNextRightHit(TextHitInfo hit)
+ {
+ checkHitInfo(hit);
+ int index = hitToCaret(hit);
+ TextHitInfo next = null;
+ if (index < length)
+ {
+ index++;
+ next = caretToHit(index);
+ }
+ return next;
+ }
+
+ public Shape getOutline (AffineTransform tx)
+ {
+ float x = 0f;
+ GeneralPath gp = new GeneralPath();
+ for(int i = 0; i < runs.length; i++)
+ {
+ GlyphVector gv = runs[i].glyphVector;
+ gp.append( gv.getOutline( x, 0f ), false );
+ Rectangle2D r = gv.getLogicalBounds();
+ x += r.getWidth();
+ }
+ if( tx != null )
+ gp.transform( tx );
+ return gp;
+ }
+
+ public float getVisibleAdvance ()
+ {
+ float totalAdvance = 0f;
+
+ if( runs.length <= 0 )
+ return 0f;
+
+ // No trailing whitespace
+ if( !Character.isWhitespace( string[offset + length - 1]) )
+ return getAdvance();
+
+ // Get length of all runs up to the last
+ for(int i = 0; i < runs.length - 1; i++)
+ totalAdvance += runs[i].glyphVector.getLogicalBounds().getWidth();
+
+ int lastRun = runs[runs.length - 1].runStart;
+ int j = length - 1;
+ while( j >= lastRun && Character.isWhitespace( string[j] ) ) j--;
+
+ if( j < lastRun )
+ return totalAdvance; // entire last run is whitespace
+
+ int lastNonWSChar = j - lastRun;
+ j = 0;
+ while( runs[ runs.length - 1 ].glyphVector.getGlyphCharIndex( j )
+ <= lastNonWSChar )
+ {
+ totalAdvance += runs[ runs.length - 1 ].glyphVector
+ .getGlyphLogicalBounds( j )
+ .getBounds2D().getWidth();
+ j ++;
+ }
+
+ return totalAdvance;
+ }
+
+ public Shape getVisualHighlightShape (TextHitInfo firstEndpoint,
+ TextHitInfo secondEndpoint)
+ {
+ return getVisualHighlightShape( firstEndpoint, secondEndpoint,
+ getBounds() );
+ }
+
+ public Shape getVisualHighlightShape (TextHitInfo firstEndpoint,
+ TextHitInfo secondEndpoint,
+ Rectangle2D bounds)
+ {
+ GeneralPath path = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
+ Shape caret1 = getCaretShape(firstEndpoint, bounds);
+ path.append(caret1, false);
+ Shape caret2 = getCaretShape(secondEndpoint, bounds);
+ path.append(caret2, false);
+ // Append left (top) bounds to selection if necessary.
+ int c1 = hitToCaret(firstEndpoint);
+ int c2 = hitToCaret(secondEndpoint);
+ if (c1 == 0 || c2 == 0)
+ {
+ path.append(left(bounds), false);
+ }
+ // Append right (bottom) bounds if necessary.
+ if (c1 == length || c2 == length)
+ {
+ path.append(right(bounds), false);
+ }
+ return path.getBounds2D();
+ }
+
+ /**
+ * Returns the shape that makes up the left (top) edge of this text layout.
+ *
+ * @param b the bounds
+ *
+ * @return the shape that makes up the left (top) edge of this text layout
+ */
+ private Shape left(Rectangle2D b)
+ {
+ GeneralPath left = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
+ left.append(getCaretShape(TextHitInfo.beforeOffset(0)), false);
+ if (isVertical())
+ {
+ float y = (float) b.getMinY();
+ left.append(new Line2D.Float((float) b.getMinX(), y,
+ (float) b.getMaxX(), y), false);
+ }
+ else
+ {
+ float x = (float) b.getMinX();
+ left.append(new Line2D.Float(x, (float) b.getMinY(),
+ x, (float) b.getMaxY()), false);
+ }
+ return left.getBounds2D();
+ }
+
+ /**
+ * Returns the shape that makes up the right (bottom) edge of this text
+ * layout.
+ *
+ * @param b the bounds
+ *
+ * @return the shape that makes up the right (bottom) edge of this text
+ * layout
+ */
+ private Shape right(Rectangle2D b)
+ {
+ GeneralPath right = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
+ right.append(getCaretShape(TextHitInfo.afterOffset(length)), false);
+ if (isVertical())
+ {
+ float y = (float) b.getMaxY();
+ right.append(new Line2D.Float((float) b.getMinX(), y,
+ (float) b.getMaxX(), y), false);
+ }
+ else
+ {
+ float x = (float) b.getMaxX();
+ right.append(new Line2D.Float(x, (float) b.getMinY(),
+ x, (float) b.getMaxY()), false);
+ }
+ return right.getBounds2D();
+ }
+
+ public TextHitInfo getVisualOtherHit (TextHitInfo hit)
+ {
+ checkHitInfo(hit);
+ int hitIndex = hit.getCharIndex();
+
+ int index;
+ boolean leading;
+ if (hitIndex == -1 || hitIndex == length)
+ {
+ // Boundary case.
+ int visual;
+ if (isLeftToRight() == (hitIndex == -1))
+ visual = 0;
+ else
+ visual = length - 1;
+ index = visualToLogical[visual];
+ if (isLeftToRight() == (hitIndex == -1))
+ leading = isCharacterLTR(index); // LTR.
+ else
+ leading = ! isCharacterLTR(index); // RTL.
+ }
+ else
+ {
+ // Normal case.
+ int visual = logicalToVisual[hitIndex];
+ boolean b;
+ if (isCharacterLTR(hitIndex) == hit.isLeadingEdge())
+ {
+ visual--;
+ b = false;
+ }
+ else
+ {
+ visual++;
+ b = true;
+ }
+ if (visual >= 0 && visual < length)
+ {
+ index = visualToLogical[visual];
+ leading = b == isLeftToRight();
+ }
+ else
+ {
+ index = b == isLeftToRight() ? length : -1;
+ leading = index == length;
+ }
+ }
+ return leading ? TextHitInfo.leading(index) : TextHitInfo.trailing(index);
+ }
+
+ /**
+ * This is a protected method of a <code>final</code> class, meaning
+ * it exists only to taunt you.
+ */
+ protected void handleJustify (float justificationWidth)
+ {
+ // We assume that the text has non-trailing whitespace.
+ // First get the change in width to insert into the whitespaces.
+ double deltaW = justificationWidth - getVisibleAdvance();
+ int nglyphs = 0; // # of whitespace chars
+
+ // determine last non-whitespace char.
+ int lastNWS = offset + length - 1;
+ while( Character.isWhitespace( string[lastNWS] ) ) lastNWS--;
+
+ // locations of the glyphs.
+ int[] wsglyphs = new int[length * 10];
+ for(int run = 0; run < runs.length; run++ )
+ {
+ Run current = runs[run];
+ for(int i = 0; i < current.glyphVector.getNumGlyphs(); i++ )
+ {
+ int cindex = current.runStart
+ + current.glyphVector.getGlyphCharIndex( i );
+ if( Character.isWhitespace( string[cindex] ) )
+ // && cindex < lastNWS )
+ {
+ wsglyphs[ nglyphs * 2 ] = run;
+ wsglyphs[ nglyphs * 2 + 1] = i;
+ nglyphs++;
+ }
+ }
+ }
+ deltaW = deltaW / nglyphs; // Change in width per whitespace glyph
+ double w = 0;
+ int cws = 0;
+ // Shift all characters
+ for(int run = 0; run < runs.length; run++ )
+ {
+ Run current = runs[run];
+ for(int i = 0; i < current.glyphVector.getNumGlyphs(); i++ )
+ {
+ if( wsglyphs[ cws * 2 ] == run && wsglyphs[ cws * 2 + 1 ] == i )
+ {
+ cws++; // update 'current whitespace'
+ w += deltaW; // increment the shift
+ }
+ Point2D p = current.glyphVector.getGlyphPosition( i );
+ p.setLocation( p.getX() + w, p.getY() );
+ current.glyphVector.setGlyphPosition( i, p );
+ }
+ }
+ }
+
+ public TextHitInfo hitTestChar (float x, float y)
+ {
+ return hitTestChar(x, y, getNaturalBounds());
+ }
+
+ /**
+ * Finds the character hit at the specified point. This 'clips' this
+ * text layout against the specified <code>bounds</code> rectangle. That
+ * means that in the case where a point is outside these bounds, this method
+ * returns the leading edge of the first character or the trailing edge of
+ * the last character.
+ *
+ * @param x the X location to test
+ * @param y the Y location to test
+ * @param bounds the bounds to test against
+ *
+ * @return the character hit at the specified point
+ */
+ public TextHitInfo hitTestChar (float x, float y, Rectangle2D bounds)
+ {
+ // Check bounds.
+ if (isVertical())
+ {
+ if (y < bounds.getMinY())
+ return TextHitInfo.leading(0);
+ else if (y > bounds.getMaxY())
+ return TextHitInfo.trailing(getCharacterCount() - 1);
+ }
+ else
+ {
+ if (x < bounds.getMinX())
+ return TextHitInfo.leading(0);
+ else if (x > bounds.getMaxX())
+ return TextHitInfo.trailing(getCharacterCount() - 1);
+ }
+
+ TextHitInfo hitInfo = null;
+ if (isVertical())
+ {
+ // Search for the run at the location.
+ // TODO: Perform binary search for maximum efficiency. However, we
+ // need the run location laid out statically to do that.
+ int numRuns = runs.length;
+ Run hitRun = null;
+ for (int i = 0; i < numRuns && hitRun == null; i++)
+ {
+ Run run = runs[i];
+ Rectangle2D lBounds = run.glyphVector.getLogicalBounds();
+ if (lBounds.getMinY() + run.location <= y
+ && lBounds.getMaxY() + run.location >= y)
+ hitRun = run;
+ }
+ // Now we have (hopefully) found a run that hits. Now find the
+ // right character.
+ if (hitRun != null)
+ {
+ GlyphVector gv = hitRun.glyphVector;
+ for (int i = hitRun.runStart;
+ i < hitRun.runEnd && hitInfo == null; i++)
+ {
+ int gi = i - hitRun.runStart;
+ Rectangle2D lBounds = gv.getGlyphLogicalBounds(gi)
+ .getBounds2D();
+ if (lBounds.getMinY() + hitRun.location <= y
+ && lBounds.getMaxY() + hitRun.location >= y)
+ {
+ // Found hit. Now check if we are leading or trailing.
+ boolean leading = true;
+ if (lBounds.getCenterY() + hitRun.location <= y)
+ leading = false;
+ hitInfo = leading ? TextHitInfo.leading(i)
+ : TextHitInfo.trailing(i);
+ }
+ }
+ }
+ }
+ else
+ {
+ // Search for the run at the location.
+ // TODO: Perform binary search for maximum efficiency. However, we
+ // need the run location laid out statically to do that.
+ int numRuns = runs.length;
+ Run hitRun = null;
+ for (int i = 0; i < numRuns && hitRun == null; i++)
+ {
+ Run run = runs[i];
+ Rectangle2D lBounds = run.glyphVector.getLogicalBounds();
+ if (lBounds.getMinX() + run.location <= x
+ && lBounds.getMaxX() + run.location >= x)
+ hitRun = run;
+ }
+ // Now we have (hopefully) found a run that hits. Now find the
+ // right character.
+ if (hitRun != null)
+ {
+ GlyphVector gv = hitRun.glyphVector;
+ for (int i = hitRun.runStart;
+ i < hitRun.runEnd && hitInfo == null; i++)
+ {
+ int gi = i - hitRun.runStart;
+ Rectangle2D lBounds = gv.getGlyphLogicalBounds(gi)
+ .getBounds2D();
+ if (lBounds.getMinX() + hitRun.location <= x
+ && lBounds.getMaxX() + hitRun.location >= x)
+ {
+ // Found hit. Now check if we are leading or trailing.
+ boolean leading = true;
+ if (lBounds.getCenterX() + hitRun.location <= x)
+ leading = false;
+ hitInfo = leading ? TextHitInfo.leading(i)
+ : TextHitInfo.trailing(i);
+ }
+ }
+ }
+ }
+ return hitInfo;
+ }
+
+ public boolean isLeftToRight ()
+ {
+ return leftToRight;
+ }
+
+ public boolean isVertical ()
+ {
+ return false; // FIXME: How do you create a vertical layout?
+ }
+
+ public int hashCode ()
+ {
+ // This is implemented in sync to equals().
+ if (hash == 0 && runs.length > 0)
+ {
+ hash = runs.length;
+ for (int i = 0; i < runs.length; i++)
+ hash ^= runs[i].glyphVector.hashCode();
+ }
+ return hash;
+ }
+
+ public String toString ()
+ {
+ return "TextLayout [string:"+ new String(string, offset, length)
+ +" Rendercontext:"+
+ frc+"]";
+ }
+
+ /**
+ * Returns the natural bounds of that text layout. This is made up
+ * of the ascent plus descent and the text advance.
+ *
+ * @return the natural bounds of that text layout
+ */
+ private Rectangle2D getNaturalBounds()
+ {
+ if (naturalBounds == null)
+ naturalBounds = new Rectangle2D.Float(0.0F, -getAscent(), getAdvance(),
+ getAscent() + getDescent());
+ return naturalBounds;
+ }
+
+ private void checkHitInfo(TextHitInfo hit)
+ {
+ if (hit == null)
+ throw new IllegalArgumentException("Null hit info not allowed");
+ int index = hit.getInsertionIndex();
+ if (index < 0 || index > length)
+ throw new IllegalArgumentException("Hit index out of range");
+ }
+
+ private int hitToCaret(TextHitInfo hit)
+ {
+ int index = hit.getCharIndex();
+ int ret;
+ if (index < 0)
+ ret = isLeftToRight() ? 0 : length;
+ else if (index >= length)
+ ret = isLeftToRight() ? length : 0;
+ else
+ {
+ ret = logicalToVisual[index];
+ if (hit.isLeadingEdge() != isCharacterLTR(index))
+ ret++;
+ }
+ return ret;
+ }
+
+ private TextHitInfo caretToHit(int index)
+ {
+ TextHitInfo hit;
+ if (index == 0 || index == length)
+ {
+ if ((index == length) == isLeftToRight())
+ hit = TextHitInfo.leading(length);
+ else
+ hit = TextHitInfo.trailing(-1);
+ }
+ else
+ {
+ int logical = visualToLogical[index];
+ boolean leading = isCharacterLTR(logical); // LTR.
+ hit = leading ? TextHitInfo.leading(logical)
+ : TextHitInfo.trailing(logical);
+ }
+ return hit;
+ }
+
+ private boolean isCharacterLTR(int index)
+ {
+ byte level = getCharacterLevel(index);
+ return (level & 1) == 0;
+ }
+
+ /**
+ * Finds the run that holds the specified (logical) character index. This
+ * returns <code>null</code> when the index is not inside the range.
+ *
+ * @param index the index of the character to find
+ *
+ * @return the run that holds the specified character
+ */
+ private Run findRunAtIndex(int index)
+ {
+ Run found = null;
+ // TODO: Can we do better than linear searching here?
+ for (int i = 0; i < runs.length && found == null; i++)
+ {
+ Run run = runs[i];
+ if (run.runStart <= index && run.runEnd > index)
+ found = run;
+ }
+ return found;
+ }
+
+ /**
+ * Computes the layout locations for each run.
+ */
+ private void layoutRuns()
+ {
+ float loc = 0.0F;
+ float lastWidth = 0.0F;
+ for (int i = 0; i < runs.length; i++)
+ {
+ runs[i].location = loc;
+ Rectangle2D bounds = runs[i].glyphVector.getLogicalBounds();
+ loc += isVertical() ? bounds.getHeight() : bounds.getWidth();
+ }
+ }
+
+ /**
+ * Inner class describing a caret policy
+ */
+ public static class CaretPolicy
+ {
+ public CaretPolicy()
+ {
+ }
+
+ public TextHitInfo getStrongCaret(TextHitInfo hit1,
+ TextHitInfo hit2,
+ TextLayout layout)
+ {
+ byte l1 = layout.getCharacterLevel(hit1.getCharIndex());
+ byte l2 = layout.getCharacterLevel(hit2.getCharIndex());
+ TextHitInfo strong;
+ if (l1 == l2)
+ {
+ if (hit2.isLeadingEdge() && ! hit1.isLeadingEdge())
+ strong = hit2;
+ else
+ strong = hit1;
+ }
+ else
+ {
+ if (l1 < l2)
+ strong = hit1;
+ else
+ strong = hit2;
+ }
+ return strong;
+ }
+ }
+}
diff --git a/libjava/classpath/java/awt/font/TextMeasurer.java b/libjava/classpath/java/awt/font/TextMeasurer.java
new file mode 100644
index 000000000..e443e8bc7
--- /dev/null
+++ b/libjava/classpath/java/awt/font/TextMeasurer.java
@@ -0,0 +1,190 @@
+/* TextMeasurer.java
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+import java.text.AttributedCharacterIterator;
+import java.awt.Shape;
+
+/**
+ * TextMeasurer is a small utility class for measuring the length of laid-out
+ * text objects.
+ *
+ * @author Sven de Marothy
+ * @since 1.3
+ */
+public final class TextMeasurer implements Cloneable
+{
+ private AttributedCharacterIterator text;
+ private FontRenderContext frc;
+ private TextLayout totalLayout;
+ private int numChars;
+
+ /**
+ * Creates a TextMeasurer from a given text in the form of an
+ * <code>AttributedCharacterIterator</code> and a
+ * <code>FontRenderContext</code>.
+ */
+ public TextMeasurer (AttributedCharacterIterator text, FontRenderContext frc)
+ {
+ this.text = text;
+ this.frc = frc;
+ totalLayout = new TextLayout( text, frc );
+ numChars = totalLayout.getCharacterCount();
+ }
+
+ /**
+ * Clones the TextMeasurer object
+ */
+ protected Object clone ()
+ {
+ return new TextMeasurer( text, frc );
+ }
+
+ /**
+ * Update the text if a character is deleted at the position deletePos
+ * @param newParagraph - the updated paragraph.
+ * @param deletePos - the deletion position
+ */
+ public void deleteChar (AttributedCharacterIterator newParagraph,
+ int deletePos)
+ {
+ totalLayout = new TextLayout(newParagraph, frc);
+ if( deletePos < 0 || deletePos > totalLayout.getCharacterCount() )
+ throw new NullPointerException("Invalid deletePos:"+deletePos);
+ numChars = totalLayout.getCharacterCount();
+ text = newParagraph;
+ }
+
+ /**
+ * Update the text if a character is inserted at the position insertPos
+ * @param newParagraph - the updated paragraph.
+ * @param insertPos - the insertion position
+ */
+ public void insertChar (AttributedCharacterIterator newParagraph,
+ int insertPos)
+ {
+ totalLayout = new TextLayout(newParagraph, frc);
+ if( insertPos < 0 || insertPos > totalLayout.getCharacterCount() )
+ throw new NullPointerException("Invalid insertPos:"+insertPos);
+ numChars = totalLayout.getCharacterCount();
+ text = newParagraph;
+ }
+
+ /***
+ * Returns the total advance between two positions in the paragraph.
+ * Characters from start to limit-1 (inclusive) are included in this count.
+ *
+ * @param start - the starting character index.
+ * @param limit - the limiting index.
+ */
+ public float getAdvanceBetween (int start, int limit)
+ {
+ Shape s = totalLayout.getLogicalHighlightShape( start, limit );
+ return (float)s.getBounds2D().getWidth();
+ }
+
+ /**
+ * Returns a <code>TextLayout</code> object corresponding to the characters
+ * from text to limit.
+ * @param start - the starting character index.
+ * @param limit - the limiting index.
+ */
+ public TextLayout getLayout (int start, int limit)
+ {
+ if( start >= limit )
+ throw new IllegalArgumentException("Start position must be < limit.");
+ return new TextLayout( totalLayout, start, limit );
+ }
+
+ /**
+ * Returns the line-break index from a given starting index and a maximum
+ * advance. The index returned is the first character outside the given
+ * advance (or the limit of the string, if all remaining characters fit.)
+ *
+ * @param start - the starting index.
+ * @param maxAdvance - the maximum advance allowed.
+ * @return the index of the first character beyond maxAdvance, or the
+ * index of the last character + 1.
+ */
+ public int getLineBreakIndex (int start, float maxAdvance)
+ {
+ if( start < 0 )
+ throw new IllegalArgumentException("Start parameter must be > 0.");
+
+ double remainingLength = getAdvanceBetween( start, numChars );
+
+ int guessOffset = (int)( ( (double)maxAdvance / (double)remainingLength)
+ * ( (double)numChars - (double)start ) );
+ guessOffset += start;
+ if( guessOffset > numChars )
+ guessOffset = numChars;
+
+ double guessLength = getAdvanceBetween( start, guessOffset );
+ boolean makeSmaller = ( guessLength > maxAdvance );
+ int inc = makeSmaller ? -1 : 1;
+ boolean keepGoing = true;
+
+ do
+ {
+ guessOffset = guessOffset + inc;
+ if( guessOffset <= start || guessOffset > numChars )
+ {
+ keepGoing = false;
+ }
+ else
+ {
+ guessLength = getAdvanceBetween( start, guessOffset );
+ if( makeSmaller && ( guessLength <= maxAdvance) )
+ keepGoing = false;
+ if( !makeSmaller && ( guessLength >= maxAdvance) )
+ keepGoing = false;
+ }
+ }
+ while( keepGoing );
+
+ // Return first index that doesn't fit.
+ if( !makeSmaller )
+ guessOffset--;
+
+ if( guessOffset > numChars )
+ return numChars;
+
+ return guessOffset;
+ }
+}
diff --git a/libjava/classpath/java/awt/font/TransformAttribute.java b/libjava/classpath/java/awt/font/TransformAttribute.java
new file mode 100644
index 000000000..56d15bb0b
--- /dev/null
+++ b/libjava/classpath/java/awt/font/TransformAttribute.java
@@ -0,0 +1,100 @@
+/* TransformAttribute.java --
+ Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.font;
+
+import java.awt.geom.AffineTransform;
+import java.io.Serializable;
+
+/**
+ * This class provides a mechanism for using an {@link AffineTransform} as
+ * an <i>immutable</i> attribute (for example, in the
+ * {@link java.text.AttributedString} class). Any transform passed to
+ * this class is copied before being stored, and any transform handed out
+ * by this class is a copy of the stored transform. In this way, it is
+ * not possible to modify the stored transform.
+ *
+ * @author Michael Koch
+ */
+public final class TransformAttribute implements Serializable
+{
+ private static final long serialVersionUID = 3356247357827709530L;
+
+ private AffineTransform affineTransform;
+
+ /**
+ * Creates a new attribute that contains a copy of the given transform.
+ *
+ * @param transform the transform (<code>null</code> not permitted).
+ *
+ * @throws IllegalArgumentException if <code>transform</code> is
+ * <code>null</code>.
+ */
+ public TransformAttribute (AffineTransform transform)
+ {
+ if (transform == null)
+ {
+ throw new IllegalArgumentException("Null 'transform' not permitted.");
+ }
+ this.affineTransform = new AffineTransform (transform);
+ }
+
+ /**
+ * Returns a copy of the transform contained by this attribute.
+ *
+ * @return A copy of the transform.
+ */
+ public AffineTransform getTransform ()
+ {
+ return (AffineTransform) affineTransform.clone();
+ }
+
+ /**
+ * Returns <code>true</code> if the transform contained by this attribute is
+ * an identity transform, and <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if the transform contained by this attribute is
+ * an identity transform, and <code>false</code> otherwise.
+ *
+ * @since 1.4
+ */
+ public boolean isIdentity ()
+ {
+ return (affineTransform == null ? false : affineTransform.isIdentity ());
+ }
+}
diff --git a/libjava/classpath/java/awt/font/package.html b/libjava/classpath/java/awt/font/package.html
new file mode 100644
index 000000000..8c3c61a40
--- /dev/null
+++ b/libjava/classpath/java/awt/font/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt.font package.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - java.awt.font</title></head>
+
+<body>
+<p>Representations of different kind of characters and fonts.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/geom/AffineTransform.java b/libjava/classpath/java/awt/geom/AffineTransform.java
new file mode 100644
index 000000000..42590efce
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/AffineTransform.java
@@ -0,0 +1,1489 @@
+/* AffineTransform.java -- transform coordinates between two 2-D spaces
+ Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.geom;
+
+import java.awt.Shape;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+
+/**
+ * This class represents an affine transformation between two coordinate
+ * spaces in 2 dimensions. Such a transform preserves the "straightness"
+ * and "parallelness" of lines. The transform is built from a sequence of
+ * translations, scales, flips, rotations, and shears.
+ *
+ * <p>The transformation can be represented using matrix math on a 3x3 array.
+ * Given (x,y), the transformation (x',y') can be found by:
+ * <pre>
+ * [ x'] [ m00 m01 m02 ] [ x ] [ m00*x + m01*y + m02 ]
+ * [ y'] = [ m10 m11 m12 ] [ y ] = [ m10*x + m11*y + m12 ]
+ * [ 1 ] [ 0 0 1 ] [ 1 ] [ 1 ]
+ * </pre>
+ * The bottom row of the matrix is constant, so a transform can be uniquely
+ * represented (as in {@link #toString()}) by
+ * "[[m00, m01, m02], [m10, m11, m12]]".
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status partially updated to 1.4, still has some problems
+ */
+public class AffineTransform implements Cloneable, Serializable
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 1330973210523860834L;
+
+ /**
+ * The transformation is the identity (x' = x, y' = y). All other transforms
+ * have either a combination of the appropriate transform flag bits for
+ * their type, or the type GENERAL_TRANSFORM.
+ *
+ * @see #TYPE_TRANSLATION
+ * @see #TYPE_UNIFORM_SCALE
+ * @see #TYPE_GENERAL_SCALE
+ * @see #TYPE_FLIP
+ * @see #TYPE_QUADRANT_ROTATION
+ * @see #TYPE_GENERAL_ROTATION
+ * @see #TYPE_GENERAL_TRANSFORM
+ * @see #getType()
+ */
+ public static final int TYPE_IDENTITY = 0;
+
+ /**
+ * The transformation includes a translation - shifting in the x or y
+ * direction without changing length or angles.
+ *
+ * @see #TYPE_IDENTITY
+ * @see #TYPE_UNIFORM_SCALE
+ * @see #TYPE_GENERAL_SCALE
+ * @see #TYPE_FLIP
+ * @see #TYPE_QUADRANT_ROTATION
+ * @see #TYPE_GENERAL_ROTATION
+ * @see #TYPE_GENERAL_TRANSFORM
+ * @see #getType()
+ */
+ public static final int TYPE_TRANSLATION = 1;
+
+ /**
+ * The transformation includes a uniform scale - length is scaled in both
+ * the x and y directions by the same amount, without affecting angles.
+ * This is mutually exclusive with TYPE_GENERAL_SCALE.
+ *
+ * @see #TYPE_IDENTITY
+ * @see #TYPE_TRANSLATION
+ * @see #TYPE_GENERAL_SCALE
+ * @see #TYPE_FLIP
+ * @see #TYPE_QUADRANT_ROTATION
+ * @see #TYPE_GENERAL_ROTATION
+ * @see #TYPE_GENERAL_TRANSFORM
+ * @see #TYPE_MASK_SCALE
+ * @see #getType()
+ */
+ public static final int TYPE_UNIFORM_SCALE = 2;
+
+ /**
+ * The transformation includes a general scale - length is scaled in either
+ * or both the x and y directions, but by different amounts; without
+ * affecting angles. This is mutually exclusive with TYPE_UNIFORM_SCALE.
+ *
+ * @see #TYPE_IDENTITY
+ * @see #TYPE_TRANSLATION
+ * @see #TYPE_UNIFORM_SCALE
+ * @see #TYPE_FLIP
+ * @see #TYPE_QUADRANT_ROTATION
+ * @see #TYPE_GENERAL_ROTATION
+ * @see #TYPE_GENERAL_TRANSFORM
+ * @see #TYPE_MASK_SCALE
+ * @see #getType()
+ */
+ public static final int TYPE_GENERAL_SCALE = 4;
+
+ /**
+ * This constant checks if either variety of scale transform is performed.
+ *
+ * @see #TYPE_UNIFORM_SCALE
+ * @see #TYPE_GENERAL_SCALE
+ */
+ public static final int TYPE_MASK_SCALE = 6;
+
+ /**
+ * The transformation includes a flip about an axis, swapping between
+ * right-handed and left-handed coordinate systems. In a right-handed
+ * system, the positive x-axis rotates counter-clockwise to the positive
+ * y-axis; in a left-handed system it rotates clockwise.
+ *
+ * @see #TYPE_IDENTITY
+ * @see #TYPE_TRANSLATION
+ * @see #TYPE_UNIFORM_SCALE
+ * @see #TYPE_GENERAL_SCALE
+ * @see #TYPE_QUADRANT_ROTATION
+ * @see #TYPE_GENERAL_ROTATION
+ * @see #TYPE_GENERAL_TRANSFORM
+ * @see #getType()
+ */
+ public static final int TYPE_FLIP = 64;
+
+ /**
+ * The transformation includes a rotation of a multiple of 90 degrees (PI/2
+ * radians). Angles are rotated, but length is preserved. This is mutually
+ * exclusive with TYPE_GENERAL_ROTATION.
+ *
+ * @see #TYPE_IDENTITY
+ * @see #TYPE_TRANSLATION
+ * @see #TYPE_UNIFORM_SCALE
+ * @see #TYPE_GENERAL_SCALE
+ * @see #TYPE_FLIP
+ * @see #TYPE_GENERAL_ROTATION
+ * @see #TYPE_GENERAL_TRANSFORM
+ * @see #TYPE_MASK_ROTATION
+ * @see #getType()
+ */
+ public static final int TYPE_QUADRANT_ROTATION = 8;
+
+ /**
+ * The transformation includes a rotation by an arbitrary angle. Angles are
+ * rotated, but length is preserved. This is mutually exclusive with
+ * TYPE_QUADRANT_ROTATION.
+ *
+ * @see #TYPE_IDENTITY
+ * @see #TYPE_TRANSLATION
+ * @see #TYPE_UNIFORM_SCALE
+ * @see #TYPE_GENERAL_SCALE
+ * @see #TYPE_FLIP
+ * @see #TYPE_QUADRANT_ROTATION
+ * @see #TYPE_GENERAL_TRANSFORM
+ * @see #TYPE_MASK_ROTATION
+ * @see #getType()
+ */
+ public static final int TYPE_GENERAL_ROTATION = 16;
+
+ /**
+ * This constant checks if either variety of rotation is performed.
+ *
+ * @see #TYPE_QUADRANT_ROTATION
+ * @see #TYPE_GENERAL_ROTATION
+ */
+ public static final int TYPE_MASK_ROTATION = 24;
+
+ /**
+ * The transformation is an arbitrary conversion of coordinates which
+ * could not be decomposed into the other TYPEs.
+ *
+ * @see #TYPE_IDENTITY
+ * @see #TYPE_TRANSLATION
+ * @see #TYPE_UNIFORM_SCALE
+ * @see #TYPE_GENERAL_SCALE
+ * @see #TYPE_FLIP
+ * @see #TYPE_QUADRANT_ROTATION
+ * @see #TYPE_GENERAL_ROTATION
+ * @see #getType()
+ */
+ public static final int TYPE_GENERAL_TRANSFORM = 32;
+
+ /**
+ * The X coordinate scaling element of the transform matrix.
+ *
+ * @serial matrix[0,0]
+ */
+ private double m00;
+
+ /**
+ * The Y coordinate shearing element of the transform matrix.
+ *
+ * @serial matrix[1,0]
+ */
+ private double m10;
+
+ /**
+ * The X coordinate shearing element of the transform matrix.
+ *
+ * @serial matrix[0,1]
+ */
+ private double m01;
+
+ /**
+ * The Y coordinate scaling element of the transform matrix.
+ *
+ * @serial matrix[1,1]
+ */
+ private double m11;
+
+ /**
+ * The X coordinate translation element of the transform matrix.
+ *
+ * @serial matrix[0,2]
+ */
+ private double m02;
+
+ /**
+ * The Y coordinate translation element of the transform matrix.
+ *
+ * @serial matrix[1,2]
+ */
+ private double m12;
+
+ /** The type of this transform. */
+ private transient int type;
+
+ /**
+ * Construct a new identity transform:
+ * <pre>
+ * [ 1 0 0 ]
+ * [ 0 1 0 ]
+ * [ 0 0 1 ]
+ * </pre>
+ */
+ public AffineTransform()
+ {
+ m00 = m11 = 1;
+ }
+
+ /**
+ * Create a new transform which copies the given one.
+ *
+ * @param tx the transform to copy
+ * @throws NullPointerException if tx is null
+ */
+ public AffineTransform(AffineTransform tx)
+ {
+ setTransform(tx);
+ }
+
+ /**
+ * Construct a transform with the given matrix entries:
+ * <pre>
+ * [ m00 m01 m02 ]
+ * [ m10 m11 m12 ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param m00 the x scaling component
+ * @param m10 the y shearing component
+ * @param m01 the x shearing component
+ * @param m11 the y scaling component
+ * @param m02 the x translation component
+ * @param m12 the y translation component
+ */
+ public AffineTransform(float m00, float m10,
+ float m01, float m11,
+ float m02, float m12)
+ {
+ this.m00 = m00;
+ this.m10 = m10;
+ this.m01 = m01;
+ this.m11 = m11;
+ this.m02 = m02;
+ this.m12 = m12;
+ updateType();
+ }
+
+ /**
+ * Construct a transform from a sequence of float entries. The array must
+ * have at least 4 entries, which has a translation factor of 0; or 6
+ * entries, for specifying all parameters:
+ * <pre>
+ * [ f[0] f[2] (f[4]) ]
+ * [ f[1] f[3] (f[5]) ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param f the matrix to copy from, with at least 4 (6) entries
+ * @throws NullPointerException if f is null
+ * @throws ArrayIndexOutOfBoundsException if f is too small
+ */
+ public AffineTransform(float[] f)
+ {
+ m00 = f[0];
+ m10 = f[1];
+ m01 = f[2];
+ m11 = f[3];
+ if (f.length >= 6)
+ {
+ m02 = f[4];
+ m12 = f[5];
+ }
+ updateType();
+ }
+
+ /**
+ * Construct a transform with the given matrix entries:
+ * <pre>
+ * [ m00 m01 m02 ]
+ * [ m10 m11 m12 ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param m00 the x scaling component
+ * @param m10 the y shearing component
+ * @param m01 the x shearing component
+ * @param m11 the y scaling component
+ * @param m02 the x translation component
+ * @param m12 the y translation component
+ */
+ public AffineTransform(double m00, double m10, double m01,
+ double m11, double m02, double m12)
+ {
+ this.m00 = m00;
+ this.m10 = m10;
+ this.m01 = m01;
+ this.m11 = m11;
+ this.m02 = m02;
+ this.m12 = m12;
+ updateType();
+ }
+
+ /**
+ * Construct a transform from a sequence of double entries. The array must
+ * have at least 4 entries, which has a translation factor of 0; or 6
+ * entries, for specifying all parameters:
+ * <pre>
+ * [ d[0] d[2] (d[4]) ]
+ * [ d[1] d[3] (d[5]) ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param d the matrix to copy from, with at least 4 (6) entries
+ * @throws NullPointerException if d is null
+ * @throws ArrayIndexOutOfBoundsException if d is too small
+ */
+ public AffineTransform(double[] d)
+ {
+ m00 = d[0];
+ m10 = d[1];
+ m01 = d[2];
+ m11 = d[3];
+ if (d.length >= 6)
+ {
+ m02 = d[4];
+ m12 = d[5];
+ }
+ updateType();
+ }
+
+ /**
+ * Returns a translation transform:
+ * <pre>
+ * [ 1 0 tx ]
+ * [ 0 1 ty ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param tx the x translation distance
+ * @param ty the y translation distance
+ * @return the translating transform
+ */
+ public static AffineTransform getTranslateInstance(double tx, double ty)
+ {
+ AffineTransform t = new AffineTransform();
+ t.m02 = tx;
+ t.m12 = ty;
+ t.type = (tx == 0 && ty == 0) ? TYPE_UNIFORM_SCALE : TYPE_TRANSLATION;
+ return t;
+ }
+
+ /**
+ * Returns a rotation transform. A positive angle (in radians) rotates
+ * the positive x-axis to the positive y-axis:
+ * <pre>
+ * [ cos(theta) -sin(theta) 0 ]
+ * [ sin(theta) cos(theta) 0 ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param theta the rotation angle
+ * @return the rotating transform
+ */
+ public static AffineTransform getRotateInstance(double theta)
+ {
+ AffineTransform t = new AffineTransform();
+ t.setToRotation(theta);
+ return t;
+ }
+
+ /**
+ * Returns a rotation transform about a point. A positive angle (in radians)
+ * rotates the positive x-axis to the positive y-axis. This is the same
+ * as calling:
+ * <pre>
+ * AffineTransform tx = new AffineTransform();
+ * tx.setToTranslation(x, y);
+ * tx.rotate(theta);
+ * tx.translate(-x, -y);
+ * </pre>
+ *
+ * <p>The resulting matrix is:
+ * <pre>
+ * [ cos(theta) -sin(theta) x-x*cos+y*sin ]
+ * [ sin(theta) cos(theta) y-x*sin-y*cos ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param theta the rotation angle
+ * @param x the x coordinate of the pivot point
+ * @param y the y coordinate of the pivot point
+ * @return the rotating transform
+ */
+ public static AffineTransform getRotateInstance(double theta,
+ double x, double y)
+ {
+ AffineTransform t = new AffineTransform();
+ t.setToTranslation(x, y);
+ t.rotate(theta);
+ t.translate(-x, -y);
+ return t;
+ }
+
+ /**
+ * Returns a scaling transform:
+ * <pre>
+ * [ sx 0 0 ]
+ * [ 0 sy 0 ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param sx the x scaling factor
+ * @param sy the y scaling factor
+ * @return the scaling transform
+ */
+ public static AffineTransform getScaleInstance(double sx, double sy)
+ {
+ AffineTransform t = new AffineTransform();
+ t.setToScale(sx, sy);
+ return t;
+ }
+
+ /**
+ * Returns a shearing transform (points are shifted in the x direction based
+ * on a factor of their y coordinate, and in the y direction as a factor of
+ * their x coordinate):
+ * <pre>
+ * [ 1 shx 0 ]
+ * [ shy 1 0 ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param shx the x shearing factor
+ * @param shy the y shearing factor
+ * @return the shearing transform
+ */
+ public static AffineTransform getShearInstance(double shx, double shy)
+ {
+ AffineTransform t = new AffineTransform();
+ t.setToShear(shx, shy);
+ return t;
+ }
+
+ /**
+ * Returns the type of this transform. The result is always valid, although
+ * it may not be the simplest interpretation (in other words, there are
+ * sequences of transforms which reduce to something simpler, which this
+ * does not always detect). The result is either TYPE_GENERAL_TRANSFORM,
+ * or a bit-wise combination of TYPE_TRANSLATION, the mutually exclusive
+ * TYPE_*_ROTATIONs, and the mutually exclusive TYPE_*_SCALEs.
+ *
+ * @return The type.
+ *
+ * @see #TYPE_IDENTITY
+ * @see #TYPE_TRANSLATION
+ * @see #TYPE_UNIFORM_SCALE
+ * @see #TYPE_GENERAL_SCALE
+ * @see #TYPE_QUADRANT_ROTATION
+ * @see #TYPE_GENERAL_ROTATION
+ * @see #TYPE_GENERAL_TRANSFORM
+ */
+ public int getType()
+ {
+ return type;
+ }
+
+ /**
+ * Return the determinant of this transform matrix. If the determinant is
+ * non-zero, the transform is invertible; otherwise operations which require
+ * an inverse throw a NoninvertibleTransformException. A result very near
+ * zero, due to rounding errors, may indicate that inversion results do not
+ * carry enough precision to be meaningful.
+ *
+ * <p>If this is a uniform scale transformation, the determinant also
+ * represents the squared value of the scale. Otherwise, it carries little
+ * additional meaning. The determinant is calculated as:
+ * <pre>
+ * | m00 m01 m02 |
+ * | m10 m11 m12 | = m00 * m11 - m01 * m10
+ * | 0 0 1 |
+ * </pre>
+ *
+ * @return the determinant
+ * @see #createInverse()
+ */
+ public double getDeterminant()
+ {
+ return m00 * m11 - m01 * m10;
+ }
+
+ /**
+ * Return the matrix of values used in this transform. If the matrix has
+ * fewer than 6 entries, only the scale and shear factors are returned;
+ * otherwise the translation factors are copied as well. The resulting
+ * values are:
+ * <pre>
+ * [ d[0] d[2] (d[4]) ]
+ * [ d[1] d[3] (d[5]) ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param d the matrix to store the results into; with 4 (6) entries
+ * @throws NullPointerException if d is null
+ * @throws ArrayIndexOutOfBoundsException if d is too small
+ */
+ public void getMatrix(double[] d)
+ {
+ d[0] = m00;
+ d[1] = m10;
+ d[2] = m01;
+ d[3] = m11;
+ if (d.length >= 6)
+ {
+ d[4] = m02;
+ d[5] = m12;
+ }
+ }
+
+ /**
+ * Returns the X coordinate scaling factor of the matrix.
+ *
+ * @return m00
+ * @see #getMatrix(double[])
+ */
+ public double getScaleX()
+ {
+ return m00;
+ }
+
+ /**
+ * Returns the Y coordinate scaling factor of the matrix.
+ *
+ * @return m11
+ * @see #getMatrix(double[])
+ */
+ public double getScaleY()
+ {
+ return m11;
+ }
+
+ /**
+ * Returns the X coordinate shearing factor of the matrix.
+ *
+ * @return m01
+ * @see #getMatrix(double[])
+ */
+ public double getShearX()
+ {
+ return m01;
+ }
+
+ /**
+ * Returns the Y coordinate shearing factor of the matrix.
+ *
+ * @return m10
+ * @see #getMatrix(double[])
+ */
+ public double getShearY()
+ {
+ return m10;
+ }
+
+ /**
+ * Returns the X coordinate translation factor of the matrix.
+ *
+ * @return m02
+ * @see #getMatrix(double[])
+ */
+ public double getTranslateX()
+ {
+ return m02;
+ }
+
+ /**
+ * Returns the Y coordinate translation factor of the matrix.
+ *
+ * @return m12
+ * @see #getMatrix(double[])
+ */
+ public double getTranslateY()
+ {
+ return m12;
+ }
+
+ /**
+ * Concatenate a translation onto this transform. This is equivalent, but
+ * more efficient than
+ * <code>concatenate(AffineTransform.getTranslateInstance(tx, ty))</code>.
+ *
+ * @param tx the x translation distance
+ * @param ty the y translation distance
+ * @see #getTranslateInstance(double, double)
+ * @see #concatenate(AffineTransform)
+ */
+ public void translate(double tx, double ty)
+ {
+ m02 += tx * m00 + ty * m01;
+ m12 += tx * m10 + ty * m11;
+ updateType();
+ }
+
+ /**
+ * Concatenate a rotation onto this transform. This is equivalent, but
+ * more efficient than
+ * <code>concatenate(AffineTransform.getRotateInstance(theta))</code>.
+ *
+ * @param theta the rotation angle
+ * @see #getRotateInstance(double)
+ * @see #concatenate(AffineTransform)
+ */
+ public void rotate(double theta)
+ {
+ double c = Math.cos(theta);
+ double s = Math.sin(theta);
+ double n00 = m00 * c + m01 * s;
+ double n01 = m00 * -s + m01 * c;
+ double n10 = m10 * c + m11 * s;
+ double n11 = m10 * -s + m11 * c;
+ m00 = n00;
+ m01 = n01;
+ m10 = n10;
+ m11 = n11;
+ updateType();
+ }
+
+ /**
+ * Concatenate a rotation about a point onto this transform. This is
+ * equivalent, but more efficient than
+ * <code>concatenate(AffineTransform.getRotateInstance(theta, x, y))</code>.
+ *
+ * @param theta the rotation angle
+ * @param x the x coordinate of the pivot point
+ * @param y the y coordinate of the pivot point
+ * @see #getRotateInstance(double, double, double)
+ * @see #concatenate(AffineTransform)
+ */
+ public void rotate(double theta, double x, double y)
+ {
+ translate(x, y);
+ rotate(theta);
+ translate(-x, -y);
+ }
+
+ /**
+ * Concatenate a scale onto this transform. This is equivalent, but more
+ * efficient than
+ * <code>concatenate(AffineTransform.getScaleInstance(sx, sy))</code>.
+ *
+ * @param sx the x scaling factor
+ * @param sy the y scaling factor
+ * @see #getScaleInstance(double, double)
+ * @see #concatenate(AffineTransform)
+ */
+ public void scale(double sx, double sy)
+ {
+ m00 *= sx;
+ m01 *= sy;
+ m10 *= sx;
+ m11 *= sy;
+ updateType();
+ }
+
+ /**
+ * Concatenate a shearing onto this transform. This is equivalent, but more
+ * efficient than
+ * <code>concatenate(AffineTransform.getShearInstance(sx, sy))</code>.
+ *
+ * @param shx the x shearing factor
+ * @param shy the y shearing factor
+ * @see #getShearInstance(double, double)
+ * @see #concatenate(AffineTransform)
+ */
+ public void shear(double shx, double shy)
+ {
+ double n00 = m00 + (shy * m01);
+ double n01 = m01 + (shx * m00);
+ double n10 = m10 + (shy * m11);
+ double n11 = m11 + (shx * m10);
+ m00 = n00;
+ m01 = n01;
+ m10 = n10;
+ m11 = n11;
+ updateType();
+ }
+
+ /**
+ * Reset this transform to the identity (no transformation):
+ * <pre>
+ * [ 1 0 0 ]
+ * [ 0 1 0 ]
+ * [ 0 0 1 ]
+ * </pre>
+ */
+ public void setToIdentity()
+ {
+ m00 = m11 = 1;
+ m01 = m02 = m10 = m12 = 0;
+ type = TYPE_IDENTITY;
+ }
+
+ /**
+ * Set this transform to a translation:
+ * <pre>
+ * [ 1 0 tx ]
+ * [ 0 1 ty ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param tx the x translation distance
+ * @param ty the y translation distance
+ */
+ public void setToTranslation(double tx, double ty)
+ {
+ m00 = m11 = 1;
+ m01 = m10 = 0;
+ m02 = tx;
+ m12 = ty;
+ type = (tx == 0 && ty == 0) ? TYPE_UNIFORM_SCALE : TYPE_TRANSLATION;
+ }
+
+ /**
+ * Set this transform to a rotation. A positive angle (in radians) rotates
+ * the positive x-axis to the positive y-axis:
+ * <pre>
+ * [ cos(theta) -sin(theta) 0 ]
+ * [ sin(theta) cos(theta) 0 ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param theta the rotation angle
+ */
+ public void setToRotation(double theta)
+ {
+ double c = Math.cos(theta);
+ double s = Math.sin(theta);
+ m00 = c;
+ m01 = -s;
+ m02 = 0;
+ m10 = s;
+ m11 = c;
+ m12 = 0;
+ type = (c == 1 ? TYPE_IDENTITY
+ : c == 0 || c == -1 ? TYPE_QUADRANT_ROTATION
+ : TYPE_GENERAL_ROTATION);
+ }
+
+ /**
+ * Set this transform to a rotation about a point. A positive angle (in
+ * radians) rotates the positive x-axis to the positive y-axis. This is the
+ * same as calling:
+ * <pre>
+ * tx.setToTranslation(x, y);
+ * tx.rotate(theta);
+ * tx.translate(-x, -y);
+ * </pre>
+ *
+ * <p>The resulting matrix is:
+ * <pre>
+ * [ cos(theta) -sin(theta) x-x*cos+y*sin ]
+ * [ sin(theta) cos(theta) y-x*sin-y*cos ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param theta the rotation angle
+ * @param x the x coordinate of the pivot point
+ * @param y the y coordinate of the pivot point
+ */
+ public void setToRotation(double theta, double x, double y)
+ {
+ double c = Math.cos(theta);
+ double s = Math.sin(theta);
+ m00 = c;
+ m01 = -s;
+ m02 = x - x * c + y * s;
+ m10 = s;
+ m11 = c;
+ m12 = y - x * s - y * c;
+ updateType();
+ }
+
+ /**
+ * Set this transform to a scale:
+ * <pre>
+ * [ sx 0 0 ]
+ * [ 0 sy 0 ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param sx the x scaling factor
+ * @param sy the y scaling factor
+ */
+ public void setToScale(double sx, double sy)
+ {
+ m00 = sx;
+ m01 = m02 = m10 = m12 = 0;
+ m11 = sy;
+ type = (sx != sy ? TYPE_GENERAL_SCALE
+ : sx == 1 ? TYPE_IDENTITY : TYPE_UNIFORM_SCALE);
+ }
+
+ /**
+ * Set this transform to a shear (points are shifted in the x direction based
+ * on a factor of their y coordinate, and in the y direction as a factor of
+ * their x coordinate):
+ * <pre>
+ * [ 1 shx 0 ]
+ * [ shy 1 0 ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param shx the x shearing factor
+ * @param shy the y shearing factor
+ */
+ public void setToShear(double shx, double shy)
+ {
+ m00 = m11 = 1;
+ m01 = shx;
+ m10 = shy;
+ m02 = m12 = 0;
+ updateType();
+ }
+
+ /**
+ * Set this transform to a copy of the given one.
+ *
+ * @param tx the transform to copy
+ * @throws NullPointerException if tx is null
+ */
+ public void setTransform(AffineTransform tx)
+ {
+ m00 = tx.m00;
+ m01 = tx.m01;
+ m02 = tx.m02;
+ m10 = tx.m10;
+ m11 = tx.m11;
+ m12 = tx.m12;
+ type = tx.type;
+ }
+
+ /**
+ * Set this transform to the given values:
+ * <pre>
+ * [ m00 m01 m02 ]
+ * [ m10 m11 m12 ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @param m00 the x scaling component
+ * @param m10 the y shearing component
+ * @param m01 the x shearing component
+ * @param m11 the y scaling component
+ * @param m02 the x translation component
+ * @param m12 the y translation component
+ */
+ public void setTransform(double m00, double m10, double m01,
+ double m11, double m02, double m12)
+ {
+ this.m00 = m00;
+ this.m10 = m10;
+ this.m01 = m01;
+ this.m11 = m11;
+ this.m02 = m02;
+ this.m12 = m12;
+ updateType();
+ }
+
+ /**
+ * Set this transform to the result of performing the original version of
+ * this followed by tx. This is commonly used when chaining transformations
+ * from one space to another. In matrix form:
+ * <pre>
+ * [ this ] = [ this ] x [ tx ]
+ * </pre>
+ *
+ * @param tx the transform to concatenate
+ * @throws NullPointerException if tx is null
+ * @see #preConcatenate(AffineTransform)
+ */
+ public void concatenate(AffineTransform tx)
+ {
+ double n00 = m00 * tx.m00 + m01 * tx.m10;
+ double n01 = m00 * tx.m01 + m01 * tx.m11;
+ double n02 = m00 * tx.m02 + m01 * tx.m12 + m02;
+ double n10 = m10 * tx.m00 + m11 * tx.m10;
+ double n11 = m10 * tx.m01 + m11 * tx.m11;
+ double n12 = m10 * tx.m02 + m11 * tx.m12 + m12;
+ m00 = n00;
+ m01 = n01;
+ m02 = n02;
+ m10 = n10;
+ m11 = n11;
+ m12 = n12;
+ updateType();
+ }
+
+ /**
+ * Set this transform to the result of performing tx followed by the
+ * original version of this. This is less common than normal concatenation,
+ * but can still be used to chain transformations from one space to another.
+ * In matrix form:
+ * <pre>
+ * [ this ] = [ tx ] x [ this ]
+ * </pre>
+ *
+ * @param tx the transform to concatenate
+ * @throws NullPointerException if tx is null
+ * @see #concatenate(AffineTransform)
+ */
+ public void preConcatenate(AffineTransform tx)
+ {
+ double n00 = tx.m00 * m00 + tx.m01 * m10;
+ double n01 = tx.m00 * m01 + tx.m01 * m11;
+ double n02 = tx.m00 * m02 + tx.m01 * m12 + tx.m02;
+ double n10 = tx.m10 * m00 + tx.m11 * m10;
+ double n11 = tx.m10 * m01 + tx.m11 * m11;
+ double n12 = tx.m10 * m02 + tx.m11 * m12 + tx.m12;
+ m00 = n00;
+ m01 = n01;
+ m02 = n02;
+ m10 = n10;
+ m11 = n11;
+ m12 = n12;
+ updateType();
+ }
+
+ /**
+ * Returns a transform, which if concatenated to this one, will result in
+ * the identity transform. This is useful for undoing transformations, but
+ * is only possible if the original transform has an inverse (ie. does not
+ * map multiple points to the same line or point). A transform exists only
+ * if getDeterminant() has a non-zero value.
+ *
+ * The inverse is calculated as:
+ *
+ * <pre>
+ *
+ * Let A be the matrix for which we want to find the inverse:
+ *
+ * A = [ m00 m01 m02 ]
+ * [ m10 m11 m12 ]
+ * [ 0 0 1 ]
+ *
+ *
+ * 1
+ * inverse (A) = --- x adjoint(A)
+ * det
+ *
+ *
+ *
+ * = 1 [ m11 -m01 m01*m12-m02*m11 ]
+ * --- x [ -m10 m00 -m00*m12+m10*m02 ]
+ * det [ 0 0 m00*m11-m10*m01 ]
+ *
+ *
+ *
+ * = [ m11/det -m01/det m01*m12-m02*m11/det ]
+ * [ -m10/det m00/det -m00*m12+m10*m02/det ]
+ * [ 0 0 1 ]
+ *
+ *
+ * </pre>
+ *
+ *
+ *
+ * @return a new inverse transform
+ * @throws NoninvertibleTransformException if inversion is not possible
+ * @see #getDeterminant()
+ */
+ public AffineTransform createInverse()
+ throws NoninvertibleTransformException
+ {
+ double det = getDeterminant();
+ if (det == 0)
+ throw new NoninvertibleTransformException("can't invert transform");
+
+ double im00 = m11 / det;
+ double im10 = -m10 / det;
+ double im01 = -m01 / det;
+ double im11 = m00 / det;
+ double im02 = (m01 * m12 - m02 * m11) / det;
+ double im12 = (-m00 * m12 + m10 * m02) / det;
+
+ return new AffineTransform (im00, im10, im01, im11, im02, im12);
+ }
+
+ /**
+ * Perform this transformation on the given source point, and store the
+ * result in the destination (creating it if necessary). It is safe for
+ * src and dst to be the same.
+ *
+ * @param src the source point
+ * @param dst the destination, or null
+ * @return the transformation of src, in dst if it was non-null
+ * @throws NullPointerException if src is null
+ */
+ public Point2D transform(Point2D src, Point2D dst)
+ {
+ if (dst == null)
+ dst = new Point2D.Double();
+ double x = src.getX();
+ double y = src.getY();
+ double nx = m00 * x + m01 * y + m02;
+ double ny = m10 * x + m11 * y + m12;
+ dst.setLocation(nx, ny);
+ return dst;
+ }
+
+ /**
+ * Perform this transformation on an array of points, storing the results
+ * in another (possibly same) array. This will not create a destination
+ * array, but will create points for the null entries of the destination.
+ * The transformation is done sequentially. While having a single source
+ * and destination point be the same is safe, you should be aware that
+ * duplicate references to the same point in the source, and having the
+ * source overlap the destination, may result in your source points changing
+ * from a previous transform before it is their turn to be evaluated.
+ *
+ * @param src the array of source points
+ * @param srcOff the starting offset into src
+ * @param dst the array of destination points (may have null entries)
+ * @param dstOff the starting offset into dst
+ * @param num the number of points to transform
+ * @throws NullPointerException if src or dst is null, or src has null
+ * entries
+ * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded
+ * @throws ArrayStoreException if new points are incompatible with dst
+ */
+ public void transform(Point2D[] src, int srcOff,
+ Point2D[] dst, int dstOff, int num)
+ {
+ while (--num >= 0)
+ dst[dstOff] = transform(src[srcOff++], dst[dstOff++]);
+ }
+
+ /**
+ * Perform this transformation on an array of points, in (x,y) pairs,
+ * storing the results in another (possibly same) array. This will not
+ * create a destination array. All sources are copied before the
+ * transformation, so that no result will overwrite a point that has not yet
+ * been evaluated.
+ *
+ * @param srcPts the array of source points
+ * @param srcOff the starting offset into src
+ * @param dstPts the array of destination points
+ * @param dstOff the starting offset into dst
+ * @param num the number of points to transform
+ * @throws NullPointerException if src or dst is null
+ * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded
+ */
+ public void transform(float[] srcPts, int srcOff,
+ float[] dstPts, int dstOff, int num)
+ {
+ if (srcPts == dstPts && dstOff > srcOff
+ && num > 1 && srcOff + 2 * num > dstOff)
+ {
+ float[] f = new float[2 * num];
+ System.arraycopy(srcPts, srcOff, f, 0, 2 * num);
+ srcPts = f;
+ }
+ while (--num >= 0)
+ {
+ float x = srcPts[srcOff++];
+ float y = srcPts[srcOff++];
+ dstPts[dstOff++] = (float) (m00 * x + m01 * y + m02);
+ dstPts[dstOff++] = (float) (m10 * x + m11 * y + m12);
+ }
+ }
+
+ /**
+ * Perform this transformation on an array of points, in (x,y) pairs,
+ * storing the results in another (possibly same) array. This will not
+ * create a destination array. All sources are copied before the
+ * transformation, so that no result will overwrite a point that has not yet
+ * been evaluated.
+ *
+ * @param srcPts the array of source points
+ * @param srcOff the starting offset into src
+ * @param dstPts the array of destination points
+ * @param dstOff the starting offset into dst
+ * @param num the number of points to transform
+ * @throws NullPointerException if src or dst is null
+ * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded
+ */
+ public void transform(double[] srcPts, int srcOff,
+ double[] dstPts, int dstOff, int num)
+ {
+ if (srcPts == dstPts && dstOff > srcOff
+ && num > 1 && srcOff + 2 * num > dstOff)
+ {
+ double[] d = new double[2 * num];
+ System.arraycopy(srcPts, srcOff, d, 0, 2 * num);
+ srcPts = d;
+ }
+ while (--num >= 0)
+ {
+ double x = srcPts[srcOff++];
+ double y = srcPts[srcOff++];
+ dstPts[dstOff++] = m00 * x + m01 * y + m02;
+ dstPts[dstOff++] = m10 * x + m11 * y + m12;
+ }
+ }
+
+ /**
+ * Perform this transformation on an array of points, in (x,y) pairs,
+ * storing the results in another array. This will not create a destination
+ * array.
+ *
+ * @param srcPts the array of source points
+ * @param srcOff the starting offset into src
+ * @param dstPts the array of destination points
+ * @param dstOff the starting offset into dst
+ * @param num the number of points to transform
+ * @throws NullPointerException if src or dst is null
+ * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded
+ */
+ public void transform(float[] srcPts, int srcOff,
+ double[] dstPts, int dstOff, int num)
+ {
+ while (--num >= 0)
+ {
+ float x = srcPts[srcOff++];
+ float y = srcPts[srcOff++];
+ dstPts[dstOff++] = m00 * x + m01 * y + m02;
+ dstPts[dstOff++] = m10 * x + m11 * y + m12;
+ }
+ }
+
+ /**
+ * Perform this transformation on an array of points, in (x,y) pairs,
+ * storing the results in another array. This will not create a destination
+ * array.
+ *
+ * @param srcPts the array of source points
+ * @param srcOff the starting offset into src
+ * @param dstPts the array of destination points
+ * @param dstOff the starting offset into dst
+ * @param num the number of points to transform
+ * @throws NullPointerException if src or dst is null
+ * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded
+ */
+ public void transform(double[] srcPts, int srcOff,
+ float[] dstPts, int dstOff, int num)
+ {
+ while (--num >= 0)
+ {
+ double x = srcPts[srcOff++];
+ double y = srcPts[srcOff++];
+ dstPts[dstOff++] = (float) (m00 * x + m01 * y + m02);
+ dstPts[dstOff++] = (float) (m10 * x + m11 * y + m12);
+ }
+ }
+
+ /**
+ * Perform the inverse of this transformation on the given source point,
+ * and store the result in the destination (creating it if necessary). It
+ * is safe for src and dst to be the same.
+ *
+ * @param src the source point
+ * @param dst the destination, or null
+ * @return the inverse transformation of src, in dst if it was non-null
+ * @throws NullPointerException if src is null
+ * @throws NoninvertibleTransformException if the inverse does not exist
+ * @see #getDeterminant()
+ */
+ public Point2D inverseTransform(Point2D src, Point2D dst)
+ throws NoninvertibleTransformException
+ {
+ return createInverse().transform(src, dst);
+ }
+
+ /**
+ * Perform the inverse of this transformation on an array of points, in
+ * (x,y) pairs, storing the results in another (possibly same) array. This
+ * will not create a destination array. All sources are copied before the
+ * transformation, so that no result will overwrite a point that has not yet
+ * been evaluated.
+ *
+ * @param srcPts the array of source points
+ * @param srcOff the starting offset into src
+ * @param dstPts the array of destination points
+ * @param dstOff the starting offset into dst
+ * @param num the number of points to transform
+ * @throws NullPointerException if src or dst is null
+ * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded
+ * @throws NoninvertibleTransformException if the inverse does not exist
+ * @see #getDeterminant()
+ */
+ public void inverseTransform(double[] srcPts, int srcOff,
+ double[] dstPts, int dstOff, int num)
+ throws NoninvertibleTransformException
+ {
+ createInverse().transform(srcPts, srcOff, dstPts, dstOff, num);
+ }
+
+ /**
+ * Perform this transformation, less any translation, on the given source
+ * point, and store the result in the destination (creating it if
+ * necessary). It is safe for src and dst to be the same. The reduced
+ * transform is equivalent to:
+ * <pre>
+ * [ x' ] = [ m00 m01 ] [ x ] = [ m00 * x + m01 * y ]
+ * [ y' ] [ m10 m11 ] [ y ] = [ m10 * x + m11 * y ]
+ * </pre>
+ *
+ * @param src the source point
+ * @param dst the destination, or null
+ * @return the delta transformation of src, in dst if it was non-null
+ * @throws NullPointerException if src is null
+ */
+ public Point2D deltaTransform(Point2D src, Point2D dst)
+ {
+ if (dst == null)
+ dst = new Point2D.Double();
+ double x = src.getX();
+ double y = src.getY();
+ double nx = m00 * x + m01 * y;
+ double ny = m10 * x + m11 * y;
+ dst.setLocation(nx, ny);
+ return dst;
+ }
+
+ /**
+ * Perform this transformation, less any translation, on an array of points,
+ * in (x,y) pairs, storing the results in another (possibly same) array.
+ * This will not create a destination array. All sources are copied before
+ * the transformation, so that no result will overwrite a point that has
+ * not yet been evaluated. The reduced transform is equivalent to:
+ * <pre>
+ * [ x' ] = [ m00 m01 ] [ x ] = [ m00 * x + m01 * y ]
+ * [ y' ] [ m10 m11 ] [ y ] = [ m10 * x + m11 * y ]
+ * </pre>
+ *
+ * @param srcPts the array of source points
+ * @param srcOff the starting offset into src
+ * @param dstPts the array of destination points
+ * @param dstOff the starting offset into dst
+ * @param num the number of points to transform
+ * @throws NullPointerException if src or dst is null
+ * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded
+ */
+ public void deltaTransform(double[] srcPts, int srcOff,
+ double[] dstPts, int dstOff,
+ int num)
+ {
+ if (srcPts == dstPts && dstOff > srcOff
+ && num > 1 && srcOff + 2 * num > dstOff)
+ {
+ double[] d = new double[2 * num];
+ System.arraycopy(srcPts, srcOff, d, 0, 2 * num);
+ srcPts = d;
+ }
+ while (--num >= 0)
+ {
+ double x = srcPts[srcOff++];
+ double y = srcPts[srcOff++];
+ dstPts[dstOff++] = m00 * x + m01 * y;
+ dstPts[dstOff++] = m10 * x + m11 * y;
+ }
+ }
+
+ /**
+ * Return a new Shape, based on the given one, where the path of the shape
+ * has been transformed by this transform. Notice that this uses GeneralPath,
+ * which only stores points in float precision.
+ *
+ * @param src the shape source to transform
+ * @return the shape, transformed by this, <code>null</code> if src is
+ * <code>null</code>.
+ * @see GeneralPath#transform(AffineTransform)
+ */
+ public Shape createTransformedShape(Shape src)
+ {
+ if(src == null)
+ return null;
+ GeneralPath p = new GeneralPath(src);
+ p.transform(this);
+ return p;
+ }
+
+ /**
+ * Returns a string representation of the transform, in the format:
+ * <code>"AffineTransform[[" + m00 + ", " + m01 + ", " + m02 + "], ["
+ * + m10 + ", " + m11 + ", " + m12 + "]]"</code>.
+ *
+ * @return the string representation
+ */
+ public String toString()
+ {
+ return "AffineTransform[[" + m00 + ", " + m01 + ", " + m02 + "], ["
+ + m10 + ", " + m11 + ", " + m12 + "]]";
+ }
+
+ /**
+ * Tests if this transformation is the identity:
+ * <pre>
+ * [ 1 0 0 ]
+ * [ 0 1 0 ]
+ * [ 0 0 1 ]
+ * </pre>
+ *
+ * @return true if this is the identity transform
+ */
+ public boolean isIdentity()
+ {
+ // Rather than rely on type, check explicitly.
+ return (m00 == 1 && m01 == 0 && m02 == 0
+ && m10 == 0 && m11 == 1 && m12 == 0);
+ }
+
+ /**
+ * Create a new transform of the same run-time type, with the same
+ * transforming properties as this one.
+ *
+ * @return the clone
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // Impossible
+ }
+ }
+
+ /**
+ * Return the hashcode for this transformation. The formula is not
+ * documented, but appears to be the same as:
+ * <pre>
+ * long l = Double.doubleToLongBits(getScaleX());
+ * l = l * 31 + Double.doubleToLongBits(getShearX());
+ * l = l * 31 + Double.doubleToLongBits(getTranslateX());
+ * l = l * 31 + Double.doubleToLongBits(getShearY());
+ * l = l * 31 + Double.doubleToLongBits(getScaleY());
+ * l = l * 31 + Double.doubleToLongBits(getTranslateY());
+ * return (int) ((l >> 32) ^ l);
+ * </pre>
+ *
+ * @return the hashcode
+ */
+ public int hashCode()
+ {
+ long l = Double.doubleToLongBits(m00);
+ l = l * 31 + Double.doubleToLongBits(m01);
+ l = l * 31 + Double.doubleToLongBits(m02);
+ l = l * 31 + Double.doubleToLongBits(m10);
+ l = l * 31 + Double.doubleToLongBits(m11);
+ l = l * 31 + Double.doubleToLongBits(m12);
+ return (int) ((l >> 32) ^ l);
+ }
+
+ /**
+ * Compares two transforms for equality. This returns true if they have the
+ * same matrix values.
+ *
+ * @param obj the transform to compare
+ * @return true if it is equal
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof AffineTransform))
+ return false;
+ AffineTransform t = (AffineTransform) obj;
+ return (m00 == t.m00 && m01 == t.m01 && m02 == t.m02
+ && m10 == t.m10 && m11 == t.m11 && m12 == t.m12);
+ }
+
+ /**
+ * Helper to decode the type from the matrix. This is not guaranteed
+ * to find the optimal type, but at least it will be valid.
+ */
+ private void updateType()
+ {
+ double det = getDeterminant();
+ if (det == 0)
+ {
+ type = TYPE_GENERAL_TRANSFORM;
+ return;
+ }
+ // Scale (includes rotation by PI) or translation.
+ if (m01 == 0 && m10 == 0)
+ {
+ if (m00 == m11)
+ type = m00 == 1 ? TYPE_IDENTITY : TYPE_UNIFORM_SCALE;
+ else
+ type = TYPE_GENERAL_SCALE;
+ if (m02 != 0 || m12 != 0)
+ type |= TYPE_TRANSLATION;
+ }
+ // Rotation.
+ else if (m00 == m11 && m01 == -m10)
+ {
+ type = m00 == 0 ? TYPE_QUADRANT_ROTATION : TYPE_GENERAL_ROTATION;
+ if (det != 1)
+ type |= TYPE_UNIFORM_SCALE;
+ if (m02 != 0 || m12 != 0)
+ type |= TYPE_TRANSLATION;
+ }
+ else
+ type = TYPE_GENERAL_TRANSFORM;
+ }
+
+ /**
+ * Reads a transform from an object stream.
+ *
+ * @param s the stream to read from
+ * @throws ClassNotFoundException if there is a problem deserializing
+ * @throws IOException if there is a problem deserializing
+ */
+ private void readObject(ObjectInputStream s)
+ throws ClassNotFoundException, IOException
+ {
+ s.defaultReadObject();
+ updateType();
+ }
+} // class AffineTransform
diff --git a/libjava/classpath/java/awt/geom/Arc2D.java b/libjava/classpath/java/awt/geom/Arc2D.java
new file mode 100644
index 000000000..928c5cfc8
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/Arc2D.java
@@ -0,0 +1,1413 @@
+/* Arc2D.java -- represents an arc in 2-D space
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.geom;
+
+import java.util.NoSuchElementException;
+
+
+/**
+ * This class represents all arcs (segments of an ellipse in 2-D space). The
+ * arcs are defined by starting angle and extent (arc length) in degrees, as
+ * opposed to radians (like the rest of Java), and can be open, chorded, or
+ * wedge shaped. The angles are skewed according to the ellipse, so that 45
+ * degrees always points to the upper right corner (positive x, negative y)
+ * of the bounding rectangle. A positive extent draws a counterclockwise arc,
+ * and while the angle can be any value, the path iterator only traverses the
+ * first 360 degrees. Storage is up to the subclasses.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Sven de Marothy (sven@physto.se)
+ * @since 1.2
+ */
+public abstract class Arc2D extends RectangularShape
+{
+ /**
+ * An open arc, with no segment connecting the endpoints. This type of
+ * arc still contains the same points as a chorded version.
+ */
+ public static final int OPEN = 0;
+
+ /**
+ * A closed arc with a single segment connecting the endpoints (a chord).
+ */
+ public static final int CHORD = 1;
+
+ /**
+ * A closed arc with two segments, one from each endpoint, meeting at the
+ * center of the ellipse.
+ */
+ public static final int PIE = 2;
+
+ /** The closure type of this arc. This is package-private to avoid an
+ * accessor method. */
+ int type;
+
+ /**
+ * Create a new arc, with the specified closure type.
+ *
+ * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE}.
+ * @throws IllegalArgumentException if type is invalid
+ */
+ protected Arc2D(int type)
+ {
+ if (type < OPEN || type > PIE)
+ throw new IllegalArgumentException();
+ this.type = type;
+ }
+
+ /**
+ * Get the starting angle of the arc in degrees.
+ *
+ * @return the starting angle
+ * @see #setAngleStart(double)
+ */
+ public abstract double getAngleStart();
+
+ /**
+ * Get the extent angle of the arc in degrees.
+ *
+ * @return the extent angle
+ * @see #setAngleExtent(double)
+ */
+ public abstract double getAngleExtent();
+
+ /**
+ * Return the closure type of the arc.
+ *
+ * @return the closure type
+ * @see #OPEN
+ * @see #CHORD
+ * @see #PIE
+ * @see #setArcType(int)
+ */
+ public int getArcType()
+ {
+ return type;
+ }
+
+ /**
+ * Returns the starting point of the arc.
+ *
+ * @return the start point
+ */
+ public Point2D getStartPoint()
+ {
+ double angle = Math.toRadians(getAngleStart());
+ double rx = getWidth() / 2;
+ double ry = getHeight() / 2;
+ double x = getX() + rx + rx * Math.cos(angle);
+ double y = getY() + ry - ry * Math.sin(angle);
+ return new Point2D.Double(x, y);
+ }
+
+ /**
+ * Returns the ending point of the arc.
+ *
+ * @return the end point
+ */
+ public Point2D getEndPoint()
+ {
+ double angle = Math.toRadians(getAngleStart() + getAngleExtent());
+ double rx = getWidth() / 2;
+ double ry = getHeight() / 2;
+ double x = getX() + rx + rx * Math.cos(angle);
+ double y = getY() + ry - ry * Math.sin(angle);
+ return new Point2D.Double(x, y);
+ }
+
+ /**
+ * Set the parameters of the arc. The angles are in degrees, and a positive
+ * extent sweeps counterclockwise (from the positive x-axis to the negative
+ * y-axis).
+ *
+ * @param x the new x coordinate of the upper left of the bounding box
+ * @param y the new y coordinate of the upper left of the bounding box
+ * @param w the new width of the bounding box
+ * @param h the new height of the bounding box
+ * @param start the start angle, in degrees
+ * @param extent the arc extent, in degrees
+ * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
+ * @throws IllegalArgumentException if type is invalid
+ */
+ public abstract void setArc(double x, double y, double w, double h,
+ double start, double extent, int type);
+
+ /**
+ * Set the parameters of the arc. The angles are in degrees, and a positive
+ * extent sweeps counterclockwise (from the positive x-axis to the negative
+ * y-axis).
+ *
+ * @param p the upper left point of the bounding box
+ * @param d the dimensions of the bounding box
+ * @param start the start angle, in degrees
+ * @param extent the arc extent, in degrees
+ * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
+ * @throws IllegalArgumentException if type is invalid
+ * @throws NullPointerException if p or d is null
+ */
+ public void setArc(Point2D p, Dimension2D d, double start, double extent,
+ int type)
+ {
+ setArc(p.getX(), p.getY(), d.getWidth(), d.getHeight(), start, extent, type);
+ }
+
+ /**
+ * Set the parameters of the arc. The angles are in degrees, and a positive
+ * extent sweeps counterclockwise (from the positive x-axis to the negative
+ * y-axis).
+ *
+ * @param r the new bounding box
+ * @param start the start angle, in degrees
+ * @param extent the arc extent, in degrees
+ * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
+ * @throws IllegalArgumentException if type is invalid
+ * @throws NullPointerException if r is null
+ */
+ public void setArc(Rectangle2D r, double start, double extent, int type)
+ {
+ setArc(r.getX(), r.getY(), r.getWidth(), r.getHeight(), start, extent, type);
+ }
+
+ /**
+ * Set the parameters of the arc from the given one.
+ *
+ * @param a the arc to copy
+ * @throws NullPointerException if a is null
+ */
+ public void setArc(Arc2D a)
+ {
+ setArc(a.getX(), a.getY(), a.getWidth(), a.getHeight(), a.getAngleStart(),
+ a.getAngleExtent(), a.getArcType());
+ }
+
+ /**
+ * Set the parameters of the arc. The angles are in degrees, and a positive
+ * extent sweeps counterclockwise (from the positive x-axis to the negative
+ * y-axis). This controls the center point and radius, so the arc will be
+ * circular.
+ *
+ * @param x the x coordinate of the center of the circle
+ * @param y the y coordinate of the center of the circle
+ * @param r the radius of the circle
+ * @param start the start angle, in degrees
+ * @param extent the arc extent, in degrees
+ * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
+ * @throws IllegalArgumentException if type is invalid
+ */
+ public void setArcByCenter(double x, double y, double r, double start,
+ double extent, int type)
+ {
+ setArc(x - r, y - r, r + r, r + r, start, extent, type);
+ }
+
+ /**
+ * Sets the parameters of the arc by finding the tangents of two lines, and
+ * using the specified radius. The arc will be circular, will begin on the
+ * tangent point of the line extending from p1 to p2, and will end on the
+ * tangent point of the line extending from p2 to p3.
+ *
+ * XXX What happens if the points are colinear, or the radius negative?
+ *
+ * @param p1 the first point
+ * @param p2 the tangent line intersection point
+ * @param p3 the third point
+ * @param r the radius of the arc
+ * @throws NullPointerException if any point is null
+ */
+ public void setArcByTangent(Point2D p1, Point2D p2, Point2D p3, double r)
+ {
+ if ((p2.getX() - p1.getX()) * (p3.getY() - p1.getY())
+ - (p3.getX() - p1.getX()) * (p2.getY() - p1.getY()) > 0)
+ {
+ Point2D p = p3;
+ p3 = p1;
+ p1 = p;
+ }
+
+ // normalized tangent vectors
+ double dx1 = (p1.getX() - p2.getX()) / p1.distance(p2);
+ double dy1 = (p1.getY() - p2.getY()) / p1.distance(p2);
+ double dx2 = (p2.getX() - p3.getX()) / p3.distance(p2);
+ double dy2 = (p2.getY() - p3.getY()) / p3.distance(p2);
+ double theta1 = Math.atan2(dx1, dy1);
+ double theta2 = Math.atan2(dx2, dy2);
+
+ double dx = r * Math.cos(theta2) - r * Math.cos(theta1);
+ double dy = -r * Math.sin(theta2) + r * Math.sin(theta1);
+
+ if (theta1 < 0)
+ theta1 += 2 * Math.PI;
+ if (theta2 < 0)
+ theta2 += 2 * Math.PI;
+ if (theta2 < theta1)
+ theta2 += 2 * Math.PI;
+
+ // Vectors of the lines, not normalized, note we change
+ // the direction of line 2.
+ dx1 = p1.getX() - p2.getX();
+ dy1 = p1.getY() - p2.getY();
+ dx2 = p3.getX() - p2.getX();
+ dy2 = p3.getY() - p2.getY();
+
+ // Calculate the tangent point to the second line
+ double t2 = -(dx1 * dy - dy1 * dx) / (dx2 * dy1 - dx1 * dy2);
+ double x2 = t2 * (p3.getX() - p2.getX()) + p2.getX();
+ double y2 = t2 * (p3.getY() - p2.getY()) + p2.getY();
+
+ // calculate the center point
+ double x = x2 - r * Math.cos(theta2);
+ double y = y2 + r * Math.sin(theta2);
+
+ setArc(x - r, y - r, 2 * r, 2 * r, Math.toDegrees(theta1),
+ Math.toDegrees(theta2 - theta1), getArcType());
+ }
+
+ /**
+ * Set the start, in degrees.
+ *
+ * @param start the new start angle
+ * @see #getAngleStart()
+ */
+ public abstract void setAngleStart(double start);
+
+ /**
+ * Set the extent, in degrees.
+ *
+ * @param extent the new extent angle
+ * @see #getAngleExtent()
+ */
+ public abstract void setAngleExtent(double extent);
+
+ /**
+ * Sets the starting angle to the angle of the given point relative to
+ * the center of the arc. The extent remains constant; in other words,
+ * this rotates the arc.
+ *
+ * @param p the new start point
+ * @throws NullPointerException if p is null
+ * @see #getStartPoint()
+ * @see #getAngleStart()
+ */
+ public void setAngleStart(Point2D p)
+ {
+ // Normalize.
+ double x = p.getX() - (getX() + getWidth() / 2);
+ double y = p.getY() - (getY() + getHeight() / 2);
+ setAngleStart(Math.toDegrees(Math.atan2(-y, x)));
+ }
+
+ /**
+ * Sets the starting and extent angles to those of the given points
+ * relative to the center of the arc. The arc will be non-empty, and will
+ * extend counterclockwise.
+ *
+ * @param x1 the first x coordinate
+ * @param y1 the first y coordinate
+ * @param x2 the second x coordinate
+ * @param y2 the second y coordinate
+ * @see #setAngleStart(Point2D)
+ */
+ public void setAngles(double x1, double y1, double x2, double y2)
+ {
+ // Normalize the points.
+ double mx = getX();
+ double my = getY();
+ double mw = getWidth();
+ double mh = getHeight();
+ x1 = x1 - (mx + mw / 2);
+ y1 = y1 - (my + mh / 2);
+ x2 = x2 - (mx + mw / 2);
+ y2 = y2 - (my + mh / 2);
+ double start = Math.toDegrees(Math.atan2(-y1, x1));
+ double extent = Math.toDegrees(Math.atan2(-y2, x2)) - start;
+ if (extent < 0)
+ extent += 360;
+ setAngleStart(start);
+ setAngleExtent(extent);
+ }
+
+ /**
+ * Sets the starting and extent angles to those of the given points
+ * relative to the center of the arc. The arc will be non-empty, and will
+ * extend counterclockwise.
+ *
+ * @param p1 the first point
+ * @param p2 the second point
+ * @throws NullPointerException if either point is null
+ * @see #setAngleStart(Point2D)
+ */
+ public void setAngles(Point2D p1, Point2D p2)
+ {
+ setAngles(p1.getX(), p1.getY(), p2.getX(), p2.getY());
+ }
+
+ /**
+ * Set the closure type of this arc.
+ *
+ * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
+ * @throws IllegalArgumentException if type is invalid
+ * @see #getArcType()
+ */
+ public void setArcType(int type)
+ {
+ if (type < OPEN || type > PIE)
+ throw new IllegalArgumentException();
+ this.type = type;
+ }
+
+ /**
+ * Sets the location and bounds of the ellipse of which this arc is a part.
+ *
+ * @param x the new x coordinate
+ * @param y the new y coordinate
+ * @param w the new width
+ * @param h the new height
+ * @see #getFrame()
+ */
+ public void setFrame(double x, double y, double w, double h)
+ {
+ setArc(x, y, w, h, getAngleStart(), getAngleExtent(), type);
+ }
+
+ /**
+ * Gets the bounds of the arc. This is much tighter than
+ * <code>getBounds</code>, as it takes into consideration the start and
+ * end angles, and the center point of a pie wedge, rather than just the
+ * overall ellipse.
+ *
+ * @return the bounds of the arc
+ * @see #getBounds()
+ */
+ public Rectangle2D getBounds2D()
+ {
+ double extent = getAngleExtent();
+ if (Math.abs(extent) >= 360)
+ return makeBounds(getX(), getY(), getWidth(), getHeight());
+
+ // Find the minimal bounding box. This determined by its extrema,
+ // which are the center, the endpoints of the arc, and any local
+ // maximum contained by the arc.
+ double rX = getWidth() / 2;
+ double rY = getHeight() / 2;
+ double centerX = getX() + rX;
+ double centerY = getY() + rY;
+
+ Point2D p1 = getStartPoint();
+ Rectangle2D result = makeBounds(p1.getX(), p1.getY(), 0, 0);
+ result.add(getEndPoint());
+
+ if (type == PIE)
+ result.add(centerX, centerY);
+ if (containsAngle(0))
+ result.add(centerX + rX, centerY);
+ if (containsAngle(90))
+ result.add(centerX, centerY - rY);
+ if (containsAngle(180))
+ result.add(centerX - rX, centerY);
+ if (containsAngle(270))
+ result.add(centerX, centerY + rY);
+
+ return result;
+ }
+
+ /**
+ * Construct a bounding box in a precision appropriate for the subclass.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param w the width
+ * @param h the height
+ * @return the rectangle for use in getBounds2D
+ */
+ protected abstract Rectangle2D makeBounds(double x, double y, double w,
+ double h);
+
+ /**
+ * Tests if the given angle, in degrees, is included in the arc.
+ * All angles are normalized to be between 0 and 360 degrees.
+ *
+ * @param a the angle to test
+ * @return true if it is contained
+ */
+ public boolean containsAngle(double a)
+ {
+ double start = getAngleStart();
+ double extent = getAngleExtent();
+ double end = start + extent;
+
+ if (extent == 0)
+ return false;
+
+ if (extent >= 360 || extent <= -360)
+ return true;
+
+ if (extent < 0)
+ {
+ end = start;
+ start += extent;
+ }
+
+ start %= 360;
+ while (start < 0)
+ start += 360;
+
+ end %= 360;
+ while (end < start)
+ end += 360;
+
+ a %= 360;
+ while (a < start)
+ a += 360;
+
+ return a >= start && a < end; // starting angle included, ending angle not
+ }
+
+ /**
+ * Determines if the arc contains the given point. If the bounding box
+ * is empty, then this will return false.
+ *
+ * The area considered 'inside' an arc of type OPEN is the same as the
+ * area inside an equivalent filled CHORD-type arc. The area considered
+ * 'inside' a CHORD-type arc is the same as the filled area.
+ *
+ * @param x the x coordinate to test
+ * @param y the y coordinate to test
+ * @return true if the point is inside the arc
+ */
+ public boolean contains(double x, double y)
+ {
+ double w = getWidth();
+ double h = getHeight();
+ double extent = getAngleExtent();
+ if (w <= 0 || h <= 0 || extent == 0)
+ return false;
+
+ double mx = getX() + w / 2;
+ double my = getY() + h / 2;
+ double dx = (x - mx) * 2 / w;
+ double dy = (y - my) * 2 / h;
+ if ((dx * dx + dy * dy) >= 1.0)
+ return false;
+
+ double angle = Math.toDegrees(Math.atan2(-dy, dx));
+ if (getArcType() == PIE)
+ return containsAngle(angle);
+
+ double a1 = Math.toRadians(getAngleStart());
+ double a2 = Math.toRadians(getAngleStart() + extent);
+ double x1 = mx + getWidth() * Math.cos(a1) / 2;
+ double y1 = my - getHeight() * Math.sin(a1) / 2;
+ double x2 = mx + getWidth() * Math.cos(a2) / 2;
+ double y2 = my - getHeight() * Math.sin(a2) / 2;
+ double sgn = ((x2 - x1) * (my - y1) - (mx - x1) * (y2 - y1)) * ((x2 - x1) * (y
+ - y1) - (x - x1) * (y2 - y1));
+
+ if (Math.abs(extent) > 180)
+ {
+ if (containsAngle(angle))
+ return true;
+ return sgn > 0;
+ }
+ else
+ {
+ if (! containsAngle(angle))
+ return false;
+ return sgn < 0;
+ }
+ }
+
+ /**
+ * Tests if a given rectangle intersects the area of the arc.
+ *
+ * For a definition of the 'inside' area, see the contains() method.
+ * @see #contains(double, double)
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @return true if the two shapes share common points
+ */
+ public boolean intersects(double x, double y, double w, double h)
+ {
+ double extent = getAngleExtent();
+ if (extent == 0)
+ return false;
+
+ if (contains(x, y) || contains(x, y + h) || contains(x + w, y)
+ || contains(x + w, y + h))
+ return true;
+
+ Rectangle2D rect = new Rectangle2D.Double(x, y, w, h);
+
+ double a = getWidth() / 2.0;
+ double b = getHeight() / 2.0;
+
+ double mx = getX() + a;
+ double my = getY() + b;
+ double x1 = mx + a * Math.cos(Math.toRadians(getAngleStart()));
+ double y1 = my - b * Math.sin(Math.toRadians(getAngleStart()));
+ double x2 = mx + a * Math.cos(Math.toRadians(getAngleStart() + extent));
+ double y2 = my - b * Math.sin(Math.toRadians(getAngleStart() + extent));
+
+ if (getArcType() != CHORD)
+ {
+ // check intersections against the pie radii
+ if (rect.intersectsLine(mx, my, x1, y1))
+ return true;
+ if (rect.intersectsLine(mx, my, x2, y2))
+ return true;
+ }
+ else// check the chord
+ if (rect.intersectsLine(x1, y1, x2, y2))
+ return true;
+
+ // Check the Arc segment against the four edges
+ double dx;
+
+ // Check the Arc segment against the four edges
+ double dy;
+ dy = y - my;
+ dx = a * Math.sqrt(1 - ((dy * dy) / (b * b)));
+ if (! java.lang.Double.isNaN(dx))
+ {
+ if (mx + dx >= x && mx + dx <= x + w
+ && containsAngle(Math.toDegrees(Math.atan2(-dy, dx))))
+ return true;
+ if (mx - dx >= x && mx - dx <= x + w
+ && containsAngle(Math.toDegrees(Math.atan2(-dy, -dx))))
+ return true;
+ }
+ dy = (y + h) - my;
+ dx = a * Math.sqrt(1 - ((dy * dy) / (b * b)));
+ if (! java.lang.Double.isNaN(dx))
+ {
+ if (mx + dx >= x && mx + dx <= x + w
+ && containsAngle(Math.toDegrees(Math.atan2(-dy, dx))))
+ return true;
+ if (mx - dx >= x && mx - dx <= x + w
+ && containsAngle(Math.toDegrees(Math.atan2(-dy, -dx))))
+ return true;
+ }
+ dx = x - mx;
+ dy = b * Math.sqrt(1 - ((dx * dx) / (a * a)));
+ if (! java.lang.Double.isNaN(dy))
+ {
+ if (my + dy >= y && my + dy <= y + h
+ && containsAngle(Math.toDegrees(Math.atan2(-dy, dx))))
+ return true;
+ if (my - dy >= y && my - dy <= y + h
+ && containsAngle(Math.toDegrees(Math.atan2(dy, dx))))
+ return true;
+ }
+
+ dx = (x + w) - mx;
+ dy = b * Math.sqrt(1 - ((dx * dx) / (a * a)));
+ if (! java.lang.Double.isNaN(dy))
+ {
+ if (my + dy >= y && my + dy <= y + h
+ && containsAngle(Math.toDegrees(Math.atan2(-dy, dx))))
+ return true;
+ if (my - dy >= y && my - dy <= y + h
+ && containsAngle(Math.toDegrees(Math.atan2(dy, dx))))
+ return true;
+ }
+
+ // Check whether the arc is contained within the box
+ if (rect.contains(mx, my))
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Tests if a given rectangle is contained in the area of the arc.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @return true if the arc contains the rectangle
+ */
+ public boolean contains(double x, double y, double w, double h)
+ {
+ double extent = getAngleExtent();
+ if (extent == 0)
+ return false;
+
+ if (! (contains(x, y) && contains(x, y + h) && contains(x + w, y)
+ && contains(x + w, y + h)))
+ return false;
+
+ Rectangle2D rect = new Rectangle2D.Double(x, y, w, h);
+
+ double a = getWidth() / 2.0;
+ double b = getHeight() / 2.0;
+
+ double mx = getX() + a;
+ double my = getY() + b;
+ double x1 = mx + a * Math.cos(Math.toRadians(getAngleStart()));
+ double y1 = my - b * Math.sin(Math.toRadians(getAngleStart()));
+ double x2 = mx + a * Math.cos(Math.toRadians(getAngleStart() + extent));
+ double y2 = my - b * Math.sin(Math.toRadians(getAngleStart() + extent));
+ if (getArcType() != CHORD)
+ {
+ // check intersections against the pie radii
+ if (rect.intersectsLine(mx, my, x1, y1))
+ return false;
+
+ if (rect.intersectsLine(mx, my, x2, y2))
+ return false;
+ }
+ else if (rect.intersectsLine(x1, y1, x2, y2))
+ return false;
+ return true;
+ }
+
+ /**
+ * Tests if a given rectangle is contained in the area of the arc.
+ *
+ * @param r the rectangle
+ * @return true if the arc contains the rectangle
+ */
+ public boolean contains(Rectangle2D r)
+ {
+ return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Returns an iterator over this arc, with an optional transformation.
+ * This iterator is threadsafe, so future modifications to the arc do not
+ * affect the iteration.
+ *
+ * @param at the transformation, or null
+ * @return a path iterator
+ */
+ public PathIterator getPathIterator(AffineTransform at)
+ {
+ return new ArcIterator(this, at);
+ }
+
+ /**
+ * This class is used to iterate over an arc. Since ellipses are a subclass
+ * of arcs, this is used by Ellipse2D as well.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ static final class ArcIterator implements PathIterator
+ {
+ /** The current iteration. */
+ private int current;
+
+ /** The last iteration. */
+ private final int limit;
+
+ /** The optional transformation. */
+ private final AffineTransform xform;
+
+ /** The x coordinate of the bounding box. */
+ private final double x;
+
+ /** The y coordinate of the bounding box. */
+ private final double y;
+
+ /** The width of the bounding box. */
+ private final double w;
+
+ /** The height of the bounding box. */
+ private final double h;
+
+ /** The start angle, in radians (not degrees). */
+ private final double start;
+
+ /** The extent angle, in radians (not degrees). */
+ private final double extent;
+
+ /** The arc closure type. */
+ private final int type;
+
+ /**
+ * Construct a new iterator over an arc.
+ *
+ * @param a the arc
+ * @param xform the transform
+ */
+ public ArcIterator(Arc2D a, AffineTransform xform)
+ {
+ this.xform = xform;
+ x = a.getX();
+ y = a.getY();
+ w = a.getWidth();
+ h = a.getHeight();
+ double start = Math.toRadians(a.getAngleStart());
+ double extent = Math.toRadians(a.getAngleExtent());
+
+ this.start = start;
+ this.extent = extent;
+
+ type = a.type;
+ if (w < 0 || h < 0)
+ limit = -1;
+ else if (extent == 0)
+ limit = type;
+ else if (Math.abs(extent) <= Math.PI / 2.0)
+ limit = type + 1;
+ else if (Math.abs(extent) <= Math.PI)
+ limit = type + 2;
+ else if (Math.abs(extent) <= 3.0 * (Math.PI / 2.0))
+ limit = type + 3;
+ else
+ limit = type + 4;
+ }
+
+ /**
+ * Construct a new iterator over an ellipse.
+ *
+ * @param e the ellipse
+ * @param xform the transform
+ */
+ public ArcIterator(Ellipse2D e, AffineTransform xform)
+ {
+ this.xform = xform;
+ x = e.getX();
+ y = e.getY();
+ w = e.getWidth();
+ h = e.getHeight();
+ start = 0;
+ extent = 2 * Math.PI;
+ type = CHORD;
+ limit = (w < 0 || h < 0) ? -1 : 5;
+ }
+
+ /**
+ * Return the winding rule.
+ *
+ * @return {@link PathIterator#WIND_NON_ZERO}
+ */
+ public int getWindingRule()
+ {
+ return WIND_NON_ZERO;
+ }
+
+ /**
+ * Test if the iteration is complete.
+ *
+ * @return true if more segments exist
+ */
+ public boolean isDone()
+ {
+ return current > limit;
+ }
+
+ /**
+ * Advance the iterator.
+ */
+ public void next()
+ {
+ current++;
+ }
+
+ /**
+ * Put the current segment into the array, and return the segment type.
+ *
+ * @param coords an array of 6 elements
+ * @return the segment type
+ * @throws NullPointerException if coords is null
+ * @throws ArrayIndexOutOfBoundsException if coords is too small
+ */
+ public int currentSegment(float[] coords)
+ {
+ double[] double_coords = new double[6];
+ int code = currentSegment(double_coords);
+ for (int i = 0; i < 6; ++i)
+ coords[i] = (float) double_coords[i];
+ return code;
+ }
+
+ /**
+ * Put the current segment into the array, and return the segment type.
+ *
+ * @param coords an array of 6 elements
+ * @return the segment type
+ * @throws NullPointerException if coords is null
+ * @throws ArrayIndexOutOfBoundsException if coords is too small
+ */
+ public int currentSegment(double[] coords)
+ {
+ double rx = w / 2;
+ double ry = h / 2;
+ double xmid = x + rx;
+ double ymid = y + ry;
+
+ if (current > limit)
+ throw new NoSuchElementException("arc iterator out of bounds");
+
+ if (current == 0)
+ {
+ coords[0] = xmid + rx * Math.cos(start);
+ coords[1] = ymid - ry * Math.sin(start);
+ if (xform != null)
+ xform.transform(coords, 0, coords, 0, 1);
+ return SEG_MOVETO;
+ }
+
+ if (type != OPEN && current == limit)
+ return SEG_CLOSE;
+
+ if ((current == limit - 1) && (type == PIE))
+ {
+ coords[0] = xmid;
+ coords[1] = ymid;
+ if (xform != null)
+ xform.transform(coords, 0, coords, 0, 1);
+ return SEG_LINETO;
+ }
+
+ // note that this produces a cubic approximation of the arc segment,
+ // not a true ellipsoid. there's no ellipsoid path segment code,
+ // unfortunately. the cubic approximation looks about right, though.
+ double kappa = (Math.sqrt(2.0) - 1.0) * (4.0 / 3.0);
+ double quad = (Math.PI / 2.0);
+
+ double curr_begin;
+ double curr_extent;
+ if (extent > 0)
+ {
+ curr_begin = start + (current - 1) * quad;
+ curr_extent = Math.min((start + extent) - curr_begin, quad);
+ }
+ else
+ {
+ curr_begin = start - (current - 1) * quad;
+ curr_extent = Math.max((start + extent) - curr_begin, -quad);
+ }
+
+ double portion_of_a_quadrant = Math.abs(curr_extent / quad);
+
+ double x0 = xmid + rx * Math.cos(curr_begin);
+ double y0 = ymid - ry * Math.sin(curr_begin);
+
+ double x1 = xmid + rx * Math.cos(curr_begin + curr_extent);
+ double y1 = ymid - ry * Math.sin(curr_begin + curr_extent);
+
+ AffineTransform trans = new AffineTransform();
+ double[] cvec = new double[2];
+ double len = kappa * portion_of_a_quadrant;
+ double angle = curr_begin;
+
+ // in a hypothetical "first quadrant" setting, our first control
+ // vector would be sticking up, from [1,0] to [1,kappa].
+ //
+ // let us recall however that in java2d, y coords are upside down
+ // from what one would consider "normal" first quadrant rules, so we
+ // will *subtract* the y value of this control vector from our first
+ // point.
+ cvec[0] = 0;
+ if (extent > 0)
+ cvec[1] = len;
+ else
+ cvec[1] = -len;
+
+ trans.scale(rx, ry);
+ trans.rotate(angle);
+ trans.transform(cvec, 0, cvec, 0, 1);
+ coords[0] = x0 + cvec[0];
+ coords[1] = y0 - cvec[1];
+
+ // control vector #2 would, ideally, be sticking out and to the
+ // right, in a first quadrant arc segment. again, subtraction of y.
+ cvec[0] = 0;
+ if (extent > 0)
+ cvec[1] = -len;
+ else
+ cvec[1] = len;
+
+ trans.rotate(curr_extent);
+ trans.transform(cvec, 0, cvec, 0, 1);
+ coords[2] = x1 + cvec[0];
+ coords[3] = y1 - cvec[1];
+
+ // end point
+ coords[4] = x1;
+ coords[5] = y1;
+
+ if (xform != null)
+ xform.transform(coords, 0, coords, 0, 3);
+
+ return SEG_CUBICTO;
+ }
+ } // class ArcIterator
+
+ /**
+ * This class implements an arc in double precision.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ */
+ public static class Double extends Arc2D
+ {
+ /** The x coordinate of the box bounding the ellipse of this arc. */
+ public double x;
+
+ /** The y coordinate of the box bounding the ellipse of this arc. */
+ public double y;
+
+ /** The width of the box bounding the ellipse of this arc. */
+ public double width;
+
+ /** The height of the box bounding the ellipse of this arc. */
+ public double height;
+
+ /** The start angle of this arc, in degrees. */
+ public double start;
+
+ /** The extent angle of this arc, in degrees. */
+ public double extent;
+
+ /**
+ * Create a new, open arc at (0,0) with 0 extent.
+ */
+ public Double()
+ {
+ super(OPEN);
+ }
+
+ /**
+ * Create a new arc of the given type at (0,0) with 0 extent.
+ *
+ * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
+ * @throws IllegalArgumentException if type is invalid
+ */
+ public Double(int type)
+ {
+ super(type);
+ }
+
+ /**
+ * Create a new arc with the given dimensions.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param w the width
+ * @param h the height
+ * @param start the start angle, in degrees
+ * @param extent the extent, in degrees
+ * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
+ * @throws IllegalArgumentException if type is invalid
+ */
+ public Double(double x, double y, double w, double h, double start,
+ double extent, int type)
+ {
+ super(type);
+ this.x = x;
+ this.y = y;
+ width = w;
+ height = h;
+ this.start = start;
+ this.extent = extent;
+ }
+
+ /**
+ * Create a new arc with the given dimensions.
+ *
+ * @param r the bounding box
+ * @param start the start angle, in degrees
+ * @param extent the extent, in degrees
+ * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
+ * @throws IllegalArgumentException if type is invalid
+ * @throws NullPointerException if r is null
+ */
+ public Double(Rectangle2D r, double start, double extent, int type)
+ {
+ super(type);
+ x = r.getX();
+ y = r.getY();
+ width = r.getWidth();
+ height = r.getHeight();
+ this.start = start;
+ this.extent = extent;
+ }
+
+ /**
+ * Return the x coordinate of the bounding box.
+ *
+ * @return the value of x
+ */
+ public double getX()
+ {
+ return x;
+ }
+
+ /**
+ * Return the y coordinate of the bounding box.
+ *
+ * @return the value of y
+ */
+ public double getY()
+ {
+ return y;
+ }
+
+ /**
+ * Return the width of the bounding box.
+ *
+ * @return the value of width
+ */
+ public double getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Return the height of the bounding box.
+ *
+ * @return the value of height
+ */
+ public double getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * Return the start angle of the arc, in degrees.
+ *
+ * @return the value of start
+ */
+ public double getAngleStart()
+ {
+ return start;
+ }
+
+ /**
+ * Return the extent of the arc, in degrees.
+ *
+ * @return the value of extent
+ */
+ public double getAngleExtent()
+ {
+ return extent;
+ }
+
+ /**
+ * Tests if the arc contains points.
+ *
+ * @return true if the arc has no interior
+ */
+ public boolean isEmpty()
+ {
+ return width <= 0 || height <= 0;
+ }
+
+ /**
+ * Sets the arc to the given dimensions.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param w the width
+ * @param h the height
+ * @param start the start angle, in degrees
+ * @param extent the extent, in degrees
+ * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
+ * @throws IllegalArgumentException if type is invalid
+ */
+ public void setArc(double x, double y, double w, double h, double start,
+ double extent, int type)
+ {
+ this.x = x;
+ this.y = y;
+ width = w;
+ height = h;
+ this.start = start;
+ this.extent = extent;
+ setArcType(type);
+ }
+
+ /**
+ * Sets the start angle of the arc.
+ *
+ * @param start the new start angle
+ */
+ public void setAngleStart(double start)
+ {
+ this.start = start;
+ }
+
+ /**
+ * Sets the extent angle of the arc.
+ *
+ * @param extent the new extent angle
+ */
+ public void setAngleExtent(double extent)
+ {
+ this.extent = extent;
+ }
+
+ /**
+ * Creates a tight bounding box given dimensions that more precise than
+ * the bounding box of the ellipse.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param w the width
+ * @param h the height
+ */
+ protected Rectangle2D makeBounds(double x, double y, double w, double h)
+ {
+ return new Rectangle2D.Double(x, y, w, h);
+ }
+ } // class Double
+
+ /**
+ * This class implements an arc in float precision.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ */
+ public static class Float extends Arc2D
+ {
+ /** The x coordinate of the box bounding the ellipse of this arc. */
+ public float x;
+
+ /** The y coordinate of the box bounding the ellipse of this arc. */
+ public float y;
+
+ /** The width of the box bounding the ellipse of this arc. */
+ public float width;
+
+ /** The height of the box bounding the ellipse of this arc. */
+ public float height;
+
+ /** The start angle of this arc, in degrees. */
+ public float start;
+
+ /** The extent angle of this arc, in degrees. */
+ public float extent;
+
+ /**
+ * Create a new, open arc at (0,0) with 0 extent.
+ */
+ public Float()
+ {
+ super(OPEN);
+ }
+
+ /**
+ * Create a new arc of the given type at (0,0) with 0 extent.
+ *
+ * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
+ * @throws IllegalArgumentException if type is invalid
+ */
+ public Float(int type)
+ {
+ super(type);
+ }
+
+ /**
+ * Create a new arc with the given dimensions.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param w the width
+ * @param h the height
+ * @param start the start angle, in degrees
+ * @param extent the extent, in degrees
+ * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
+ * @throws IllegalArgumentException if type is invalid
+ */
+ public Float(float x, float y, float w, float h, float start,
+ float extent, int type)
+ {
+ super(type);
+ this.x = x;
+ this.y = y;
+ width = w;
+ height = h;
+ this.start = start;
+ this.extent = extent;
+ }
+
+ /**
+ * Create a new arc with the given dimensions.
+ *
+ * @param r the bounding box
+ * @param start the start angle, in degrees
+ * @param extent the extent, in degrees
+ * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
+ * @throws IllegalArgumentException if type is invalid
+ * @throws NullPointerException if r is null
+ */
+ public Float(Rectangle2D r, float start, float extent, int type)
+ {
+ super(type);
+ x = (float) r.getX();
+ y = (float) r.getY();
+ width = (float) r.getWidth();
+ height = (float) r.getHeight();
+ this.start = start;
+ this.extent = extent;
+ }
+
+ /**
+ * Return the x coordinate of the bounding box.
+ *
+ * @return the value of x
+ */
+ public double getX()
+ {
+ return x;
+ }
+
+ /**
+ * Return the y coordinate of the bounding box.
+ *
+ * @return the value of y
+ */
+ public double getY()
+ {
+ return y;
+ }
+
+ /**
+ * Return the width of the bounding box.
+ *
+ * @return the value of width
+ */
+ public double getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Return the height of the bounding box.
+ *
+ * @return the value of height
+ */
+ public double getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * Return the start angle of the arc, in degrees.
+ *
+ * @return the value of start
+ */
+ public double getAngleStart()
+ {
+ return start;
+ }
+
+ /**
+ * Return the extent of the arc, in degrees.
+ *
+ * @return the value of extent
+ */
+ public double getAngleExtent()
+ {
+ return extent;
+ }
+
+ /**
+ * Tests if the arc contains points.
+ *
+ * @return true if the arc has no interior
+ */
+ public boolean isEmpty()
+ {
+ return width <= 0 || height <= 0;
+ }
+
+ /**
+ * Sets the arc to the given dimensions.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param w the width
+ * @param h the height
+ * @param start the start angle, in degrees
+ * @param extent the extent, in degrees
+ * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE}
+ * @throws IllegalArgumentException if type is invalid
+ */
+ public void setArc(double x, double y, double w, double h, double start,
+ double extent, int type)
+ {
+ this.x = (float) x;
+ this.y = (float) y;
+ width = (float) w;
+ height = (float) h;
+ this.start = (float) start;
+ this.extent = (float) extent;
+ setArcType(type);
+ }
+
+ /**
+ * Sets the start angle of the arc.
+ *
+ * @param start the new start angle
+ */
+ public void setAngleStart(double start)
+ {
+ this.start = (float) start;
+ }
+
+ /**
+ * Sets the extent angle of the arc.
+ *
+ * @param extent the new extent angle
+ */
+ public void setAngleExtent(double extent)
+ {
+ this.extent = (float) extent;
+ }
+
+ /**
+ * Creates a tight bounding box given dimensions that more precise than
+ * the bounding box of the ellipse.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param w the width
+ * @param h the height
+ */
+ protected Rectangle2D makeBounds(double x, double y, double w, double h)
+ {
+ return new Rectangle2D.Float((float) x, (float) y, (float) w, (float) h);
+ }
+ } // class Float
+} // class Arc2D
diff --git a/libjava/classpath/java/awt/geom/Area.java b/libjava/classpath/java/awt/geom/Area.java
new file mode 100644
index 000000000..a1eaf63f3
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/Area.java
@@ -0,0 +1,3312 @@
+/* Area.java -- represents a shape built by constructive area geometry
+ Copyright (C) 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.geom;
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.util.Vector;
+
+
+/**
+ * The Area class represents any area for the purpose of
+ * Constructive Area Geometry (CAG) manipulations. CAG manipulations
+ * work as an area-wise form of boolean logic, where the basic operations are:
+ * <P><li>Add (in boolean algebra: A <B>or</B> B)<BR>
+ * <li>Subtract (in boolean algebra: A <B>and</B> (<B>not</B> B) )<BR>
+ * <li>Intersect (in boolean algebra: A <B>and</B> B)<BR>
+ * <li>Exclusive Or <BR>
+ * <img src="doc-files/Area-1.png" width="342" height="302"
+ * alt="Illustration of CAG operations" /><BR>
+ * Above is an illustration of the CAG operations on two ring shapes.<P>
+ *
+ * The contains and intersects() methods are also more accurate than the
+ * specification of #Shape requires.<P>
+ *
+ * Please note that constructing an Area can be slow
+ * (Self-intersection resolving is proportional to the square of
+ * the number of segments).<P>
+ * @see #add(Area)
+ * @see #subtract(Area)
+ * @see #intersect(Area)
+ * @see #exclusiveOr(Area)
+ *
+ * @author Sven de Marothy (sven@physto.se)
+ *
+ * @since 1.2
+ * @status Works, but could be faster and more reliable.
+ */
+public class Area implements Shape, Cloneable
+{
+ /**
+ * General numerical precision
+ */
+ private static final double EPSILON = 1E-11;
+
+ /**
+ * recursive subdivision epsilon - (see getRecursionDepth)
+ */
+ private static final double RS_EPSILON = 1E-13;
+
+ /**
+ * Snap distance - points within this distance are considered equal
+ */
+ private static final double PE_EPSILON = 1E-11;
+
+ /**
+ * Segment vectors containing solid areas and holes
+ * This is package-private to avoid an accessor method.
+ */
+ Vector solids;
+
+ /**
+ * Segment vectors containing solid areas and holes
+ * This is package-private to avoid an accessor method.
+ */
+ Vector holes;
+
+ /**
+ * Vector (temporary) storing curve-curve intersections
+ */
+ private Vector cc_intersections;
+
+ /**
+ * Winding rule WIND_NON_ZERO used, after construction,
+ * this is irrelevant.
+ */
+ private int windingRule;
+
+ /**
+ * Constructs an empty Area
+ */
+ public Area()
+ {
+ solids = new Vector();
+ holes = new Vector();
+ }
+
+ /**
+ * Constructs an Area from any given Shape. <P>
+ *
+ * If the Shape is self-intersecting, the created Area will consist
+ * of non-self-intersecting subpaths, and any inner paths which
+ * are found redundant in accordance with the Shape's winding rule
+ * will not be included.
+ *
+ * @param s the shape (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>s</code> is <code>null</code>.
+ */
+ public Area(Shape s)
+ {
+ this();
+
+ Vector p = makeSegment(s);
+
+ // empty path
+ if (p == null)
+ return;
+
+ // delete empty paths
+ for (int i = 0; i < p.size(); i++)
+ if (((Segment) p.elementAt(i)).getSignedArea() == 0.0)
+ p.remove(i--);
+
+ /*
+ * Resolve self intersecting paths into non-intersecting
+ * solids and holes.
+ * Algorithm is as follows:
+ * 1: Create nodes at all self intersections
+ * 2: Put all segments into a list
+ * 3: Grab a segment, follow it, change direction at each node,
+ * removing segments from the list in the process
+ * 4: Repeat (3) until no segments remain in the list
+ * 5: Remove redundant paths and sort into solids and holes
+ */
+ Vector paths = new Vector();
+ Segment v;
+
+ for (int i = 0; i < p.size(); i++)
+ {
+ Segment path = (Segment) p.elementAt(i);
+ createNodesSelf(path);
+ }
+
+ if (p.size() > 1)
+ {
+ for (int i = 0; i < p.size() - 1; i++)
+ for (int j = i + 1; j < p.size(); j++)
+ {
+ Segment path1 = (Segment) p.elementAt(i);
+ Segment path2 = (Segment) p.elementAt(j);
+ createNodes(path1, path2);
+ }
+ }
+
+ // we have intersecting points.
+ Vector segments = new Vector();
+
+ for (int i = 0; i < p.size(); i++)
+ {
+ Segment path = v = (Segment) p.elementAt(i);
+ do
+ {
+ segments.add(v);
+ v = v.next;
+ }
+ while (v != path);
+ }
+
+ paths = weilerAtherton(segments);
+ deleteRedundantPaths(paths);
+ }
+
+ /**
+ * Performs an add (union) operation on this area with another Area.<BR>
+ * @param area - the area to be unioned with this one
+ */
+ public void add(Area area)
+ {
+ if (equals(area))
+ return;
+ if (area.isEmpty())
+ return;
+
+ Area B = (Area) area.clone();
+
+ Vector pathA = new Vector();
+ Vector pathB = new Vector();
+ pathA.addAll(solids);
+ pathA.addAll(holes);
+ pathB.addAll(B.solids);
+ pathB.addAll(B.holes);
+
+ int nNodes = 0;
+
+ for (int i = 0; i < pathA.size(); i++)
+ {
+ Segment a = (Segment) pathA.elementAt(i);
+ for (int j = 0; j < pathB.size(); j++)
+ {
+ Segment b = (Segment) pathB.elementAt(j);
+ nNodes += createNodes(a, b);
+ }
+ }
+
+ Vector paths = new Vector();
+ Segment v;
+
+ // we have intersecting points.
+ Vector segments = new Vector();
+
+ // In a union operation, we keep all
+ // segments of A oustide B and all B outside A
+ for (int i = 0; i < pathA.size(); i++)
+ {
+ v = (Segment) pathA.elementAt(i);
+ Segment path = v;
+ do
+ {
+ if (v.isSegmentOutside(area))
+ segments.add(v);
+ v = v.next;
+ }
+ while (v != path);
+ }
+
+ for (int i = 0; i < pathB.size(); i++)
+ {
+ v = (Segment) pathB.elementAt(i);
+ Segment path = v;
+ do
+ {
+ if (v.isSegmentOutside(this))
+ segments.add(v);
+ v = v.next;
+ }
+ while (v != path);
+ }
+
+ paths = weilerAtherton(segments);
+ deleteRedundantPaths(paths);
+ }
+
+ /**
+ * Performs a subtraction operation on this Area.<BR>
+ * @param area the area to be subtracted from this area.
+ * @throws NullPointerException if <code>area</code> is <code>null</code>.
+ */
+ public void subtract(Area area)
+ {
+ if (isEmpty() || area.isEmpty())
+ return;
+
+ if (equals(area))
+ {
+ reset();
+ return;
+ }
+
+ Vector pathA = new Vector();
+ Area B = (Area) area.clone();
+ pathA.addAll(solids);
+ pathA.addAll(holes);
+
+ // reverse the directions of B paths.
+ setDirection(B.holes, true);
+ setDirection(B.solids, false);
+
+ Vector pathB = new Vector();
+ pathB.addAll(B.solids);
+ pathB.addAll(B.holes);
+
+ int nNodes = 0;
+
+ // create nodes
+ for (int i = 0; i < pathA.size(); i++)
+ {
+ Segment a = (Segment) pathA.elementAt(i);
+ for (int j = 0; j < pathB.size(); j++)
+ {
+ Segment b = (Segment) pathB.elementAt(j);
+ nNodes += createNodes(a, b);
+ }
+ }
+
+ Vector paths = new Vector();
+
+ // we have intersecting points.
+ Vector segments = new Vector();
+
+ // In a subtraction operation, we keep all
+ // segments of A oustide B and all B within A
+ // We outsideness-test only one segment in each path
+ // and the segments before and after any node
+ for (int i = 0; i < pathA.size(); i++)
+ {
+ Segment v = (Segment) pathA.elementAt(i);
+ Segment path = v;
+ if (v.isSegmentOutside(area) && v.node == null)
+ segments.add(v);
+ boolean node = false;
+ do
+ {
+ if ((v.node != null || node))
+ {
+ node = (v.node != null);
+ if (v.isSegmentOutside(area))
+ segments.add(v);
+ }
+ v = v.next;
+ }
+ while (v != path);
+ }
+
+ for (int i = 0; i < pathB.size(); i++)
+ {
+ Segment v = (Segment) pathB.elementAt(i);
+ Segment path = v;
+ if (! v.isSegmentOutside(this) && v.node == null)
+ segments.add(v);
+ v = v.next;
+ boolean node = false;
+ do
+ {
+ if ((v.node != null || node))
+ {
+ node = (v.node != null);
+ if (! v.isSegmentOutside(this))
+ segments.add(v);
+ }
+ v = v.next;
+ }
+ while (v != path);
+ }
+
+ paths = weilerAtherton(segments);
+ deleteRedundantPaths(paths);
+ }
+
+ /**
+ * Performs an intersection operation on this Area.<BR>
+ * @param area - the area to be intersected with this area.
+ * @throws NullPointerException if <code>area</code> is <code>null</code>.
+ */
+ public void intersect(Area area)
+ {
+ if (isEmpty() || area.isEmpty())
+ {
+ reset();
+ return;
+ }
+ if (equals(area))
+ return;
+
+ Vector pathA = new Vector();
+ Area B = (Area) area.clone();
+ pathA.addAll(solids);
+ pathA.addAll(holes);
+
+ Vector pathB = new Vector();
+ pathB.addAll(B.solids);
+ pathB.addAll(B.holes);
+
+ int nNodes = 0;
+
+ // create nodes
+ for (int i = 0; i < pathA.size(); i++)
+ {
+ Segment a = (Segment) pathA.elementAt(i);
+ for (int j = 0; j < pathB.size(); j++)
+ {
+ Segment b = (Segment) pathB.elementAt(j);
+ nNodes += createNodes(a, b);
+ }
+ }
+
+ Vector paths = new Vector();
+
+ // we have intersecting points.
+ Vector segments = new Vector();
+
+ // In an intersection operation, we keep all
+ // segments of A within B and all B within A
+ // (The rest must be redundant)
+ // We outsideness-test only one segment in each path
+ // and the segments before and after any node
+ for (int i = 0; i < pathA.size(); i++)
+ {
+ Segment v = (Segment) pathA.elementAt(i);
+ Segment path = v;
+ if (! v.isSegmentOutside(area) && v.node == null)
+ segments.add(v);
+ boolean node = false;
+ do
+ {
+ if ((v.node != null || node))
+ {
+ node = (v.node != null);
+ if (! v.isSegmentOutside(area))
+ segments.add(v);
+ }
+ v = v.next;
+ }
+ while (v != path);
+ }
+
+ for (int i = 0; i < pathB.size(); i++)
+ {
+ Segment v = (Segment) pathB.elementAt(i);
+ Segment path = v;
+ if (! v.isSegmentOutside(this) && v.node == null)
+ segments.add(v);
+ v = v.next;
+ boolean node = false;
+ do
+ {
+ if ((v.node != null || node))
+ {
+ node = (v.node != null);
+ if (! v.isSegmentOutside(this))
+ segments.add(v);
+ }
+ v = v.next;
+ }
+ while (v != path);
+ }
+
+ paths = weilerAtherton(segments);
+ deleteRedundantPaths(paths);
+ }
+
+ /**
+ * Performs an exclusive-or operation on this Area.<BR>
+ * @param area - the area to be XORed with this area.
+ * @throws NullPointerException if <code>area</code> is <code>null</code>.
+ */
+ public void exclusiveOr(Area area)
+ {
+ if (area.isEmpty())
+ return;
+
+ if (isEmpty())
+ {
+ Area B = (Area) area.clone();
+ solids = B.solids;
+ holes = B.holes;
+ return;
+ }
+ if (equals(area))
+ {
+ reset();
+ return;
+ }
+
+ Vector pathA = new Vector();
+
+ Area B = (Area) area.clone();
+ Vector pathB = new Vector();
+ pathA.addAll(solids);
+ pathA.addAll(holes);
+
+ // reverse the directions of B paths.
+ setDirection(B.holes, true);
+ setDirection(B.solids, false);
+ pathB.addAll(B.solids);
+ pathB.addAll(B.holes);
+
+ int nNodes = 0;
+
+ for (int i = 0; i < pathA.size(); i++)
+ {
+ Segment a = (Segment) pathA.elementAt(i);
+ for (int j = 0; j < pathB.size(); j++)
+ {
+ Segment b = (Segment) pathB.elementAt(j);
+ nNodes += createNodes(a, b);
+ }
+ }
+
+ Vector paths = new Vector();
+ Segment v;
+
+ // we have intersecting points.
+ Vector segments = new Vector();
+
+ // In an XOR operation, we operate on all segments
+ for (int i = 0; i < pathA.size(); i++)
+ {
+ v = (Segment) pathA.elementAt(i);
+ Segment path = v;
+ do
+ {
+ segments.add(v);
+ v = v.next;
+ }
+ while (v != path);
+ }
+
+ for (int i = 0; i < pathB.size(); i++)
+ {
+ v = (Segment) pathB.elementAt(i);
+ Segment path = v;
+ do
+ {
+ segments.add(v);
+ v = v.next;
+ }
+ while (v != path);
+ }
+
+ paths = weilerAtherton(segments);
+ deleteRedundantPaths(paths);
+ }
+
+ /**
+ * Clears the Area object, creating an empty area.
+ */
+ public void reset()
+ {
+ solids = new Vector();
+ holes = new Vector();
+ }
+
+ /**
+ * Returns whether this area encloses any area.
+ * @return true if the object encloses any area.
+ */
+ public boolean isEmpty()
+ {
+ if (solids.size() == 0)
+ return true;
+
+ double totalArea = 0;
+ for (int i = 0; i < solids.size(); i++)
+ totalArea += Math.abs(((Segment) solids.elementAt(i)).getSignedArea());
+ for (int i = 0; i < holes.size(); i++)
+ totalArea -= Math.abs(((Segment) holes.elementAt(i)).getSignedArea());
+ if (totalArea <= EPSILON)
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Determines whether the Area consists entirely of line segments
+ * @return true if the Area lines-only, false otherwise
+ */
+ public boolean isPolygonal()
+ {
+ for (int i = 0; i < holes.size(); i++)
+ if (! ((Segment) holes.elementAt(i)).isPolygonal())
+ return false;
+ for (int i = 0; i < solids.size(); i++)
+ if (! ((Segment) solids.elementAt(i)).isPolygonal())
+ return false;
+ return true;
+ }
+
+ /**
+ * Determines if the Area is rectangular.<P>
+ *
+ * This is strictly qualified. An area is considered rectangular if:<BR>
+ * <li>It consists of a single polygonal path.<BR>
+ * <li>It is oriented parallel/perpendicular to the xy axis<BR>
+ * <li>It must be exactly rectangular, i.e. small errors induced by
+ * transformations may cause a false result, although the area is
+ * visibly rectangular.<P>
+ * @return true if the above criteria are met, false otherwise
+ */
+ public boolean isRectangular()
+ {
+ if (isEmpty())
+ return true;
+
+ if (holes.size() != 0 || solids.size() != 1)
+ return false;
+
+ Segment path = (Segment) solids.elementAt(0);
+ if (! path.isPolygonal())
+ return false;
+
+ int nCorners = 0;
+ Segment s = path;
+ do
+ {
+ Segment s2 = s.next;
+ double d1 = (s.P2.getX() - s.P1.getX())*(s2.P2.getX() - s2.P1.getX())/
+ ((s.P1.distance(s.P2)) * (s2.P1.distance(s2.P2)));
+ double d2 = (s.P2.getY() - s.P1.getY())*(s2.P2.getY() - s2.P1.getY())/
+ ((s.P1.distance(s.P2)) * (s2.P1.distance(s2.P2)));
+ double dotproduct = d1 + d2;
+
+ // For some reason, only rectangles on the XY axis count.
+ if (d1 != 0 && d2 != 0)
+ return false;
+
+ if (Math.abs(dotproduct) == 0) // 90 degree angle
+ nCorners++;
+ else if ((Math.abs(1.0 - dotproduct) > 0)) // 0 degree angle?
+ return false; // if not, return false
+
+ s = s.next;
+ }
+ while (s != path);
+
+ return nCorners == 4;
+ }
+
+ /**
+ * Returns whether the Area consists of more than one simple
+ * (non self-intersecting) subpath.
+ *
+ * @return true if the Area consists of none or one simple subpath,
+ * false otherwise.
+ */
+ public boolean isSingular()
+ {
+ return (holes.size() == 0 && solids.size() <= 1);
+ }
+
+ /**
+ * Returns the bounding box of the Area.<P> Unlike the CubicCurve2D and
+ * QuadraticCurve2D classes, this method will return the tightest possible
+ * bounding box, evaluating the extreme points of each curved segment.<P>
+ * @return the bounding box
+ */
+ public Rectangle2D getBounds2D()
+ {
+ if (solids.size() == 0)
+ return new Rectangle2D.Double(0.0, 0.0, 0.0, 0.0);
+
+ double xmin;
+ double xmax;
+ double ymin;
+ double ymax;
+ xmin = xmax = ((Segment) solids.elementAt(0)).P1.getX();
+ ymin = ymax = ((Segment) solids.elementAt(0)).P1.getY();
+
+ for (int path = 0; path < solids.size(); path++)
+ {
+ Rectangle2D r = ((Segment) solids.elementAt(path)).getPathBounds();
+ xmin = Math.min(r.getMinX(), xmin);
+ ymin = Math.min(r.getMinY(), ymin);
+ xmax = Math.max(r.getMaxX(), xmax);
+ ymax = Math.max(r.getMaxY(), ymax);
+ }
+
+ return (new Rectangle2D.Double(xmin, ymin, (xmax - xmin), (ymax - ymin)));
+ }
+
+ /**
+ * Returns the bounds of this object in Rectangle format.
+ * Please note that this may lead to loss of precision.
+ *
+ * @return The bounds.
+ * @see #getBounds2D()
+ */
+ public Rectangle getBounds()
+ {
+ return getBounds2D().getBounds();
+ }
+
+ /**
+ * Create a new area of the same run-time type with the same contents as
+ * this one.
+ *
+ * @return the clone
+ */
+ public Object clone()
+ {
+ try
+ {
+ Area clone = new Area();
+ for (int i = 0; i < solids.size(); i++)
+ clone.solids.add(((Segment) solids.elementAt(i)).cloneSegmentList());
+ for (int i = 0; i < holes.size(); i++)
+ clone.holes.add(((Segment) holes.elementAt(i)).cloneSegmentList());
+ return clone;
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // Impossible
+ }
+ }
+
+ /**
+ * Compares two Areas.
+ *
+ * @param area the area to compare against this area (<code>null</code>
+ * permitted).
+ * @return <code>true</code> if the areas are equal, and <code>false</code>
+ * otherwise.
+ */
+ public boolean equals(Area area)
+ {
+ if (area == null)
+ return false;
+
+ if (! getBounds2D().equals(area.getBounds2D()))
+ return false;
+
+ if (solids.size() != area.solids.size()
+ || holes.size() != area.holes.size())
+ return false;
+
+ Vector pathA = new Vector();
+ pathA.addAll(solids);
+ pathA.addAll(holes);
+ Vector pathB = new Vector();
+ pathB.addAll(area.solids);
+ pathB.addAll(area.holes);
+
+ int nPaths = pathA.size();
+ boolean[][] match = new boolean[2][nPaths];
+
+ for (int i = 0; i < nPaths; i++)
+ {
+ for (int j = 0; j < nPaths; j++)
+ {
+ Segment p1 = (Segment) pathA.elementAt(i);
+ Segment p2 = (Segment) pathB.elementAt(j);
+ if (! match[0][i] && ! match[1][j])
+ if (p1.pathEquals(p2))
+ match[0][i] = match[1][j] = true;
+ }
+ }
+
+ boolean result = true;
+ for (int i = 0; i < nPaths; i++)
+ result = result && match[0][i] && match[1][i];
+ return result;
+ }
+
+ /**
+ * Transforms this area by the AffineTransform at.
+ *
+ * @param at the transform.
+ */
+ public void transform(AffineTransform at)
+ {
+ for (int i = 0; i < solids.size(); i++)
+ ((Segment) solids.elementAt(i)).transformSegmentList(at);
+ for (int i = 0; i < holes.size(); i++)
+ ((Segment) holes.elementAt(i)).transformSegmentList(at);
+
+ // Note that the orientation is not invariant under inversion
+ if ((at.getType() & AffineTransform.TYPE_FLIP) != 0)
+ {
+ setDirection(holes, false);
+ setDirection(solids, true);
+ }
+ }
+
+ /**
+ * Returns a new Area equal to this one, transformed
+ * by the AffineTransform at.
+ * @param at the transform.
+ * @return the transformed area
+ * @throws NullPointerException if <code>at</code> is <code>null</code>.
+ */
+ public Area createTransformedArea(AffineTransform at)
+ {
+ Area a = (Area) clone();
+ a.transform(at);
+ return a;
+ }
+
+ /**
+ * Determines if the point (x,y) is contained within this Area.
+ *
+ * @param x the x-coordinate of the point.
+ * @param y the y-coordinate of the point.
+ * @return true if the point is contained, false otherwise.
+ */
+ public boolean contains(double x, double y)
+ {
+ int n = 0;
+ for (int i = 0; i < solids.size(); i++)
+ if (((Segment) solids.elementAt(i)).contains(x, y))
+ n++;
+
+ for (int i = 0; i < holes.size(); i++)
+ if (((Segment) holes.elementAt(i)).contains(x, y))
+ n--;
+
+ return (n != 0);
+ }
+
+ /**
+ * Determines if the Point2D p is contained within this Area.
+ *
+ * @param p the point.
+ * @return <code>true</code> if the point is contained, <code>false</code>
+ * otherwise.
+ * @throws NullPointerException if <code>p</code> is <code>null</code>.
+ */
+ public boolean contains(Point2D p)
+ {
+ return contains(p.getX(), p.getY());
+ }
+
+ /**
+ * Determines if the rectangle specified by (x,y) as the upper-left
+ * and with width w and height h is completely contained within this Area,
+ * returns false otherwise.<P>
+ *
+ * This method should always produce the correct results, unlike for other
+ * classes in geom.
+ *
+ * @param x the x-coordinate of the rectangle.
+ * @param y the y-coordinate of the rectangle.
+ * @param w the width of the the rectangle.
+ * @param h the height of the rectangle.
+ * @return <code>true</code> if the rectangle is considered contained
+ */
+ public boolean contains(double x, double y, double w, double h)
+ {
+ LineSegment[] l = new LineSegment[4];
+ l[0] = new LineSegment(x, y, x + w, y);
+ l[1] = new LineSegment(x, y + h, x + w, y + h);
+ l[2] = new LineSegment(x, y, x, y + h);
+ l[3] = new LineSegment(x + w, y, x + w, y + h);
+
+ // Since every segment in the area must a contour
+ // between inside/outside segments, ANY intersection
+ // will mean the rectangle is not entirely contained.
+ for (int i = 0; i < 4; i++)
+ {
+ for (int path = 0; path < solids.size(); path++)
+ {
+ Segment v;
+ Segment start;
+ start = v = (Segment) solids.elementAt(path);
+ do
+ {
+ if (l[i].hasIntersections(v))
+ return false;
+ v = v.next;
+ }
+ while (v != start);
+ }
+ for (int path = 0; path < holes.size(); path++)
+ {
+ Segment v;
+ Segment start;
+ start = v = (Segment) holes.elementAt(path);
+ do
+ {
+ if (l[i].hasIntersections(v))
+ return false;
+ v = v.next;
+ }
+ while (v != start);
+ }
+ }
+
+ // Is any point inside?
+ if (! contains(x, y))
+ return false;
+
+ // Final hoop: Is the rectangle non-intersecting and inside,
+ // but encloses a hole?
+ Rectangle2D r = new Rectangle2D.Double(x, y, w, h);
+ for (int path = 0; path < holes.size(); path++)
+ if (! ((Segment) holes.elementAt(path)).isSegmentOutside(r))
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Determines if the Rectangle2D specified by r is completely contained
+ * within this Area, returns false otherwise.<P>
+ *
+ * This method should always produce the correct results, unlike for other
+ * classes in geom.
+ *
+ * @param r the rectangle.
+ * @return <code>true</code> if the rectangle is considered contained
+ *
+ * @throws NullPointerException if <code>r</code> is <code>null</code>.
+ */
+ public boolean contains(Rectangle2D r)
+ {
+ return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Determines if the rectangle specified by (x,y) as the upper-left
+ * and with width w and height h intersects any part of this Area.
+ *
+ * @param x the x-coordinate for the rectangle.
+ * @param y the y-coordinate for the rectangle.
+ * @param w the width of the rectangle.
+ * @param h the height of the rectangle.
+ * @return <code>true</code> if the rectangle intersects the area,
+ * <code>false</code> otherwise.
+ */
+ public boolean intersects(double x, double y, double w, double h)
+ {
+ if (solids.size() == 0)
+ return false;
+
+ LineSegment[] l = new LineSegment[4];
+ l[0] = new LineSegment(x, y, x + w, y);
+ l[1] = new LineSegment(x, y + h, x + w, y + h);
+ l[2] = new LineSegment(x, y, x, y + h);
+ l[3] = new LineSegment(x + w, y, x + w, y + h);
+
+ // Return true on any intersection
+ for (int i = 0; i < 4; i++)
+ {
+ for (int path = 0; path < solids.size(); path++)
+ {
+ Segment v;
+ Segment start;
+ start = v = (Segment) solids.elementAt(path);
+ do
+ {
+ if (l[i].hasIntersections(v))
+ return true;
+ v = v.next;
+ }
+ while (v != start);
+ }
+ for (int path = 0; path < holes.size(); path++)
+ {
+ Segment v;
+ Segment start;
+ start = v = (Segment) holes.elementAt(path);
+ do
+ {
+ if (l[i].hasIntersections(v))
+ return true;
+ v = v.next;
+ }
+ while (v != start);
+ }
+ }
+
+ // Non-intersecting, Is any point inside?
+ if (contains(x + w * 0.5, y + h * 0.5))
+ return true;
+
+ // What if the rectangle encloses the whole shape?
+ Point2D p = ((Segment) solids.elementAt(0)).getMidPoint();
+ if ((new Rectangle2D.Double(x, y, w, h)).contains(p))
+ return true;
+ return false;
+ }
+
+ /**
+ * Determines if the Rectangle2D specified by r intersects any
+ * part of this Area.
+ * @param r the rectangle to test intersection with (<code>null</code>
+ * not permitted).
+ * @return <code>true</code> if the rectangle intersects the area,
+ * <code>false</code> otherwise.
+ * @throws NullPointerException if <code>r</code> is <code>null</code>.
+ */
+ public boolean intersects(Rectangle2D r)
+ {
+ return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Returns a PathIterator object defining the contour of this Area,
+ * transformed by at.
+ *
+ * @param at the transform.
+ * @return A path iterator.
+ */
+ public PathIterator getPathIterator(AffineTransform at)
+ {
+ return (new AreaIterator(at));
+ }
+
+ /**
+ * Returns a flattened PathIterator object defining the contour of this
+ * Area, transformed by at and with a defined flatness.
+ *
+ * @param at the transform.
+ * @param flatness the flatness.
+ * @return A path iterator.
+ */
+ public PathIterator getPathIterator(AffineTransform at, double flatness)
+ {
+ return new FlatteningPathIterator(getPathIterator(at), flatness);
+ }
+
+ //---------------------------------------------------------------------
+ // Non-public methods and classes
+
+ /**
+ * Private pathiterator object.
+ */
+ private class AreaIterator implements PathIterator
+ {
+ private Vector segments;
+ private int index;
+ private AffineTransform at;
+
+ // Simple compound type for segments
+ class IteratorSegment
+ {
+ int type;
+ double[] coords;
+
+ IteratorSegment()
+ {
+ coords = new double[6];
+ }
+ }
+
+ /**
+ * The contructor here does most of the work,
+ * creates a vector of IteratorSegments, which can
+ * readily be returned
+ */
+ public AreaIterator(AffineTransform at)
+ {
+ this.at = at;
+ index = 0;
+ segments = new Vector();
+ Vector allpaths = new Vector();
+ allpaths.addAll(solids);
+ allpaths.addAll(holes);
+
+ for (int i = 0; i < allpaths.size(); i++)
+ {
+ Segment v = (Segment) allpaths.elementAt(i);
+ Segment start = v;
+
+ IteratorSegment is = new IteratorSegment();
+ is.type = SEG_MOVETO;
+ is.coords[0] = start.P1.getX();
+ is.coords[1] = start.P1.getY();
+ segments.add(is);
+
+ do
+ {
+ is = new IteratorSegment();
+ is.type = v.pathIteratorFormat(is.coords);
+ segments.add(is);
+ v = v.next;
+ }
+ while (v != start);
+
+ is = new IteratorSegment();
+ is.type = SEG_CLOSE;
+ segments.add(is);
+ }
+ }
+
+ public int currentSegment(double[] coords)
+ {
+ IteratorSegment s = (IteratorSegment) segments.elementAt(index);
+ if (at != null)
+ at.transform(s.coords, 0, coords, 0, 3);
+ else
+ for (int i = 0; i < 6; i++)
+ coords[i] = s.coords[i];
+ return (s.type);
+ }
+
+ public int currentSegment(float[] coords)
+ {
+ IteratorSegment s = (IteratorSegment) segments.elementAt(index);
+ double[] d = new double[6];
+ if (at != null)
+ {
+ at.transform(s.coords, 0, d, 0, 3);
+ for (int i = 0; i < 6; i++)
+ coords[i] = (float) d[i];
+ }
+ else
+ for (int i = 0; i < 6; i++)
+ coords[i] = (float) s.coords[i];
+ return (s.type);
+ }
+
+ // Note that the winding rule should not matter here,
+ // EVEN_ODD is chosen because it renders faster.
+ public int getWindingRule()
+ {
+ return (PathIterator.WIND_EVEN_ODD);
+ }
+
+ public boolean isDone()
+ {
+ return (index >= segments.size());
+ }
+
+ public void next()
+ {
+ index++;
+ }
+ }
+
+ /**
+ * Performs the fundamental task of the Weiler-Atherton algorithm,
+ * traverse a list of segments, for each segment:
+ * Follow it, removing segments from the list and switching paths
+ * at each node. Do so until the starting segment is reached.
+ *
+ * Returns a Vector of the resulting paths.
+ */
+ private Vector weilerAtherton(Vector segments)
+ {
+ Vector paths = new Vector();
+ while (segments.size() > 0)
+ {
+ // Iterate over the path
+ Segment start = (Segment) segments.elementAt(0);
+ Segment s = start;
+ do
+ {
+ segments.remove(s);
+ if (s.node != null)
+ { // switch over
+ s.next = s.node;
+ s.node = null;
+ }
+ s = s.next; // continue
+ }
+ while (s != start);
+
+ paths.add(start);
+ }
+ return paths;
+ }
+
+ /**
+ * A small wrapper class to store intersection points
+ */
+ private class Intersection
+ {
+ Point2D p; // the 2D point of intersection
+ double ta; // the parametric value on a
+ double tb; // the parametric value on b
+ Segment seg; // segment placeholder for node setting
+
+ public Intersection(Point2D p, double ta, double tb)
+ {
+ this.p = p;
+ this.ta = ta;
+ this.tb = tb;
+ }
+ }
+
+ /**
+ * Returns the recursion depth necessary to approximate the
+ * curve by line segments within the error RS_EPSILON.
+ *
+ * This is done with Wang's formula:
+ * L0 = max{0<=i<=N-2}(|xi - 2xi+1 + xi+2|,|yi - 2yi+1 + yi+2|)
+ * r0 = log4(sqrt(2)*N*(N-1)*L0/8e)
+ * Where e is the maximum distance error (RS_EPSILON)
+ */
+ private int getRecursionDepth(CubicSegment curve)
+ {
+ double x0 = curve.P1.getX();
+ double y0 = curve.P1.getY();
+
+ double x1 = curve.cp1.getX();
+ double y1 = curve.cp1.getY();
+
+ double x2 = curve.cp2.getX();
+ double y2 = curve.cp2.getY();
+
+ double x3 = curve.P2.getX();
+ double y3 = curve.P2.getY();
+
+ double L0 = Math.max(Math.max(Math.abs(x0 - 2 * x1 + x2),
+ Math.abs(x1 - 2 * x2 + x3)),
+ Math.max(Math.abs(y0 - 2 * y1 + y2),
+ Math.abs(y1 - 2 * y2 + y3)));
+
+ double f = Math.sqrt(2) * 6.0 * L0 / (8.0 * RS_EPSILON);
+
+ int r0 = (int) Math.ceil(Math.log(f) / Math.log(4.0));
+ return (r0);
+ }
+
+ /**
+ * Performs recursive subdivision:
+ * @param c1 - curve 1
+ * @param c2 - curve 2
+ * @param depth1 - recursion depth of curve 1
+ * @param depth2 - recursion depth of curve 2
+ * @param t1 - global parametric value of the first curve's starting point
+ * @param t2 - global parametric value of the second curve's starting point
+ * @param w1 - global parametric length of curve 1
+ * @param w2 - global parametric length of curve 2
+ *
+ * The final four parameters are for keeping track of the parametric
+ * value of the curve. For a full curve t = 0, w = 1, w is halved with
+ * each subdivision.
+ */
+ private void recursiveSubdivide(CubicCurve2D c1, CubicCurve2D c2,
+ int depth1, int depth2, double t1,
+ double t2, double w1, double w2)
+ {
+ boolean flat1 = depth1 <= 0;
+ boolean flat2 = depth2 <= 0;
+
+ if (flat1 && flat2)
+ {
+ double xlk = c1.getP2().getX() - c1.getP1().getX();
+ double ylk = c1.getP2().getY() - c1.getP1().getY();
+
+ double xnm = c2.getP2().getX() - c2.getP1().getX();
+ double ynm = c2.getP2().getY() - c2.getP1().getY();
+
+ double xmk = c2.getP1().getX() - c1.getP1().getX();
+ double ymk = c2.getP1().getY() - c1.getP1().getY();
+ double det = xnm * ylk - ynm * xlk;
+
+ if (det + 1.0 == 1.0)
+ return;
+
+ double detinv = 1.0 / det;
+ double s = (xnm * ymk - ynm * xmk) * detinv;
+ double t = (xlk * ymk - ylk * xmk) * detinv;
+ if ((s < 0.0) || (s > 1.0) || (t < 0.0) || (t > 1.0))
+ return;
+
+ double[] temp = new double[2];
+ temp[0] = t1 + s * w1;
+ temp[1] = t2 + t * w1;
+ cc_intersections.add(temp);
+ return;
+ }
+
+ CubicCurve2D.Double c11 = new CubicCurve2D.Double();
+ CubicCurve2D.Double c12 = new CubicCurve2D.Double();
+ CubicCurve2D.Double c21 = new CubicCurve2D.Double();
+ CubicCurve2D.Double c22 = new CubicCurve2D.Double();
+
+ if (! flat1 && ! flat2)
+ {
+ depth1--;
+ depth2--;
+ w1 = w1 * 0.5;
+ w2 = w2 * 0.5;
+ c1.subdivide(c11, c12);
+ c2.subdivide(c21, c22);
+ if (c11.getBounds2D().intersects(c21.getBounds2D()))
+ recursiveSubdivide(c11, c21, depth1, depth2, t1, t2, w1, w2);
+ if (c11.getBounds2D().intersects(c22.getBounds2D()))
+ recursiveSubdivide(c11, c22, depth1, depth2, t1, t2 + w2, w1, w2);
+ if (c12.getBounds2D().intersects(c21.getBounds2D()))
+ recursiveSubdivide(c12, c21, depth1, depth2, t1 + w1, t2, w1, w2);
+ if (c12.getBounds2D().intersects(c22.getBounds2D()))
+ recursiveSubdivide(c12, c22, depth1, depth2, t1 + w1, t2 + w2, w1, w2);
+ return;
+ }
+
+ if (! flat1)
+ {
+ depth1--;
+ c1.subdivide(c11, c12);
+ w1 = w1 * 0.5;
+ if (c11.getBounds2D().intersects(c2.getBounds2D()))
+ recursiveSubdivide(c11, c2, depth1, depth2, t1, t2, w1, w2);
+ if (c12.getBounds2D().intersects(c2.getBounds2D()))
+ recursiveSubdivide(c12, c2, depth1, depth2, t1 + w1, t2, w1, w2);
+ return;
+ }
+
+ depth2--;
+ c2.subdivide(c21, c22);
+ w2 = w2 * 0.5;
+ if (c1.getBounds2D().intersects(c21.getBounds2D()))
+ recursiveSubdivide(c1, c21, depth1, depth2, t1, t2, w1, w2);
+ if (c1.getBounds2D().intersects(c22.getBounds2D()))
+ recursiveSubdivide(c1, c22, depth1, depth2, t1, t2 + w2, w1, w2);
+ }
+
+ /**
+ * Returns a set of interesections between two Cubic segments
+ * Or null if no intersections were found.
+ *
+ * The method used to find the intersection is recursive midpoint
+ * subdivision. Outline description:
+ *
+ * 1) Check if the bounding boxes of the curves intersect,
+ * 2) If so, divide the curves in the middle and test the bounding
+ * boxes again,
+ * 3) Repeat until a maximum recursion depth has been reached, where
+ * the intersecting curves can be approximated by line segments.
+ *
+ * This is a reasonably accurate method, although the recursion depth
+ * is typically around 20, the bounding-box tests allow for significant
+ * pruning of the subdivision tree.
+ *
+ * This is package-private to avoid an accessor method.
+ */
+ Intersection[] cubicCubicIntersect(CubicSegment curve1, CubicSegment curve2)
+ {
+ Rectangle2D r1 = curve1.getBounds();
+ Rectangle2D r2 = curve2.getBounds();
+
+ if (! r1.intersects(r2))
+ return null;
+
+ cc_intersections = new Vector();
+ recursiveSubdivide(curve1.getCubicCurve2D(), curve2.getCubicCurve2D(),
+ getRecursionDepth(curve1), getRecursionDepth(curve2),
+ 0.0, 0.0, 1.0, 1.0);
+
+ if (cc_intersections.size() == 0)
+ return null;
+
+ Intersection[] results = new Intersection[cc_intersections.size()];
+ for (int i = 0; i < cc_intersections.size(); i++)
+ {
+ double[] temp = (double[]) cc_intersections.elementAt(i);
+ results[i] = new Intersection(curve1.evaluatePoint(temp[0]), temp[0],
+ temp[1]);
+ }
+ cc_intersections = null;
+ return (results);
+ }
+
+ /**
+ * Returns the intersections between a line and a quadratic bezier
+ * Or null if no intersections are found1
+ * This is done through combining the line's equation with the
+ * parametric form of the Bezier and solving the resulting quadratic.
+ * This is package-private to avoid an accessor method.
+ */
+ Intersection[] lineQuadIntersect(LineSegment l, QuadSegment c)
+ {
+ double[] y = new double[3];
+ double[] x = new double[3];
+ double[] r = new double[3];
+ int nRoots;
+ double x0 = c.P1.getX();
+ double y0 = c.P1.getY();
+ double x1 = c.cp.getX();
+ double y1 = c.cp.getY();
+ double x2 = c.P2.getX();
+ double y2 = c.P2.getY();
+
+ double lx0 = l.P1.getX();
+ double ly0 = l.P1.getY();
+ double lx1 = l.P2.getX();
+ double ly1 = l.P2.getY();
+ double dx = lx1 - lx0;
+ double dy = ly1 - ly0;
+
+ // form r(t) = y(t) - x(t) for the bezier
+ y[0] = y0;
+ y[1] = 2 * (y1 - y0);
+ y[2] = (y2 - 2 * y1 + y0);
+
+ x[0] = x0;
+ x[1] = 2 * (x1 - x0);
+ x[2] = (x2 - 2 * x1 + x0);
+
+ // a point, not a line
+ if (dy == 0 && dx == 0)
+ return null;
+
+ // line on y axis
+ if (dx == 0 || (dy / dx) > 1.0)
+ {
+ double k = dx / dy;
+ x[0] -= lx0;
+ y[0] -= ly0;
+ y[0] *= k;
+ y[1] *= k;
+ y[2] *= k;
+ }
+ else
+ {
+ double k = dy / dx;
+ x[0] -= lx0;
+ y[0] -= ly0;
+ x[0] *= k;
+ x[1] *= k;
+ x[2] *= k;
+ }
+
+ for (int i = 0; i < 3; i++)
+ r[i] = y[i] - x[i];
+
+ if ((nRoots = QuadCurve2D.solveQuadratic(r)) > 0)
+ {
+ Intersection[] temp = new Intersection[nRoots];
+ int intersections = 0;
+ for (int i = 0; i < nRoots; i++)
+ {
+ double t = r[i];
+ if (t >= 0.0 && t <= 1.0)
+ {
+ Point2D p = c.evaluatePoint(t);
+
+ // if the line is on an axis, snap the point to that axis.
+ if (dx == 0)
+ p.setLocation(lx0, p.getY());
+ if (dy == 0)
+ p.setLocation(p.getX(), ly0);
+
+ if (p.getX() <= Math.max(lx0, lx1)
+ && p.getX() >= Math.min(lx0, lx1)
+ && p.getY() <= Math.max(ly0, ly1)
+ && p.getY() >= Math.min(ly0, ly1))
+ {
+ double lineparameter = p.distance(l.P1) / l.P2.distance(l.P1);
+ temp[i] = new Intersection(p, lineparameter, t);
+ intersections++;
+ }
+ }
+ else
+ temp[i] = null;
+ }
+ if (intersections == 0)
+ return null;
+
+ Intersection[] rValues = new Intersection[intersections];
+
+ for (int i = 0; i < nRoots; i++)
+ if (temp[i] != null)
+ rValues[--intersections] = temp[i];
+ return (rValues);
+ }
+ return null;
+ }
+
+ /**
+ * Returns the intersections between a line and a cubic segment
+ * This is done through combining the line's equation with the
+ * parametric form of the Bezier and solving the resulting quadratic.
+ * This is package-private to avoid an accessor method.
+ */
+ Intersection[] lineCubicIntersect(LineSegment l, CubicSegment c)
+ {
+ double[] y = new double[4];
+ double[] x = new double[4];
+ double[] r = new double[4];
+ int nRoots;
+ double x0 = c.P1.getX();
+ double y0 = c.P1.getY();
+ double x1 = c.cp1.getX();
+ double y1 = c.cp1.getY();
+ double x2 = c.cp2.getX();
+ double y2 = c.cp2.getY();
+ double x3 = c.P2.getX();
+ double y3 = c.P2.getY();
+
+ double lx0 = l.P1.getX();
+ double ly0 = l.P1.getY();
+ double lx1 = l.P2.getX();
+ double ly1 = l.P2.getY();
+ double dx = lx1 - lx0;
+ double dy = ly1 - ly0;
+
+ // form r(t) = y(t) - x(t) for the bezier
+ y[0] = y0;
+ y[1] = 3 * (y1 - y0);
+ y[2] = 3 * (y2 + y0 - 2 * y1);
+ y[3] = y3 - 3 * y2 + 3 * y1 - y0;
+
+ x[0] = x0;
+ x[1] = 3 * (x1 - x0);
+ x[2] = 3 * (x2 + x0 - 2 * x1);
+ x[3] = x3 - 3 * x2 + 3 * x1 - x0;
+
+ // a point, not a line
+ if (dy == 0 && dx == 0)
+ return null;
+
+ // line on y axis
+ if (dx == 0 || (dy / dx) > 1.0)
+ {
+ double k = dx / dy;
+ x[0] -= lx0;
+ y[0] -= ly0;
+ y[0] *= k;
+ y[1] *= k;
+ y[2] *= k;
+ y[3] *= k;
+ }
+ else
+ {
+ double k = dy / dx;
+ x[0] -= lx0;
+ y[0] -= ly0;
+ x[0] *= k;
+ x[1] *= k;
+ x[2] *= k;
+ x[3] *= k;
+ }
+ for (int i = 0; i < 4; i++)
+ r[i] = y[i] - x[i];
+
+ if ((nRoots = CubicCurve2D.solveCubic(r)) > 0)
+ {
+ Intersection[] temp = new Intersection[nRoots];
+ int intersections = 0;
+ for (int i = 0; i < nRoots; i++)
+ {
+ double t = r[i];
+ if (t >= 0.0 && t <= 1.0)
+ {
+ // if the line is on an axis, snap the point to that axis.
+ Point2D p = c.evaluatePoint(t);
+ if (dx == 0)
+ p.setLocation(lx0, p.getY());
+ if (dy == 0)
+ p.setLocation(p.getX(), ly0);
+
+ if (p.getX() <= Math.max(lx0, lx1)
+ && p.getX() >= Math.min(lx0, lx1)
+ && p.getY() <= Math.max(ly0, ly1)
+ && p.getY() >= Math.min(ly0, ly1))
+ {
+ double lineparameter = p.distance(l.P1) / l.P2.distance(l.P1);
+ temp[i] = new Intersection(p, lineparameter, t);
+ intersections++;
+ }
+ }
+ else
+ temp[i] = null;
+ }
+
+ if (intersections == 0)
+ return null;
+
+ Intersection[] rValues = new Intersection[intersections];
+ for (int i = 0; i < nRoots; i++)
+ if (temp[i] != null)
+ rValues[--intersections] = temp[i];
+ return (rValues);
+ }
+ return null;
+ }
+
+ /**
+ * Returns the intersection between two lines, or null if there is no
+ * intersection.
+ * This is package-private to avoid an accessor method.
+ */
+ Intersection linesIntersect(LineSegment a, LineSegment b)
+ {
+ Point2D P1 = a.P1;
+ Point2D P2 = a.P2;
+ Point2D P3 = b.P1;
+ Point2D P4 = b.P2;
+
+ if (! Line2D.linesIntersect(P1.getX(), P1.getY(), P2.getX(), P2.getY(),
+ P3.getX(), P3.getY(), P4.getX(), P4.getY()))
+ return null;
+
+ double x1 = P1.getX();
+ double y1 = P1.getY();
+ double rx = P2.getX() - x1;
+ double ry = P2.getY() - y1;
+
+ double x2 = P3.getX();
+ double y2 = P3.getY();
+ double sx = P4.getX() - x2;
+ double sy = P4.getY() - y2;
+
+ double determinant = sx * ry - sy * rx;
+ double nom = (sx * (y2 - y1) + sy * (x1 - x2));
+
+ // Parallel lines don't intersect. At least we pretend they don't.
+ if (Math.abs(determinant) < EPSILON)
+ return null;
+
+ nom = nom / determinant;
+
+ if (nom == 0.0)
+ return null;
+ if (nom == 1.0)
+ return null;
+
+ Point2D p = new Point2D.Double(x1 + nom * rx, y1 + nom * ry);
+
+ return new Intersection(p, p.distance(P1) / P1.distance(P2),
+ p.distance(P3) / P3.distance(P4));
+ }
+
+ /**
+ * Determines if two points are equal, within an error margin
+ * 'snap distance'
+ * This is package-private to avoid an accessor method.
+ */
+ boolean pointEquals(Point2D a, Point2D b)
+ {
+ return (a.equals(b) || a.distance(b) < PE_EPSILON);
+ }
+
+ /**
+ * Helper method
+ * Turns a shape into a Vector of Segments
+ */
+ private Vector makeSegment(Shape s)
+ {
+ Vector paths = new Vector();
+ PathIterator pi = s.getPathIterator(null);
+ double[] coords = new double[6];
+ Segment subpath = null;
+ Segment current = null;
+ double cx;
+ double cy;
+ double subpathx;
+ double subpathy;
+ cx = cy = subpathx = subpathy = 0.0;
+
+ this.windingRule = pi.getWindingRule();
+
+ while (! pi.isDone())
+ {
+ Segment v;
+ switch (pi.currentSegment(coords))
+ {
+ case PathIterator.SEG_MOVETO:
+ if (subpath != null)
+ { // close existing open path
+ current.next = new LineSegment(cx, cy, subpathx, subpathy);
+ current = current.next;
+ current.next = subpath;
+ }
+ subpath = null;
+ subpathx = cx = coords[0];
+ subpathy = cy = coords[1];
+ break;
+
+ // replace 'close' with a line-to.
+ case PathIterator.SEG_CLOSE:
+ if (subpath != null && (subpathx != cx || subpathy != cy))
+ {
+ current.next = new LineSegment(cx, cy, subpathx, subpathy);
+ current = current.next;
+ current.next = subpath;
+ cx = subpathx;
+ cy = subpathy;
+ subpath = null;
+ }
+ else if (subpath != null)
+ {
+ current.next = subpath;
+ subpath = null;
+ }
+ break;
+ case PathIterator.SEG_LINETO:
+ if (cx != coords[0] || cy != coords[1])
+ {
+ v = new LineSegment(cx, cy, coords[0], coords[1]);
+ if (subpath == null)
+ {
+ subpath = current = v;
+ paths.add(subpath);
+ }
+ else
+ {
+ current.next = v;
+ current = current.next;
+ }
+ cx = coords[0];
+ cy = coords[1];
+ }
+ break;
+ case PathIterator.SEG_QUADTO:
+ v = new QuadSegment(cx, cy, coords[0], coords[1], coords[2],
+ coords[3]);
+ if (subpath == null)
+ {
+ subpath = current = v;
+ paths.add(subpath);
+ }
+ else
+ {
+ current.next = v;
+ current = current.next;
+ }
+ cx = coords[2];
+ cy = coords[3];
+ break;
+ case PathIterator.SEG_CUBICTO:
+ v = new CubicSegment(cx, cy, coords[0], coords[1], coords[2],
+ coords[3], coords[4], coords[5]);
+ if (subpath == null)
+ {
+ subpath = current = v;
+ paths.add(subpath);
+ }
+ else
+ {
+ current.next = v;
+ current = current.next;
+ }
+
+ // check if the cubic is self-intersecting
+ double[] lpts = ((CubicSegment) v).getLoop();
+ if (lpts != null)
+ {
+ // if it is, break off the loop into its own path.
+ v.subdivideInsert(lpts[0]);
+ v.next.subdivideInsert((lpts[1] - lpts[0]) / (1.0 - lpts[0]));
+
+ CubicSegment loop = (CubicSegment) v.next;
+ v.next = loop.next;
+ loop.next = loop;
+
+ v.P2 = v.next.P1 = loop.P2 = loop.P1; // snap points
+ paths.add(loop);
+ current = v.next;
+ }
+
+ cx = coords[4];
+ cy = coords[5];
+ break;
+ }
+ pi.next();
+ }
+
+ if (subpath != null)
+ { // close any open path
+ if (subpathx != cx || subpathy != cy)
+ {
+ current.next = new LineSegment(cx, cy, subpathx, subpathy);
+ current = current.next;
+ current.next = subpath;
+ }
+ else
+ current.next = subpath;
+ }
+
+ if (paths.size() == 0)
+ return (null);
+
+ return (paths);
+ }
+
+ /**
+ * Find the intersections of two separate closed paths,
+ * A and B, split the segments at the intersection points,
+ * and create nodes pointing from one to the other
+ */
+ private int createNodes(Segment A, Segment B)
+ {
+ int nNodes = 0;
+
+ Segment a = A;
+ Segment b = B;
+
+ do
+ {
+ do
+ {
+ nNodes += a.splitIntersections(b);
+ b = b.next;
+ }
+ while (b != B);
+
+ a = a.next; // move to the next segment
+ }
+ while (a != A); // until one wrap.
+
+ return (nNodes);
+ }
+
+ /**
+ * Find the intersections of a path with itself.
+ * Splits the segments at the intersection points,
+ * and create nodes pointing from one to the other.
+ */
+ private int createNodesSelf(Segment A)
+ {
+ int nNodes = 0;
+ Segment a = A;
+
+ if (A.next == A)
+ return 0;
+
+ do
+ {
+ Segment b = a.next;
+ do
+ {
+ if (b != a) // necessary
+ nNodes += a.splitIntersections(b);
+ b = b.next;
+ }
+ while (b != A);
+ a = a.next; // move to the next segment
+ }
+ while (a != A); // until one wrap.
+
+ return (nNodes);
+ }
+
+ /**
+ * Deletes paths which are redundant from a list, (i.e. solid areas within
+ * solid areas) Clears any nodes. Sorts the remaining paths into solids
+ * and holes, sets their orientation and sets the solids and holes lists.
+ */
+ private void deleteRedundantPaths(Vector paths)
+ {
+ int npaths = paths.size();
+
+ int[][] contains = new int[npaths][npaths];
+ int[][] windingNumbers = new int[npaths][2];
+ int neg;
+ Rectangle2D[] bb = new Rectangle2D[npaths]; // path bounding boxes
+
+ neg = ((windingRule == PathIterator.WIND_NON_ZERO) ? -1 : 1);
+
+ for (int i = 0; i < npaths; i++)
+ bb[i] = ((Segment) paths.elementAt(i)).getPathBounds();
+
+ // Find which path contains which, assign winding numbers
+ for (int i = 0; i < npaths; i++)
+ {
+ Segment pathA = (Segment) paths.elementAt(i);
+ pathA.nullNodes(); // remove any now-redundant nodes, in case.
+ int windingA = pathA.hasClockwiseOrientation() ? 1 : neg;
+
+ for (int j = 0; j < npaths; j++)
+ if (i != j)
+ {
+ Segment pathB = (Segment) paths.elementAt(j);
+
+ // A contains B
+ if (bb[i].intersects(bb[j]))
+ {
+ Segment s = pathB.next;
+ while (s.P1.getY() == s.P2.getY() && s != pathB)
+ s = s.next;
+ Point2D p = s.getMidPoint();
+ if (pathA.contains(p.getX(), p.getY()))
+ contains[i][j] = windingA;
+ }
+ else
+ // A does not contain B
+ contains[i][j] = 0;
+ }
+ else
+ contains[i][j] = windingA; // i == j
+ }
+
+ for (int i = 0; i < npaths; i++)
+ {
+ windingNumbers[i][0] = 0;
+ for (int j = 0; j < npaths; j++)
+ windingNumbers[i][0] += contains[j][i];
+ windingNumbers[i][1] = contains[i][i];
+ }
+
+ Vector solids = new Vector();
+ Vector holes = new Vector();
+
+ if (windingRule == PathIterator.WIND_NON_ZERO)
+ {
+ for (int i = 0; i < npaths; i++)
+ {
+ if (windingNumbers[i][0] == 0)
+ holes.add(paths.elementAt(i));
+ else if (windingNumbers[i][0] - windingNumbers[i][1] == 0
+ && Math.abs(windingNumbers[i][0]) == 1)
+ solids.add(paths.elementAt(i));
+ }
+ }
+ else
+ {
+ windingRule = PathIterator.WIND_NON_ZERO;
+ for (int i = 0; i < npaths; i++)
+ {
+ if ((windingNumbers[i][0] & 1) == 0)
+ holes.add(paths.elementAt(i));
+ else if ((windingNumbers[i][0] & 1) == 1)
+ solids.add(paths.elementAt(i));
+ }
+ }
+
+ setDirection(holes, false);
+ setDirection(solids, true);
+ this.holes = holes;
+ this.solids = solids;
+ }
+
+ /**
+ * Sets the winding direction of a Vector of paths
+ * @param clockwise gives the direction,
+ * true = clockwise, false = counter-clockwise
+ */
+ private void setDirection(Vector paths, boolean clockwise)
+ {
+ Segment v;
+ for (int i = 0; i < paths.size(); i++)
+ {
+ v = (Segment) paths.elementAt(i);
+ if (clockwise != v.hasClockwiseOrientation())
+ v.reverseAll();
+ }
+ }
+
+ /**
+ * Class representing a linked-list of vertices forming a closed polygon,
+ * convex or concave, without holes.
+ */
+ private abstract class Segment implements Cloneable
+ {
+ // segment type, PathIterator segment types are used.
+ Point2D P1;
+ Point2D P2;
+ Segment next;
+ Segment node;
+
+ Segment()
+ {
+ P1 = P2 = null;
+ node = next = null;
+ }
+
+ /**
+ * Reverses the direction of a single segment
+ */
+ abstract void reverseCoords();
+
+ /**
+ * Returns the segment's midpoint
+ */
+ abstract Point2D getMidPoint();
+
+ /**
+ * Returns the bounding box of this segment
+ */
+ abstract Rectangle2D getBounds();
+
+ /**
+ * Transforms a single segment
+ */
+ abstract void transform(AffineTransform at);
+
+ /**
+ * Returns the PathIterator type of a segment
+ */
+ abstract int getType();
+
+ /**
+ */
+ abstract int splitIntersections(Segment b);
+
+ /**
+ * Returns the PathIterator coords of a segment
+ */
+ abstract int pathIteratorFormat(double[] coords);
+
+ /**
+ * Returns the number of intersections on the positive X axis,
+ * with the origin at (x,y), used for contains()-testing
+ *
+ * (Although that could be done by the line-intersect methods,
+ * a dedicated method is better to guarantee consitent handling
+ * of endpoint-special-cases)
+ */
+ abstract int rayCrossing(double x, double y);
+
+ /**
+ * Subdivides the segment at parametric value t, inserting
+ * the new segment into the linked list after this,
+ * such that this becomes [0,t] and this.next becomes [t,1]
+ */
+ abstract void subdivideInsert(double t);
+
+ /**
+ * Returns twice the area of a curve, relative the P1-P2 line
+ * Used for area calculations.
+ */
+ abstract double curveArea();
+
+ /**
+ * Compare two segments.
+ */
+ abstract boolean equals(Segment b);
+
+ /**
+ * Determines if this path of segments contains the point (x,y)
+ */
+ boolean contains(double x, double y)
+ {
+ Segment v = this;
+ int crossings = 0;
+ do
+ {
+ int n = v.rayCrossing(x, y);
+ crossings += n;
+ v = v.next;
+ }
+ while (v != this);
+ return ((crossings & 1) == 1);
+ }
+
+ /**
+ * Nulls all nodes of the path. Clean up any 'hairs'.
+ */
+ void nullNodes()
+ {
+ Segment v = this;
+ do
+ {
+ v.node = null;
+ v = v.next;
+ }
+ while (v != this);
+ }
+
+ /**
+ * Transforms each segment in the closed path
+ */
+ void transformSegmentList(AffineTransform at)
+ {
+ Segment v = this;
+ do
+ {
+ v.transform(at);
+ v = v.next;
+ }
+ while (v != this);
+ }
+
+ /**
+ * Determines the winding direction of the path
+ * By the sign of the area.
+ */
+ boolean hasClockwiseOrientation()
+ {
+ return (getSignedArea() > 0.0);
+ }
+
+ /**
+ * Returns the bounds of this path
+ */
+ public Rectangle2D getPathBounds()
+ {
+ double xmin;
+ double xmax;
+ double ymin;
+ double ymax;
+ xmin = xmax = P1.getX();
+ ymin = ymax = P1.getY();
+
+ Segment v = this;
+ do
+ {
+ Rectangle2D r = v.getBounds();
+ xmin = Math.min(r.getMinX(), xmin);
+ ymin = Math.min(r.getMinY(), ymin);
+ xmax = Math.max(r.getMaxX(), xmax);
+ ymax = Math.max(r.getMaxY(), ymax);
+ v = v.next;
+ }
+ while (v != this);
+
+ return (new Rectangle2D.Double(xmin, ymin, (xmax - xmin), (ymax - ymin)));
+ }
+
+ /**
+ * Calculates twice the signed area of the path;
+ */
+ double getSignedArea()
+ {
+ Segment s;
+ double area = 0.0;
+
+ s = this;
+ do
+ {
+ area += s.curveArea();
+
+ area += s.P1.getX() * s.next.P1.getY()
+ - s.P1.getY() * s.next.P1.getX();
+ s = s.next;
+ }
+ while (s != this);
+
+ return area;
+ }
+
+ /**
+ * Reverses the orientation of the whole polygon
+ */
+ void reverseAll()
+ {
+ reverseCoords();
+ Segment v = next;
+ Segment former = this;
+ while (v != this)
+ {
+ v.reverseCoords();
+ Segment vnext = v.next;
+ v.next = former;
+ former = v;
+ v = vnext;
+ }
+ next = former;
+ }
+
+ /**
+ * Inserts a Segment after this one
+ */
+ void insert(Segment v)
+ {
+ Segment n = next;
+ next = v;
+ v.next = n;
+ }
+
+ /**
+ * Returns if this segment path is polygonal
+ */
+ boolean isPolygonal()
+ {
+ Segment v = this;
+ do
+ {
+ if (! (v instanceof LineSegment))
+ return false;
+ v = v.next;
+ }
+ while (v != this);
+ return true;
+ }
+
+ /**
+ * Clones this path
+ */
+ Segment cloneSegmentList() throws CloneNotSupportedException
+ {
+ Vector list = new Vector();
+ Segment v = next;
+
+ while (v != this)
+ {
+ list.add(v);
+ v = v.next;
+ }
+
+ Segment clone = (Segment) this.clone();
+ v = clone;
+ for (int i = 0; i < list.size(); i++)
+ {
+ clone.next = (Segment) ((Segment) list.elementAt(i)).clone();
+ clone = clone.next;
+ }
+ clone.next = v;
+ return v;
+ }
+
+ /**
+ * Creates a node between this segment and segment b
+ * at the given intersection
+ * @return the number of nodes created (0 or 1)
+ */
+ int createNode(Segment b, Intersection i)
+ {
+ Point2D p = i.p;
+ if ((pointEquals(P1, p) || pointEquals(P2, p))
+ && (pointEquals(b.P1, p) || pointEquals(b.P2, p)))
+ return 0;
+
+ subdivideInsert(i.ta);
+ b.subdivideInsert(i.tb);
+
+ // snap points
+ b.P2 = b.next.P1 = P2 = next.P1 = i.p;
+
+ node = b.next;
+ b.node = next;
+ return 1;
+ }
+
+ /**
+ * Creates multiple nodes from a list of intersections,
+ * This must be done in the order of ascending parameters,
+ * and the parameters must be recalculated in accordance
+ * with each split.
+ * @return the number of nodes created
+ */
+ protected int createNodes(Segment b, Intersection[] x)
+ {
+ Vector v = new Vector();
+ for (int i = 0; i < x.length; i++)
+ {
+ Point2D p = x[i].p;
+ if (! ((pointEquals(P1, p) || pointEquals(P2, p))
+ && (pointEquals(b.P1, p) || pointEquals(b.P2, p))))
+ v.add(x[i]);
+ }
+
+ int nNodes = v.size();
+ Intersection[] A = new Intersection[nNodes];
+ Intersection[] B = new Intersection[nNodes];
+ for (int i = 0; i < nNodes; i++)
+ A[i] = B[i] = (Intersection) v.elementAt(i);
+
+ // Create two lists sorted by the parameter
+ // Bubble sort, OK I suppose, since the number of intersections
+ // cannot be larger than 9 (cubic-cubic worst case) anyway
+ for (int i = 0; i < nNodes - 1; i++)
+ {
+ for (int j = i + 1; j < nNodes; j++)
+ {
+ if (A[i].ta > A[j].ta)
+ {
+ Intersection swap = A[i];
+ A[i] = A[j];
+ A[j] = swap;
+ }
+ if (B[i].tb > B[j].tb)
+ {
+ Intersection swap = B[i];
+ B[i] = B[j];
+ B[j] = swap;
+ }
+ }
+ }
+ // subdivide a
+ Segment s = this;
+ for (int i = 0; i < nNodes; i++)
+ {
+ s.subdivideInsert(A[i].ta);
+
+ // renormalize the parameters
+ for (int j = i + 1; j < nNodes; j++)
+ A[j].ta = (A[j].ta - A[i].ta) / (1.0 - A[i].ta);
+
+ A[i].seg = s;
+ s = s.next;
+ }
+
+ // subdivide b, set nodes
+ s = b;
+ for (int i = 0; i < nNodes; i++)
+ {
+ s.subdivideInsert(B[i].tb);
+
+ for (int j = i + 1; j < nNodes; j++)
+ B[j].tb = (B[j].tb - B[i].tb) / (1.0 - B[i].tb);
+
+ // set nodes
+ B[i].seg.node = s.next; // node a -> b
+ s.node = B[i].seg.next; // node b -> a
+
+ // snap points
+ B[i].seg.P2 = B[i].seg.next.P1 = s.P2 = s.next.P1 = B[i].p;
+ s = s.next;
+ }
+ return nNodes;
+ }
+
+ /**
+ * Determines if two paths are equal.
+ * Colinear line segments are ignored in the comparison.
+ */
+ boolean pathEquals(Segment B)
+ {
+ if (! getPathBounds().equals(B.getPathBounds()))
+ return false;
+
+ Segment startA = getTopLeft();
+ Segment startB = B.getTopLeft();
+ Segment a = startA;
+ Segment b = startB;
+ do
+ {
+ if (! a.equals(b))
+ return false;
+
+ if (a instanceof LineSegment)
+ a = ((LineSegment) a).lastCoLinear();
+ if (b instanceof LineSegment)
+ b = ((LineSegment) b).lastCoLinear();
+
+ a = a.next;
+ b = b.next;
+ }
+ while (a != startA && b != startB);
+ return true;
+ }
+
+ /**
+ * Return the segment with the top-leftmost first point
+ */
+ Segment getTopLeft()
+ {
+ Segment v = this;
+ Segment tl = this;
+ do
+ {
+ if (v.P1.getY() < tl.P1.getY())
+ tl = v;
+ else if (v.P1.getY() == tl.P1.getY())
+ {
+ if (v.P1.getX() < tl.P1.getX())
+ tl = v;
+ }
+ v = v.next;
+ }
+ while (v != this);
+ return tl;
+ }
+
+ /**
+ * Returns if the path has a segment outside a shape
+ */
+ boolean isSegmentOutside(Shape shape)
+ {
+ return ! shape.contains(getMidPoint());
+ }
+ } // class Segment
+
+ private class LineSegment extends Segment
+ {
+ public LineSegment(double x1, double y1, double x2, double y2)
+ {
+ super();
+ P1 = new Point2D.Double(x1, y1);
+ P2 = new Point2D.Double(x2, y2);
+ }
+
+ public LineSegment(Point2D p1, Point2D p2)
+ {
+ super();
+ P1 = (Point2D) p1.clone();
+ P2 = (Point2D) p2.clone();
+ }
+
+ /**
+ * Clones this segment
+ */
+ public Object clone()
+ {
+ return new LineSegment(P1, P2);
+ }
+
+ /**
+ * Transforms the segment
+ */
+ void transform(AffineTransform at)
+ {
+ P1 = at.transform(P1, null);
+ P2 = at.transform(P2, null);
+ }
+
+ /**
+ * Swap start and end points
+ */
+ void reverseCoords()
+ {
+ Point2D p = P1;
+ P1 = P2;
+ P2 = p;
+ }
+
+ /**
+ * Returns the segment's midpoint
+ */
+ Point2D getMidPoint()
+ {
+ return (new Point2D.Double(0.5 * (P1.getX() + P2.getX()),
+ 0.5 * (P1.getY() + P2.getY())));
+ }
+
+ /**
+ * Returns twice the area of a curve, relative the P1-P2 line
+ * Obviously, a line does not enclose any area besides the line
+ */
+ double curveArea()
+ {
+ return 0;
+ }
+
+ /**
+ * Returns the PathIterator type of a segment
+ */
+ int getType()
+ {
+ return (PathIterator.SEG_LINETO);
+ }
+
+ /**
+ * Subdivides the segment at parametric value t, inserting
+ * the new segment into the linked list after this,
+ * such that this becomes [0,t] and this.next becomes [t,1]
+ */
+ void subdivideInsert(double t)
+ {
+ Point2D p = new Point2D.Double((P2.getX() - P1.getX()) * t + P1.getX(),
+ (P2.getY() - P1.getY()) * t + P1.getY());
+ insert(new LineSegment(p, P2));
+ P2 = p;
+ next.node = node;
+ node = null;
+ }
+
+ /**
+ * Determines if two line segments are strictly colinear
+ */
+ boolean isCoLinear(LineSegment b)
+ {
+ double x1 = P1.getX();
+ double y1 = P1.getY();
+ double x2 = P2.getX();
+ double y2 = P2.getY();
+ double x3 = b.P1.getX();
+ double y3 = b.P1.getY();
+ double x4 = b.P2.getX();
+ double y4 = b.P2.getY();
+
+ if ((y1 - y3) * (x4 - x3) - (x1 - x3) * (y4 - y3) != 0.0)
+ return false;
+
+ return ((x2 - x1) * (y4 - y3) - (y2 - y1) * (x4 - x3) == 0.0);
+ }
+
+ /**
+ * Return the last segment colinear with this one.
+ * Used in comparing paths.
+ */
+ Segment lastCoLinear()
+ {
+ Segment prev = this;
+ Segment v = next;
+
+ while (v instanceof LineSegment)
+ {
+ if (isCoLinear((LineSegment) v))
+ {
+ prev = v;
+ v = v.next;
+ }
+ else
+ return prev;
+ }
+ return prev;
+ }
+
+ /**
+ * Compare two segments.
+ * We must take into account that the lines may be broken into colinear
+ * subsegments and ignore them.
+ */
+ boolean equals(Segment b)
+ {
+ if (! (b instanceof LineSegment))
+ return false;
+ Point2D p1 = P1;
+ Point2D p3 = b.P1;
+
+ if (! p1.equals(p3))
+ return false;
+
+ Point2D p2 = lastCoLinear().P2;
+ Point2D p4 = ((LineSegment) b).lastCoLinear().P2;
+ return (p2.equals(p4));
+ }
+
+ /**
+ * Returns a line segment
+ */
+ int pathIteratorFormat(double[] coords)
+ {
+ coords[0] = P2.getX();
+ coords[1] = P2.getY();
+ return (PathIterator.SEG_LINETO);
+ }
+
+ /**
+ * Returns if the line has intersections.
+ */
+ boolean hasIntersections(Segment b)
+ {
+ if (b instanceof LineSegment)
+ return (linesIntersect(this, (LineSegment) b) != null);
+
+ if (b instanceof QuadSegment)
+ return (lineQuadIntersect(this, (QuadSegment) b) != null);
+
+ if (b instanceof CubicSegment)
+ return (lineCubicIntersect(this, (CubicSegment) b) != null);
+
+ return false;
+ }
+
+ /**
+ * Splits intersections into nodes,
+ * This one handles line-line, line-quadratic, line-cubic
+ */
+ int splitIntersections(Segment b)
+ {
+ if (b instanceof LineSegment)
+ {
+ Intersection i = linesIntersect(this, (LineSegment) b);
+
+ if (i == null)
+ return 0;
+
+ return createNode(b, i);
+ }
+
+ Intersection[] x = null;
+
+ if (b instanceof QuadSegment)
+ x = lineQuadIntersect(this, (QuadSegment) b);
+
+ if (b instanceof CubicSegment)
+ x = lineCubicIntersect(this, (CubicSegment) b);
+
+ if (x == null)
+ return 0;
+
+ if (x.length == 1)
+ return createNode(b, (Intersection) x[0]);
+
+ return createNodes(b, x);
+ }
+
+ /**
+ * Returns the bounding box of this segment
+ */
+ Rectangle2D getBounds()
+ {
+ return (new Rectangle2D.Double(Math.min(P1.getX(), P2.getX()),
+ Math.min(P1.getY(), P2.getY()),
+ Math.abs(P1.getX() - P2.getX()),
+ Math.abs(P1.getY() - P2.getY())));
+ }
+
+ /**
+ * Returns the number of intersections on the positive X axis,
+ * with the origin at (x,y), used for contains()-testing
+ */
+ int rayCrossing(double x, double y)
+ {
+ double x0 = P1.getX() - x;
+ double y0 = P1.getY() - y;
+ double x1 = P2.getX() - x;
+ double y1 = P2.getY() - y;
+
+ if (y0 * y1 > 0)
+ return 0;
+
+ if (x0 < 0 && x1 < 0)
+ return 0;
+
+ if (y0 == 0.0)
+ y0 -= EPSILON;
+
+ if (y1 == 0.0)
+ y1 -= EPSILON;
+
+ if (Line2D.linesIntersect(x0, y0, x1, y1,
+ EPSILON, 0.0, Double.MAX_VALUE, 0.0))
+ return 1;
+ return 0;
+ }
+ } // class LineSegment
+
+ /**
+ * Quadratic Bezier curve segment
+ *
+ * Note: Most peers don't support quadratics directly, so it might make
+ * sense to represent them as cubics internally and just be done with it.
+ * I think we should be peer-agnostic, however, and stay faithful to the
+ * input geometry types as far as possible.
+ */
+ private class QuadSegment extends Segment
+ {
+ Point2D cp; // control point
+
+ /**
+ * Constructor, takes the coordinates of the start, control,
+ * and end point, respectively.
+ */
+ QuadSegment(double x1, double y1, double cx, double cy, double x2,
+ double y2)
+ {
+ super();
+ P1 = new Point2D.Double(x1, y1);
+ P2 = new Point2D.Double(x2, y2);
+ cp = new Point2D.Double(cx, cy);
+ }
+
+ /**
+ * Clones this segment
+ */
+ public Object clone()
+ {
+ return new QuadSegment(P1.getX(), P1.getY(), cp.getX(), cp.getY(),
+ P2.getX(), P2.getY());
+ }
+
+ /**
+ * Returns twice the area of a curve, relative the P1-P2 line
+ *
+ * The area formula can be derived by using Green's formula in the
+ * plane on the parametric form of the bezier.
+ */
+ double curveArea()
+ {
+ double x0 = P1.getX();
+ double y0 = P1.getY();
+ double x1 = cp.getX();
+ double y1 = cp.getY();
+ double x2 = P2.getX();
+ double y2 = P2.getY();
+
+ double P = (y2 - 2 * y1 + y0);
+ double Q = 2 * (y1 - y0);
+
+ double A = (x2 - 2 * x1 + x0);
+ double B = 2 * (x1 - x0);
+
+ double area = (B * P - A * Q) / 3.0;
+ return (area);
+ }
+
+ /**
+ * Compare two segments.
+ */
+ boolean equals(Segment b)
+ {
+ if (! (b instanceof QuadSegment))
+ return false;
+
+ return (P1.equals(b.P1) && cp.equals(((QuadSegment) b).cp)
+ && P2.equals(b.P2));
+ }
+
+ /**
+ * Returns a Point2D corresponding to the parametric value t
+ * of the curve
+ */
+ Point2D evaluatePoint(double t)
+ {
+ double x0 = P1.getX();
+ double y0 = P1.getY();
+ double x1 = cp.getX();
+ double y1 = cp.getY();
+ double x2 = P2.getX();
+ double y2 = P2.getY();
+
+ return new Point2D.Double(t * t * (x2 - 2 * x1 + x0) + 2 * t * (x1 - x0)
+ + x0,
+ t * t * (y2 - 2 * y1 + y0) + 2 * t * (y1 - y0)
+ + y0);
+ }
+
+ /**
+ * Returns the bounding box of this segment
+ */
+ Rectangle2D getBounds()
+ {
+ double x0 = P1.getX();
+ double y0 = P1.getY();
+ double x1 = cp.getX();
+ double y1 = cp.getY();
+ double x2 = P2.getX();
+ double y2 = P2.getY();
+ double r0;
+ double r1;
+
+ double xmax = Math.max(x0, x2);
+ double ymax = Math.max(y0, y2);
+ double xmin = Math.min(x0, x2);
+ double ymin = Math.min(y0, y2);
+
+ r0 = 2 * (y1 - y0);
+ r1 = 2 * (y2 - 2 * y1 + y0);
+ if (r1 != 0.0)
+ {
+ double t = -r0 / r1;
+ if (t > 0.0 && t < 1.0)
+ {
+ double y = evaluatePoint(t).getY();
+ ymax = Math.max(y, ymax);
+ ymin = Math.min(y, ymin);
+ }
+ }
+ r0 = 2 * (x1 - x0);
+ r1 = 2 * (x2 - 2 * x1 + x0);
+ if (r1 != 0.0)
+ {
+ double t = -r0 / r1;
+ if (t > 0.0 && t < 1.0)
+ {
+ double x = evaluatePoint(t).getY();
+ xmax = Math.max(x, xmax);
+ xmin = Math.min(x, xmin);
+ }
+ }
+
+ return (new Rectangle2D.Double(xmin, ymin, xmax - xmin, ymax - ymin));
+ }
+
+ /**
+ * Returns a cubic segment corresponding to this curve
+ */
+ CubicSegment getCubicSegment()
+ {
+ double x1 = P1.getX() + 2.0 * (cp.getX() - P1.getX()) / 3.0;
+ double y1 = P1.getY() + 2.0 * (cp.getY() - P1.getY()) / 3.0;
+ double x2 = cp.getX() + (P2.getX() - cp.getX()) / 3.0;
+ double y2 = cp.getY() + (P2.getY() - cp.getY()) / 3.0;
+
+ return new CubicSegment(P1.getX(), P1.getY(), x1, y1, x2, y2, P2.getX(),
+ P2.getY());
+ }
+
+ /**
+ * Returns the segment's midpoint
+ */
+ Point2D getMidPoint()
+ {
+ return evaluatePoint(0.5);
+ }
+
+ /**
+ * Returns the PathIterator type of a segment
+ */
+ int getType()
+ {
+ return (PathIterator.SEG_QUADTO);
+ }
+
+ /**
+ * Returns the PathIterator coords of a segment
+ */
+ int pathIteratorFormat(double[] coords)
+ {
+ coords[0] = cp.getX();
+ coords[1] = cp.getY();
+ coords[2] = P2.getX();
+ coords[3] = P2.getY();
+ return (PathIterator.SEG_QUADTO);
+ }
+
+ /**
+ * Returns the number of intersections on the positive X axis,
+ * with the origin at (x,y), used for contains()-testing
+ */
+ int rayCrossing(double x, double y)
+ {
+ double x0 = P1.getX() - x;
+ double y0 = P1.getY() - y;
+ double x1 = cp.getX() - x;
+ double y1 = cp.getY() - y;
+ double x2 = P2.getX() - x;
+ double y2 = P2.getY() - y;
+ double[] r = new double[3];
+ int nRoots;
+ int nCrossings = 0;
+
+ /* check if curve may intersect X+ axis. */
+ if ((x0 > 0.0 || x1 > 0.0 || x2 > 0.0) && (y0 * y1 <= 0 || y1 * y2 <= 0))
+ {
+ if (y0 == 0.0)
+ y0 -= EPSILON;
+ if (y2 == 0.0)
+ y2 -= EPSILON;
+
+ r[0] = y0;
+ r[1] = 2 * (y1 - y0);
+ r[2] = (y2 - 2 * y1 + y0);
+
+ nRoots = QuadCurve2D.solveQuadratic(r);
+ for (int i = 0; i < nRoots; i++)
+ if (r[i] > 0.0f && r[i] < 1.0f)
+ {
+ double t = r[i];
+ if (t * t * (x2 - 2 * x1 + x0) + 2 * t * (x1 - x0) + x0 > 0.0)
+ nCrossings++;
+ }
+ }
+ return nCrossings;
+ }
+
+ /**
+ * Swap start and end points
+ */
+ void reverseCoords()
+ {
+ Point2D temp = P1;
+ P1 = P2;
+ P2 = temp;
+ }
+
+ /**
+ * Splits intersections into nodes,
+ * This one handles quadratic-quadratic only,
+ * Quadratic-line is passed on to the LineSegment class,
+ * Quadratic-cubic is passed on to the CubicSegment class
+ */
+ int splitIntersections(Segment b)
+ {
+ if (b instanceof LineSegment)
+ return (b.splitIntersections(this));
+
+ if (b instanceof CubicSegment)
+ return (b.splitIntersections(this));
+
+ if (b instanceof QuadSegment)
+ {
+ // Use the cubic-cubic intersection routine for quads as well,
+ // Since a quadratic can be exactly described as a cubic, this
+ // should not be a problem;
+ // The recursion depth will be the same in any case.
+ Intersection[] x = cubicCubicIntersect(getCubicSegment(),
+ ((QuadSegment) b)
+ .getCubicSegment());
+ if (x == null)
+ return 0;
+
+ if (x.length == 1)
+ return createNode(b, (Intersection) x[0]);
+
+ return createNodes(b, x);
+ }
+ return 0;
+ }
+
+ /**
+ * Subdivides the segment at parametric value t, inserting
+ * the new segment into the linked list after this,
+ * such that this becomes [0,t] and this.next becomes [t,1]
+ */
+ void subdivideInsert(double t)
+ {
+ double x0 = P1.getX();
+ double y0 = P1.getY();
+ double x1 = cp.getX();
+ double y1 = cp.getY();
+ double x2 = P2.getX();
+ double y2 = P2.getY();
+
+ double p10x = x0 + t * (x1 - x0);
+ double p10y = y0 + t * (y1 - y0);
+ double p11x = x1 + t * (x2 - x1);
+ double p11y = y1 + t * (y2 - y1);
+ double p20x = p10x + t * (p11x - p10x);
+ double p20y = p10y + t * (p11y - p10y);
+
+ insert(new QuadSegment(p20x, p20y, p11x, p11y, x2, y2));
+ P2 = next.P1;
+ cp.setLocation(p10x, p10y);
+
+ next.node = node;
+ node = null;
+ }
+
+ /**
+ * Transforms the segment
+ */
+ void transform(AffineTransform at)
+ {
+ P1 = at.transform(P1, null);
+ P2 = at.transform(P2, null);
+ cp = at.transform(cp, null);
+ }
+ } // class QuadSegment
+
+ /**
+ * Cubic Bezier curve segment
+ */
+ private class CubicSegment extends Segment
+ {
+ Point2D cp1; // control points
+ Point2D cp2; // control points
+
+ /**
+ * Constructor - takes coordinates of the starting point,
+ * first control point, second control point and end point,
+ * respecively.
+ */
+ public CubicSegment(double x1, double y1, double c1x, double c1y,
+ double c2x, double c2y, double x2, double y2)
+ {
+ super();
+ P1 = new Point2D.Double(x1, y1);
+ P2 = new Point2D.Double(x2, y2);
+ cp1 = new Point2D.Double(c1x, c1y);
+ cp2 = new Point2D.Double(c2x, c2y);
+ }
+
+ /**
+ * Clones this segment
+ */
+ public Object clone()
+ {
+ return new CubicSegment(P1.getX(), P1.getY(), cp1.getX(), cp1.getY(),
+ cp2.getX(), cp2.getY(), P2.getX(), P2.getY());
+ }
+
+ /**
+ * Returns twice the area of a curve, relative the P1-P2 line
+ *
+ * The area formula can be derived by using Green's formula in the
+ * plane on the parametric form of the bezier.
+ */
+ double curveArea()
+ {
+ double x0 = P1.getX();
+ double y0 = P1.getY();
+ double x1 = cp1.getX();
+ double y1 = cp1.getY();
+ double x2 = cp2.getX();
+ double y2 = cp2.getY();
+ double x3 = P2.getX();
+ double y3 = P2.getY();
+
+ double P = y3 - 3 * y2 + 3 * y1 - y0;
+ double Q = 3 * (y2 + y0 - 2 * y1);
+ double R = 3 * (y1 - y0);
+
+ double A = x3 - 3 * x2 + 3 * x1 - x0;
+ double B = 3 * (x2 + x0 - 2 * x1);
+ double C = 3 * (x1 - x0);
+
+ double area = (B * P - A * Q) / 5.0 + (C * P - A * R) / 2.0
+ + (C * Q - B * R) / 3.0;
+
+ return (area);
+ }
+
+ /**
+ * Compare two segments.
+ */
+ boolean equals(Segment b)
+ {
+ if (! (b instanceof CubicSegment))
+ return false;
+
+ return (P1.equals(b.P1) && cp1.equals(((CubicSegment) b).cp1)
+ && cp2.equals(((CubicSegment) b).cp2) && P2.equals(b.P2));
+ }
+
+ /**
+ * Returns a Point2D corresponding to the parametric value t
+ * of the curve
+ */
+ Point2D evaluatePoint(double t)
+ {
+ double x0 = P1.getX();
+ double y0 = P1.getY();
+ double x1 = cp1.getX();
+ double y1 = cp1.getY();
+ double x2 = cp2.getX();
+ double y2 = cp2.getY();
+ double x3 = P2.getX();
+ double y3 = P2.getY();
+
+ return new Point2D.Double(-(t * t * t) * (x0 - 3 * x1 + 3 * x2 - x3)
+ + 3 * t * t * (x0 - 2 * x1 + x2)
+ + 3 * t * (x1 - x0) + x0,
+ -(t * t * t) * (y0 - 3 * y1 + 3 * y2 - y3)
+ + 3 * t * t * (y0 - 2 * y1 + y2)
+ + 3 * t * (y1 - y0) + y0);
+ }
+
+ /**
+ * Returns the bounding box of this segment
+ */
+ Rectangle2D getBounds()
+ {
+ double x0 = P1.getX();
+ double y0 = P1.getY();
+ double x1 = cp1.getX();
+ double y1 = cp1.getY();
+ double x2 = cp2.getX();
+ double y2 = cp2.getY();
+ double x3 = P2.getX();
+ double y3 = P2.getY();
+ double[] r = new double[3];
+
+ double xmax = Math.max(x0, x3);
+ double ymax = Math.max(y0, y3);
+ double xmin = Math.min(x0, x3);
+ double ymin = Math.min(y0, y3);
+
+ r[0] = 3 * (y1 - y0);
+ r[1] = 6.0 * (y2 + y0 - 2 * y1);
+ r[2] = 3.0 * (y3 - 3 * y2 + 3 * y1 - y0);
+
+ int n = QuadCurve2D.solveQuadratic(r);
+ for (int i = 0; i < n; i++)
+ {
+ double t = r[i];
+ if (t > 0 && t < 1.0)
+ {
+ double y = evaluatePoint(t).getY();
+ ymax = Math.max(y, ymax);
+ ymin = Math.min(y, ymin);
+ }
+ }
+
+ r[0] = 3 * (x1 - x0);
+ r[1] = 6.0 * (x2 + x0 - 2 * x1);
+ r[2] = 3.0 * (x3 - 3 * x2 + 3 * x1 - x0);
+ n = QuadCurve2D.solveQuadratic(r);
+ for (int i = 0; i < n; i++)
+ {
+ double t = r[i];
+ if (t > 0 && t < 1.0)
+ {
+ double x = evaluatePoint(t).getX();
+ xmax = Math.max(x, xmax);
+ xmin = Math.min(x, xmin);
+ }
+ }
+ return (new Rectangle2D.Double(xmin, ymin, (xmax - xmin), (ymax - ymin)));
+ }
+
+ /**
+ * Returns a CubicCurve2D object corresponding to this segment.
+ */
+ CubicCurve2D getCubicCurve2D()
+ {
+ return new CubicCurve2D.Double(P1.getX(), P1.getY(), cp1.getX(),
+ cp1.getY(), cp2.getX(), cp2.getY(),
+ P2.getX(), P2.getY());
+ }
+
+ /**
+ * Returns the parametric points of self-intersection if the cubic
+ * is self-intersecting, null otherwise.
+ */
+ double[] getLoop()
+ {
+ double x0 = P1.getX();
+ double y0 = P1.getY();
+ double x1 = cp1.getX();
+ double y1 = cp1.getY();
+ double x2 = cp2.getX();
+ double y2 = cp2.getY();
+ double x3 = P2.getX();
+ double y3 = P2.getY();
+ double[] r = new double[4];
+ double k;
+ double R;
+ double T;
+ double A;
+ double B;
+ double[] results = new double[2];
+
+ R = x3 - 3 * x2 + 3 * x1 - x0;
+ T = y3 - 3 * y2 + 3 * y1 - y0;
+
+ // A qudratic
+ if (R == 0.0 && T == 0.0)
+ return null;
+
+ // true cubic
+ if (R != 0.0 && T != 0.0)
+ {
+ A = 3 * (x2 + x0 - 2 * x1) / R;
+ B = 3 * (x1 - x0) / R;
+
+ double P = 3 * (y2 + y0 - 2 * y1) / T;
+ double Q = 3 * (y1 - y0) / T;
+
+ if (A == P || Q == B)
+ return null;
+
+ k = (Q - B) / (A - P);
+ }
+ else
+ {
+ if (R == 0.0)
+ {
+ // quadratic in x
+ k = -(3 * (x1 - x0)) / (3 * (x2 + x0 - 2 * x1));
+ A = 3 * (y2 + y0 - 2 * y1) / T;
+ B = 3 * (y1 - y0) / T;
+ }
+ else
+ {
+ // quadratic in y
+ k = -(3 * (y1 - y0)) / (3 * (y2 + y0 - 2 * y1));
+ A = 3 * (x2 + x0 - 2 * x1) / R;
+ B = 3 * (x1 - x0) / R;
+ }
+ }
+
+ r[0] = -k * k * k - A * k * k - B * k;
+ r[1] = 3 * k * k + 2 * k * A + 2 * B;
+ r[2] = -3 * k;
+ r[3] = 2;
+
+ int n = CubicCurve2D.solveCubic(r);
+ if (n != 3)
+ return null;
+
+ // sort r
+ double t;
+ for (int i = 0; i < 2; i++)
+ for (int j = i + 1; j < 3; j++)
+ if (r[j] < r[i])
+ {
+ t = r[i];
+ r[i] = r[j];
+ r[j] = t;
+ }
+
+ if (Math.abs(r[0] + r[2] - k) < 1E-13)
+ if (r[0] >= 0.0 && r[0] <= 1.0 && r[2] >= 0.0 && r[2] <= 1.0)
+ if (evaluatePoint(r[0]).distance(evaluatePoint(r[2])) < PE_EPSILON * 10)
+ { // we snap the points anyway
+ results[0] = r[0];
+ results[1] = r[2];
+ return (results);
+ }
+ return null;
+ }
+
+ /**
+ * Returns the segment's midpoint
+ */
+ Point2D getMidPoint()
+ {
+ return evaluatePoint(0.5);
+ }
+
+ /**
+ * Returns the PathIterator type of a segment
+ */
+ int getType()
+ {
+ return (PathIterator.SEG_CUBICTO);
+ }
+
+ /**
+ * Returns the PathIterator coords of a segment
+ */
+ int pathIteratorFormat(double[] coords)
+ {
+ coords[0] = cp1.getX();
+ coords[1] = cp1.getY();
+ coords[2] = cp2.getX();
+ coords[3] = cp2.getY();
+ coords[4] = P2.getX();
+ coords[5] = P2.getY();
+ return (PathIterator.SEG_CUBICTO);
+ }
+
+ /**
+ * Returns the number of intersections on the positive X axis,
+ * with the origin at (x,y), used for contains()-testing
+ */
+ int rayCrossing(double x, double y)
+ {
+ double x0 = P1.getX() - x;
+ double y0 = P1.getY() - y;
+ double x1 = cp1.getX() - x;
+ double y1 = cp1.getY() - y;
+ double x2 = cp2.getX() - x;
+ double y2 = cp2.getY() - y;
+ double x3 = P2.getX() - x;
+ double y3 = P2.getY() - y;
+ double[] r = new double[4];
+ int nRoots;
+ int nCrossings = 0;
+
+ /* check if curve may intersect X+ axis. */
+ if ((x0 > 0.0 || x1 > 0.0 || x2 > 0.0 || x3 > 0.0)
+ && (y0 * y1 <= 0 || y1 * y2 <= 0 || y2 * y3 <= 0))
+ {
+ if (y0 == 0.0)
+ y0 -= EPSILON;
+ if (y3 == 0.0)
+ y3 -= EPSILON;
+
+ r[0] = y0;
+ r[1] = 3 * (y1 - y0);
+ r[2] = 3 * (y2 + y0 - 2 * y1);
+ r[3] = y3 - 3 * y2 + 3 * y1 - y0;
+
+ if ((nRoots = CubicCurve2D.solveCubic(r)) > 0)
+ for (int i = 0; i < nRoots; i++)
+ {
+ if (r[i] > 0.0 && r[i] < 1.0)
+ {
+ double t = r[i];
+ if (-(t * t * t) * (x0 - 3 * x1 + 3 * x2 - x3)
+ + 3 * t * t * (x0 - 2 * x1 + x2) + 3 * t * (x1 - x0)
+ + x0 > 0.0)
+ nCrossings++;
+ }
+ }
+ }
+ return nCrossings;
+ }
+
+ /**
+ * Swap start and end points
+ */
+ void reverseCoords()
+ {
+ Point2D p = P1;
+ P1 = P2;
+ P2 = p;
+ p = cp1; // swap control points
+ cp1 = cp2;
+ cp2 = p;
+ }
+
+ /**
+ * Splits intersections into nodes,
+ * This one handles cubic-cubic and cubic-quadratic intersections
+ */
+ int splitIntersections(Segment b)
+ {
+ if (b instanceof LineSegment)
+ return (b.splitIntersections(this));
+
+ Intersection[] x = null;
+
+ if (b instanceof QuadSegment)
+ x = cubicCubicIntersect(this, ((QuadSegment) b).getCubicSegment());
+
+ if (b instanceof CubicSegment)
+ x = cubicCubicIntersect(this, (CubicSegment) b);
+
+ if (x == null)
+ return 0;
+
+ if (x.length == 1)
+ return createNode(b, x[0]);
+
+ return createNodes(b, x);
+ }
+
+ /**
+ * Subdivides the segment at parametric value t, inserting
+ * the new segment into the linked list after this,
+ * such that this becomes [0,t] and this.next becomes [t,1]
+ */
+ void subdivideInsert(double t)
+ {
+ CubicSegment s = (CubicSegment) clone();
+ double p1x = (s.cp1.getX() - s.P1.getX()) * t + s.P1.getX();
+ double p1y = (s.cp1.getY() - s.P1.getY()) * t + s.P1.getY();
+
+ double px = (s.cp2.getX() - s.cp1.getX()) * t + s.cp1.getX();
+ double py = (s.cp2.getY() - s.cp1.getY()) * t + s.cp1.getY();
+
+ s.cp2.setLocation((s.P2.getX() - s.cp2.getX()) * t + s.cp2.getX(),
+ (s.P2.getY() - s.cp2.getY()) * t + s.cp2.getY());
+
+ s.cp1.setLocation((s.cp2.getX() - px) * t + px,
+ (s.cp2.getY() - py) * t + py);
+
+ double p2x = (px - p1x) * t + p1x;
+ double p2y = (py - p1y) * t + p1y;
+
+ double p3x = (s.cp1.getX() - p2x) * t + p2x;
+ double p3y = (s.cp1.getY() - p2y) * t + p2y;
+ s.P1.setLocation(p3x, p3y);
+
+ // insert new curve
+ insert(s);
+
+ // set this curve
+ cp1.setLocation(p1x, p1y);
+ cp2.setLocation(p2x, p2y);
+ P2 = s.P1;
+ next.node = node;
+ node = null;
+ }
+
+ /**
+ * Transforms the segment
+ */
+ void transform(AffineTransform at)
+ {
+ P1 = at.transform(P1, null);
+ P2 = at.transform(P2, null);
+ cp1 = at.transform(cp1, null);
+ cp2 = at.transform(cp2, null);
+ }
+ } // class CubicSegment
+} // class Area
diff --git a/libjava/classpath/java/awt/geom/CubicCurve2D.java b/libjava/classpath/java/awt/geom/CubicCurve2D.java
new file mode 100644
index 000000000..5cb11fe77
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/CubicCurve2D.java
@@ -0,0 +1,1724 @@
+/* CubicCurve2D.java -- represents a parameterized cubic curve in 2-D space
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.geom;
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.util.NoSuchElementException;
+
+
+/**
+ * A two-dimensional curve that is parameterized with a cubic
+ * function.
+ *
+ * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180"
+ * alt="A drawing of a CubicCurve2D" />
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Graydon Hoare (graydon@redhat.com)
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ * @author Sven de Marothy (sven@physto.se)
+ *
+ * @since 1.2
+ */
+public abstract class CubicCurve2D implements Shape, Cloneable
+{
+ private static final double BIG_VALUE = java.lang.Double.MAX_VALUE / 10.0;
+ private static final double EPSILON = 1E-10;
+
+ /**
+ * Constructs a new CubicCurve2D. Typical users will want to
+ * construct instances of a subclass, such as {@link
+ * CubicCurve2D.Float} or {@link CubicCurve2D.Double}.
+ */
+ protected CubicCurve2D()
+ {
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s start
+ * point.
+ */
+ public abstract double getX1();
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s start
+ * point.
+ */
+ public abstract double getY1();
+
+ /**
+ * Returns the curve&#x2019;s start point.
+ */
+ public abstract Point2D getP1();
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s first
+ * control point.
+ */
+ public abstract double getCtrlX1();
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s first
+ * control point.
+ */
+ public abstract double getCtrlY1();
+
+ /**
+ * Returns the curve&#x2019;s first control point.
+ */
+ public abstract Point2D getCtrlP1();
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s second
+ * control point.
+ */
+ public abstract double getCtrlX2();
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s second
+ * control point.
+ */
+ public abstract double getCtrlY2();
+
+ /**
+ * Returns the curve&#x2019;s second control point.
+ */
+ public abstract Point2D getCtrlP2();
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public abstract double getX2();
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public abstract double getY2();
+
+ /**
+ * Returns the curve&#x2019;s end point.
+ */
+ public abstract Point2D getP2();
+
+ /**
+ * Changes the curve geometry, separately specifying each coordinate
+ * value.
+ *
+ * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180"
+ * alt="A drawing of a CubicCurve2D" />
+ *
+ * @param x1 the <i>x</i> coordinate of the curve&#x2019;s new start
+ * point.
+ *
+ * @param y1 the <i>y</i> coordinate of the curve&#x2019;s new start
+ * point.
+ *
+ * @param cx1 the <i>x</i> coordinate of the curve&#x2019;s new
+ * first control point.
+ *
+ * @param cy1 the <i>y</i> coordinate of the curve&#x2019;s new
+ * first control point.
+ *
+ * @param cx2 the <i>x</i> coordinate of the curve&#x2019;s new
+ * second control point.
+ *
+ * @param cy2 the <i>y</i> coordinate of the curve&#x2019;s new
+ * second control point.
+ *
+ * @param x2 the <i>x</i> coordinate of the curve&#x2019;s new end
+ * point.
+ *
+ * @param y2 the <i>y</i> coordinate of the curve&#x2019;s new end
+ * point.
+ */
+ public abstract void setCurve(double x1, double y1, double cx1, double cy1,
+ double cx2, double cy2, double x2, double y2);
+
+ /**
+ * Changes the curve geometry, specifying coordinate values in an
+ * array.
+ *
+ * @param coords an array containing the new coordinate values. The
+ * <i>x</i> coordinate of the new start point is located at
+ * <code>coords[offset]</code>, its <i>y</i> coordinate at
+ * <code>coords[offset + 1]</code>. The <i>x</i> coordinate of the
+ * new first control point is located at <code>coords[offset +
+ * 2]</code>, its <i>y</i> coordinate at <code>coords[offset +
+ * 3]</code>. The <i>x</i> coordinate of the new second control
+ * point is located at <code>coords[offset + 4]</code>, its <i>y</i>
+ * coordinate at <code>coords[offset + 5]</code>. The <i>x</i>
+ * coordinate of the new end point is located at <code>coords[offset
+ * + 6]</code>, its <i>y</i> coordinate at <code>coords[offset +
+ * 7]</code>.
+ *
+ * @param offset the offset of the first coordinate value in
+ * <code>coords</code>.
+ */
+ public void setCurve(double[] coords, int offset)
+ {
+ setCurve(coords[offset++], coords[offset++], coords[offset++],
+ coords[offset++], coords[offset++], coords[offset++],
+ coords[offset++], coords[offset++]);
+ }
+
+ /**
+ * Changes the curve geometry, specifying coordinate values in
+ * separate Point objects.
+ *
+ * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180"
+ * alt="A drawing of a CubicCurve2D" />
+ *
+ * <p>The curve does not keep any reference to the passed point
+ * objects. Therefore, a later change to <code>p1</code>,
+ * <code>c1</code>, <code>c2</code> or <code>p2</code> will not
+ * affect the curve geometry.
+ *
+ * @param p1 the new start point.
+ * @param c1 the new first control point.
+ * @param c2 the new second control point.
+ * @param p2 the new end point.
+ */
+ public void setCurve(Point2D p1, Point2D c1, Point2D c2, Point2D p2)
+ {
+ setCurve(p1.getX(), p1.getY(), c1.getX(), c1.getY(), c2.getX(), c2.getY(),
+ p2.getX(), p2.getY());
+ }
+
+ /**
+ * Changes the curve geometry, specifying coordinate values in an
+ * array of Point objects.
+ *
+ * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180"
+ * alt="A drawing of a CubicCurve2D" />
+ *
+ * <p>The curve does not keep references to the passed point
+ * objects. Therefore, a later change to the <code>pts</code> array
+ * or any of its elements will not affect the curve geometry.
+ *
+ * @param pts an array containing the points. The new start point
+ * is located at <code>pts[offset]</code>, the new first control
+ * point at <code>pts[offset + 1]</code>, the new second control
+ * point at <code>pts[offset + 2]</code>, and the new end point
+ * at <code>pts[offset + 3]</code>.
+ *
+ * @param offset the offset of the start point in <code>pts</code>.
+ */
+ public void setCurve(Point2D[] pts, int offset)
+ {
+ setCurve(pts[offset].getX(), pts[offset++].getY(), pts[offset].getX(),
+ pts[offset++].getY(), pts[offset].getX(), pts[offset++].getY(),
+ pts[offset].getX(), pts[offset++].getY());
+ }
+
+ /**
+ * Changes the curve geometry to that of another curve.
+ *
+ * @param c the curve whose coordinates will be copied.
+ */
+ public void setCurve(CubicCurve2D c)
+ {
+ setCurve(c.getX1(), c.getY1(), c.getCtrlX1(), c.getCtrlY1(),
+ c.getCtrlX2(), c.getCtrlY2(), c.getX2(), c.getY2());
+ }
+
+ /**
+ * Calculates the squared flatness of a cubic curve, directly
+ * specifying each coordinate value. The flatness is the maximal
+ * distance of a control point to the line between start and end
+ * point.
+ *
+ * <p><img src="doc-files/CubicCurve2D-4.png" width="350" height="180"
+ * alt="A drawing that illustrates the flatness" />
+ *
+ * <p>In the above drawing, the straight line connecting start point
+ * P1 and end point P2 is depicted in gray. In comparison to C1,
+ * control point C2 is father away from the gray line. Therefore,
+ * the result will be the square of the distance between C2 and the
+ * gray line, i.e. the squared length of the red line.
+ *
+ * @param x1 the <i>x</i> coordinate of the start point P1.
+ * @param y1 the <i>y</i> coordinate of the start point P1.
+ * @param cx1 the <i>x</i> coordinate of the first control point C1.
+ * @param cy1 the <i>y</i> coordinate of the first control point C1.
+ * @param cx2 the <i>x</i> coordinate of the second control point C2.
+ * @param cy2 the <i>y</i> coordinate of the second control point C2.
+ * @param x2 the <i>x</i> coordinate of the end point P2.
+ * @param y2 the <i>y</i> coordinate of the end point P2.
+ */
+ public static double getFlatnessSq(double x1, double y1, double cx1,
+ double cy1, double cx2, double cy2,
+ double x2, double y2)
+ {
+ return Math.max(Line2D.ptSegDistSq(x1, y1, x2, y2, cx1, cy1),
+ Line2D.ptSegDistSq(x1, y1, x2, y2, cx2, cy2));
+ }
+
+ /**
+ * Calculates the flatness of a cubic curve, directly specifying
+ * each coordinate value. The flatness is the maximal distance of a
+ * control point to the line between start and end point.
+ *
+ * <p><img src="doc-files/CubicCurve2D-4.png" width="350" height="180"
+ * alt="A drawing that illustrates the flatness" />
+ *
+ * <p>In the above drawing, the straight line connecting start point
+ * P1 and end point P2 is depicted in gray. In comparison to C1,
+ * control point C2 is father away from the gray line. Therefore,
+ * the result will be the distance between C2 and the gray line,
+ * i.e. the length of the red line.
+ *
+ * @param x1 the <i>x</i> coordinate of the start point P1.
+ * @param y1 the <i>y</i> coordinate of the start point P1.
+ * @param cx1 the <i>x</i> coordinate of the first control point C1.
+ * @param cy1 the <i>y</i> coordinate of the first control point C1.
+ * @param cx2 the <i>x</i> coordinate of the second control point C2.
+ * @param cy2 the <i>y</i> coordinate of the second control point C2.
+ * @param x2 the <i>x</i> coordinate of the end point P2.
+ * @param y2 the <i>y</i> coordinate of the end point P2.
+ */
+ public static double getFlatness(double x1, double y1, double cx1,
+ double cy1, double cx2, double cy2,
+ double x2, double y2)
+ {
+ return Math.sqrt(getFlatnessSq(x1, y1, cx1, cy1, cx2, cy2, x2, y2));
+ }
+
+ /**
+ * Calculates the squared flatness of a cubic curve, specifying the
+ * coordinate values in an array. The flatness is the maximal
+ * distance of a control point to the line between start and end
+ * point.
+ *
+ * <p><img src="doc-files/CubicCurve2D-4.png" width="350" height="180"
+ * alt="A drawing that illustrates the flatness" />
+ *
+ * <p>In the above drawing, the straight line connecting start point
+ * P1 and end point P2 is depicted in gray. In comparison to C1,
+ * control point C2 is father away from the gray line. Therefore,
+ * the result will be the square of the distance between C2 and the
+ * gray line, i.e. the squared length of the red line.
+ *
+ * @param coords an array containing the coordinate values. The
+ * <i>x</i> coordinate of the start point P1 is located at
+ * <code>coords[offset]</code>, its <i>y</i> coordinate at
+ * <code>coords[offset + 1]</code>. The <i>x</i> coordinate of the
+ * first control point C1 is located at <code>coords[offset +
+ * 2]</code>, its <i>y</i> coordinate at <code>coords[offset +
+ * 3]</code>. The <i>x</i> coordinate of the second control point C2
+ * is located at <code>coords[offset + 4]</code>, its <i>y</i>
+ * coordinate at <code>coords[offset + 5]</code>. The <i>x</i>
+ * coordinate of the end point P2 is located at <code>coords[offset
+ * + 6]</code>, its <i>y</i> coordinate at <code>coords[offset +
+ * 7]</code>.
+ *
+ * @param offset the offset of the first coordinate value in
+ * <code>coords</code>.
+ */
+ public static double getFlatnessSq(double[] coords, int offset)
+ {
+ return getFlatnessSq(coords[offset++], coords[offset++], coords[offset++],
+ coords[offset++], coords[offset++], coords[offset++],
+ coords[offset++], coords[offset++]);
+ }
+
+ /**
+ * Calculates the flatness of a cubic curve, specifying the
+ * coordinate values in an array. The flatness is the maximal
+ * distance of a control point to the line between start and end
+ * point.
+ *
+ * <p><img src="doc-files/CubicCurve2D-4.png" width="350" height="180"
+ * alt="A drawing that illustrates the flatness" />
+ *
+ * <p>In the above drawing, the straight line connecting start point
+ * P1 and end point P2 is depicted in gray. In comparison to C1,
+ * control point C2 is father away from the gray line. Therefore,
+ * the result will be the distance between C2 and the gray line,
+ * i.e. the length of the red line.
+ *
+ * @param coords an array containing the coordinate values. The
+ * <i>x</i> coordinate of the start point P1 is located at
+ * <code>coords[offset]</code>, its <i>y</i> coordinate at
+ * <code>coords[offset + 1]</code>. The <i>x</i> coordinate of the
+ * first control point C1 is located at <code>coords[offset +
+ * 2]</code>, its <i>y</i> coordinate at <code>coords[offset +
+ * 3]</code>. The <i>x</i> coordinate of the second control point C2
+ * is located at <code>coords[offset + 4]</code>, its <i>y</i>
+ * coordinate at <code>coords[offset + 5]</code>. The <i>x</i>
+ * coordinate of the end point P2 is located at <code>coords[offset
+ * + 6]</code>, its <i>y</i> coordinate at <code>coords[offset +
+ * 7]</code>.
+ *
+ * @param offset the offset of the first coordinate value in
+ * <code>coords</code>.
+ */
+ public static double getFlatness(double[] coords, int offset)
+ {
+ return Math.sqrt(getFlatnessSq(coords[offset++], coords[offset++],
+ coords[offset++], coords[offset++],
+ coords[offset++], coords[offset++],
+ coords[offset++], coords[offset++]));
+ }
+
+ /**
+ * Calculates the squared flatness of this curve. The flatness is
+ * the maximal distance of a control point to the line between start
+ * and end point.
+ *
+ * <p><img src="doc-files/CubicCurve2D-4.png" width="350" height="180"
+ * alt="A drawing that illustrates the flatness" />
+ *
+ * <p>In the above drawing, the straight line connecting start point
+ * P1 and end point P2 is depicted in gray. In comparison to C1,
+ * control point C2 is father away from the gray line. Therefore,
+ * the result will be the square of the distance between C2 and the
+ * gray line, i.e. the squared length of the red line.
+ */
+ public double getFlatnessSq()
+ {
+ return getFlatnessSq(getX1(), getY1(), getCtrlX1(), getCtrlY1(),
+ getCtrlX2(), getCtrlY2(), getX2(), getY2());
+ }
+
+ /**
+ * Calculates the flatness of this curve. The flatness is the
+ * maximal distance of a control point to the line between start and
+ * end point.
+ *
+ * <p><img src="doc-files/CubicCurve2D-4.png" width="350" height="180"
+ * alt="A drawing that illustrates the flatness" />
+ *
+ * <p>In the above drawing, the straight line connecting start point
+ * P1 and end point P2 is depicted in gray. In comparison to C1,
+ * control point C2 is father away from the gray line. Therefore,
+ * the result will be the distance between C2 and the gray line,
+ * i.e. the length of the red line.
+ */
+ public double getFlatness()
+ {
+ return Math.sqrt(getFlatnessSq(getX1(), getY1(), getCtrlX1(), getCtrlY1(),
+ getCtrlX2(), getCtrlY2(), getX2(), getY2()));
+ }
+
+ /**
+ * Subdivides this curve into two halves.
+ *
+ * <p><img src="doc-files/CubicCurve2D-3.png" width="700"
+ * height="180" alt="A drawing that illustrates the effects of
+ * subdividing a CubicCurve2D" />
+ *
+ * @param left a curve whose geometry will be set to the left half
+ * of this curve, or <code>null</code> if the caller is not
+ * interested in the left half.
+ *
+ * @param right a curve whose geometry will be set to the right half
+ * of this curve, or <code>null</code> if the caller is not
+ * interested in the right half.
+ */
+ public void subdivide(CubicCurve2D left, CubicCurve2D right)
+ {
+ // Use empty slots at end to share single array.
+ double[] d = new double[]
+ {
+ getX1(), getY1(), getCtrlX1(), getCtrlY1(), getCtrlX2(),
+ getCtrlY2(), getX2(), getY2(), 0, 0, 0, 0, 0, 0
+ };
+ subdivide(d, 0, d, 0, d, 6);
+ if (left != null)
+ left.setCurve(d, 0);
+ if (right != null)
+ right.setCurve(d, 6);
+ }
+
+ /**
+ * Subdivides a cubic curve into two halves.
+ *
+ * <p><img src="doc-files/CubicCurve2D-3.png" width="700"
+ * height="180" alt="A drawing that illustrates the effects of
+ * subdividing a CubicCurve2D" />
+ *
+ * @param src the curve to be subdivided.
+ *
+ * @param left a curve whose geometry will be set to the left half
+ * of <code>src</code>, or <code>null</code> if the caller is not
+ * interested in the left half.
+ *
+ * @param right a curve whose geometry will be set to the right half
+ * of <code>src</code>, or <code>null</code> if the caller is not
+ * interested in the right half.
+ */
+ public static void subdivide(CubicCurve2D src, CubicCurve2D left,
+ CubicCurve2D right)
+ {
+ src.subdivide(left, right);
+ }
+
+ /**
+ * Subdivides a cubic curve into two halves, passing all coordinates
+ * in an array.
+ *
+ * <p><img src="doc-files/CubicCurve2D-3.png" width="700"
+ * height="180" alt="A drawing that illustrates the effects of
+ * subdividing a CubicCurve2D" />
+ *
+ * <p>The left end point and the right start point will always be
+ * identical. Memory-concious programmers thus may want to pass the
+ * same array for both <code>left</code> and <code>right</code>, and
+ * set <code>rightOff</code> to <code>leftOff + 6</code>.
+ *
+ * @param src an array containing the coordinates of the curve to be
+ * subdivided. The <i>x</i> coordinate of the start point P1 is
+ * located at <code>src[srcOff]</code>, its <i>y</i> at
+ * <code>src[srcOff + 1]</code>. The <i>x</i> coordinate of the
+ * first control point C1 is located at <code>src[srcOff +
+ * 2]</code>, its <i>y</i> at <code>src[srcOff + 3]</code>. The
+ * <i>x</i> coordinate of the second control point C2 is located at
+ * <code>src[srcOff + 4]</code>, its <i>y</i> at <code>src[srcOff +
+ * 5]</code>. The <i>x</i> coordinate of the end point is located at
+ * <code>src[srcOff + 6]</code>, its <i>y</i> at <code>src[srcOff +
+ * 7]</code>.
+ *
+ * @param srcOff an offset into <code>src</code>, specifying
+ * the index of the start point&#x2019;s <i>x</i> coordinate.
+ *
+ * @param left an array that will receive the coordinates of the
+ * left half of <code>src</code>. It is acceptable to pass
+ * <code>src</code>. A caller who is not interested in the left half
+ * can pass <code>null</code>.
+ *
+ * @param leftOff an offset into <code>left</code>, specifying the
+ * index where the start point&#x2019;s <i>x</i> coordinate will be
+ * stored.
+ *
+ * @param right an array that will receive the coordinates of the
+ * right half of <code>src</code>. It is acceptable to pass
+ * <code>src</code> or <code>left</code>. A caller who is not
+ * interested in the right half can pass <code>null</code>.
+ *
+ * @param rightOff an offset into <code>right</code>, specifying the
+ * index where the start point&#x2019;s <i>x</i> coordinate will be
+ * stored.
+ */
+ public static void subdivide(double[] src, int srcOff, double[] left,
+ int leftOff, double[] right, int rightOff)
+ {
+ // To understand this code, please have a look at the image
+ // "CubicCurve2D-3.png" in the sub-directory "doc-files".
+ double src_C1_x;
+ double src_C1_y;
+ double src_C2_x;
+ double src_C2_y;
+ double left_P1_x;
+ double left_P1_y;
+ double left_C1_x;
+ double left_C1_y;
+ double left_C2_x;
+ double left_C2_y;
+ double right_C1_x;
+ double right_C1_y;
+ double right_C2_x;
+ double right_C2_y;
+ double right_P2_x;
+ double right_P2_y;
+ double Mid_x; // Mid = left.P2 = right.P1
+ double Mid_y; // Mid = left.P2 = right.P1
+
+ left_P1_x = src[srcOff];
+ left_P1_y = src[srcOff + 1];
+ src_C1_x = src[srcOff + 2];
+ src_C1_y = src[srcOff + 3];
+ src_C2_x = src[srcOff + 4];
+ src_C2_y = src[srcOff + 5];
+ right_P2_x = src[srcOff + 6];
+ right_P2_y = src[srcOff + 7];
+
+ left_C1_x = (left_P1_x + src_C1_x) / 2;
+ left_C1_y = (left_P1_y + src_C1_y) / 2;
+ right_C2_x = (right_P2_x + src_C2_x) / 2;
+ right_C2_y = (right_P2_y + src_C2_y) / 2;
+ Mid_x = (src_C1_x + src_C2_x) / 2;
+ Mid_y = (src_C1_y + src_C2_y) / 2;
+ left_C2_x = (left_C1_x + Mid_x) / 2;
+ left_C2_y = (left_C1_y + Mid_y) / 2;
+ right_C1_x = (Mid_x + right_C2_x) / 2;
+ right_C1_y = (Mid_y + right_C2_y) / 2;
+ Mid_x = (left_C2_x + right_C1_x) / 2;
+ Mid_y = (left_C2_y + right_C1_y) / 2;
+
+ if (left != null)
+ {
+ left[leftOff] = left_P1_x;
+ left[leftOff + 1] = left_P1_y;
+ left[leftOff + 2] = left_C1_x;
+ left[leftOff + 3] = left_C1_y;
+ left[leftOff + 4] = left_C2_x;
+ left[leftOff + 5] = left_C2_y;
+ left[leftOff + 6] = Mid_x;
+ left[leftOff + 7] = Mid_y;
+ }
+
+ if (right != null)
+ {
+ right[rightOff] = Mid_x;
+ right[rightOff + 1] = Mid_y;
+ right[rightOff + 2] = right_C1_x;
+ right[rightOff + 3] = right_C1_y;
+ right[rightOff + 4] = right_C2_x;
+ right[rightOff + 5] = right_C2_y;
+ right[rightOff + 6] = right_P2_x;
+ right[rightOff + 7] = right_P2_y;
+ }
+ }
+
+ /**
+ * Finds the non-complex roots of a cubic equation, placing the
+ * results into the same array as the equation coefficients. The
+ * following equation is being solved:
+ *
+ * <blockquote><code>eqn[3]</code> &#xb7; <i>x</i><sup>3</sup>
+ * + <code>eqn[2]</code> &#xb7; <i>x</i><sup>2</sup>
+ * + <code>eqn[1]</code> &#xb7; <i>x</i>
+ * + <code>eqn[0]</code>
+ * = 0
+ * </blockquote>
+ *
+ * <p>For some background about solving cubic equations, see the
+ * article <a
+ * href="http://planetmath.org/encyclopedia/CubicFormula.html"
+ * >&#x201c;Cubic Formula&#x201d;</a> in <a
+ * href="http://planetmath.org/" >PlanetMath</a>. For an extensive
+ * library of numerical algorithms written in the C programming
+ * language, see the <a href= "http://www.gnu.org/software/gsl/">GNU
+ * Scientific Library</a>, from which this implementation was
+ * adapted.
+ *
+ * @param eqn an array with the coefficients of the equation. When
+ * this procedure has returned, <code>eqn</code> will contain the
+ * non-complex solutions of the equation, in no particular order.
+ *
+ * @return the number of non-complex solutions. A result of 0
+ * indicates that the equation has no non-complex solutions. A
+ * result of -1 indicates that the equation is constant (i.e.,
+ * always or never zero).
+ *
+ * @see #solveCubic(double[], double[])
+ * @see QuadCurve2D#solveQuadratic(double[],double[])
+ *
+ * @author Brian Gough (bjg@network-theory.com)
+ * (original C implementation in the <a href=
+ * "http://www.gnu.org/software/gsl/">GNU Scientific Library</a>)
+ *
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ * (adaptation to Java)
+ */
+ public static int solveCubic(double[] eqn)
+ {
+ return solveCubic(eqn, eqn);
+ }
+
+ /**
+ * Finds the non-complex roots of a cubic equation. The following
+ * equation is being solved:
+ *
+ * <blockquote><code>eqn[3]</code> &#xb7; <i>x</i><sup>3</sup>
+ * + <code>eqn[2]</code> &#xb7; <i>x</i><sup>2</sup>
+ * + <code>eqn[1]</code> &#xb7; <i>x</i>
+ * + <code>eqn[0]</code>
+ * = 0
+ * </blockquote>
+ *
+ * <p>For some background about solving cubic equations, see the
+ * article <a
+ * href="http://planetmath.org/encyclopedia/CubicFormula.html"
+ * >&#x201c;Cubic Formula&#x201d;</a> in <a
+ * href="http://planetmath.org/" >PlanetMath</a>. For an extensive
+ * library of numerical algorithms written in the C programming
+ * language, see the <a href= "http://www.gnu.org/software/gsl/">GNU
+ * Scientific Library</a>, from which this implementation was
+ * adapted.
+ *
+ * @see QuadCurve2D#solveQuadratic(double[],double[])
+ *
+ * @param eqn an array with the coefficients of the equation.
+ *
+ * @param res an array into which the non-complex roots will be
+ * stored. The results may be in an arbitrary order. It is safe to
+ * pass the same array object reference for both <code>eqn</code>
+ * and <code>res</code>.
+ *
+ * @return the number of non-complex solutions. A result of 0
+ * indicates that the equation has no non-complex solutions. A
+ * result of -1 indicates that the equation is constant (i.e.,
+ * always or never zero).
+ *
+ * @author Brian Gough (bjg@network-theory.com)
+ * (original C implementation in the <a href=
+ * "http://www.gnu.org/software/gsl/">GNU Scientific Library</a>)
+ *
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ * (adaptation to Java)
+ */
+ public static int solveCubic(double[] eqn, double[] res)
+ {
+ // Adapted from poly/solve_cubic.c in the GNU Scientific Library
+ // (GSL), revision 1.7 of 2003-07-26. For the original source, see
+ // http://www.gnu.org/software/gsl/
+ //
+ // Brian Gough, the author of that code, has granted the
+ // permission to use it in GNU Classpath under the GNU Classpath
+ // license, and has assigned the copyright to the Free Software
+ // Foundation.
+ //
+ // The Java implementation is very similar to the GSL code, but
+ // not a strict one-to-one copy. For example, GSL would sort the
+ // result.
+
+ double a;
+ double b;
+ double c;
+ double q;
+ double r;
+ double Q;
+ double R;
+ double c3;
+ double Q3;
+ double R2;
+ double CR2;
+ double CQ3;
+
+ // If the cubic coefficient is zero, we have a quadratic equation.
+ c3 = eqn[3];
+ if (c3 == 0)
+ return QuadCurve2D.solveQuadratic(eqn, res);
+
+ // Divide the equation by the cubic coefficient.
+ c = eqn[0] / c3;
+ b = eqn[1] / c3;
+ a = eqn[2] / c3;
+
+ // We now need to solve x^3 + ax^2 + bx + c = 0.
+ q = a * a - 3 * b;
+ r = 2 * a * a * a - 9 * a * b + 27 * c;
+
+ Q = q / 9;
+ R = r / 54;
+
+ Q3 = Q * Q * Q;
+ R2 = R * R;
+
+ CR2 = 729 * r * r;
+ CQ3 = 2916 * q * q * q;
+
+ if (R == 0 && Q == 0)
+ {
+ // The GNU Scientific Library would return three identical
+ // solutions in this case.
+ res[0] = -a / 3;
+ return 1;
+ }
+
+ if (CR2 == CQ3)
+ {
+ /* this test is actually R2 == Q3, written in a form suitable
+ for exact computation with integers */
+ /* Due to finite precision some double roots may be missed, and
+ considered to be a pair of complex roots z = x +/- epsilon i
+ close to the real axis. */
+ double sqrtQ = Math.sqrt(Q);
+
+ if (R > 0)
+ {
+ res[0] = -2 * sqrtQ - a / 3;
+ res[1] = sqrtQ - a / 3;
+ }
+ else
+ {
+ res[0] = -sqrtQ - a / 3;
+ res[1] = 2 * sqrtQ - a / 3;
+ }
+ return 2;
+ }
+
+ if (CR2 < CQ3) /* equivalent to R2 < Q3 */
+ {
+ double sqrtQ = Math.sqrt(Q);
+ double sqrtQ3 = sqrtQ * sqrtQ * sqrtQ;
+ double theta = Math.acos(R / sqrtQ3);
+ double norm = -2 * sqrtQ;
+ res[0] = norm * Math.cos(theta / 3) - a / 3;
+ res[1] = norm * Math.cos((theta + 2.0 * Math.PI) / 3) - a / 3;
+ res[2] = norm * Math.cos((theta - 2.0 * Math.PI) / 3) - a / 3;
+
+ // The GNU Scientific Library sorts the results. We don't.
+ return 3;
+ }
+
+ double sgnR = (R >= 0 ? 1 : -1);
+ double A = -sgnR * Math.pow(Math.abs(R) + Math.sqrt(R2 - Q3), 1.0 / 3.0);
+ double B = Q / A;
+ res[0] = A + B - a / 3;
+ return 1;
+ }
+
+ /**
+ * Determines whether a position lies inside the area bounded
+ * by the curve and the straight line connecting its end points.
+ *
+ * <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180"
+ * alt="A drawing of the area spanned by the curve" />
+ *
+ * <p>The above drawing illustrates in which area points are
+ * considered &#x201c;inside&#x201d; a CubicCurve2D.
+ */
+ public boolean contains(double x, double y)
+ {
+ if (! getBounds2D().contains(x, y))
+ return false;
+
+ return ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0);
+ }
+
+ /**
+ * Determines whether a point lies inside the area bounded
+ * by the curve and the straight line connecting its end points.
+ *
+ * <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180"
+ * alt="A drawing of the area spanned by the curve" />
+ *
+ * <p>The above drawing illustrates in which area points are
+ * considered &#x201c;inside&#x201d; a CubicCurve2D.
+ */
+ public boolean contains(Point2D p)
+ {
+ return contains(p.getX(), p.getY());
+ }
+
+ /**
+ * Determines whether any part of a rectangle is inside the area bounded
+ * by the curve and the straight line connecting its end points.
+ *
+ * <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180"
+ * alt="A drawing of the area spanned by the curve" />
+ *
+ * <p>The above drawing illustrates in which area points are
+ * considered &#x201c;inside&#x201d; in a CubicCurve2D.
+ * @see #contains(double, double)
+ */
+ public boolean intersects(double x, double y, double w, double h)
+ {
+ if (! getBounds2D().contains(x, y, w, h))
+ return false;
+
+ /* Does any edge intersect? */
+ if (getAxisIntersections(x, y, true, w) != 0 /* top */
+ || getAxisIntersections(x, y + h, true, w) != 0 /* bottom */
+ || getAxisIntersections(x + w, y, false, h) != 0 /* right */
+ || getAxisIntersections(x, y, false, h) != 0) /* left */
+ return true;
+
+ /* No intersections, is any point inside? */
+ if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0)
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Determines whether any part of a Rectangle2D is inside the area bounded
+ * by the curve and the straight line connecting its end points.
+ * @see #intersects(double, double, double, double)
+ */
+ public boolean intersects(Rectangle2D r)
+ {
+ return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Determine whether a rectangle is entirely inside the area that is bounded
+ * by the curve and the straight line connecting its end points.
+ *
+ * <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180"
+ * alt="A drawing of the area spanned by the curve" />
+ *
+ * <p>The above drawing illustrates in which area points are
+ * considered &#x201c;inside&#x201d; a CubicCurve2D.
+ * @see #contains(double, double)
+ */
+ public boolean contains(double x, double y, double w, double h)
+ {
+ if (! getBounds2D().intersects(x, y, w, h))
+ return false;
+
+ /* Does any edge intersect? */
+ if (getAxisIntersections(x, y, true, w) != 0 /* top */
+ || getAxisIntersections(x, y + h, true, w) != 0 /* bottom */
+ || getAxisIntersections(x + w, y, false, h) != 0 /* right */
+ || getAxisIntersections(x, y, false, h) != 0) /* left */
+ return false;
+
+ /* No intersections, is any point inside? */
+ if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0)
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Determine whether a Rectangle2D is entirely inside the area that is
+ * bounded by the curve and the straight line connecting its end points.
+ *
+ * <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180"
+ * alt="A drawing of the area spanned by the curve" />
+ *
+ * <p>The above drawing illustrates in which area points are
+ * considered &#x201c;inside&#x201d; a CubicCurve2D.
+ * @see #contains(double, double)
+ */
+ public boolean contains(Rectangle2D r)
+ {
+ return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Determines the smallest rectangle that encloses the
+ * curve&#x2019;s start, end and control points.
+ */
+ public Rectangle getBounds()
+ {
+ return getBounds2D().getBounds();
+ }
+
+ public PathIterator getPathIterator(final AffineTransform at)
+ {
+ return new PathIterator()
+ {
+ /** Current coordinate. */
+ private int current = 0;
+
+ public int getWindingRule()
+ {
+ return WIND_NON_ZERO;
+ }
+
+ public boolean isDone()
+ {
+ return current >= 2;
+ }
+
+ public void next()
+ {
+ current++;
+ }
+
+ public int currentSegment(float[] coords)
+ {
+ int result;
+ switch (current)
+ {
+ case 0:
+ coords[0] = (float) getX1();
+ coords[1] = (float) getY1();
+ result = SEG_MOVETO;
+ break;
+ case 1:
+ coords[0] = (float) getCtrlX1();
+ coords[1] = (float) getCtrlY1();
+ coords[2] = (float) getCtrlX2();
+ coords[3] = (float) getCtrlY2();
+ coords[4] = (float) getX2();
+ coords[5] = (float) getY2();
+ result = SEG_CUBICTO;
+ break;
+ default:
+ throw new NoSuchElementException("cubic iterator out of bounds");
+ }
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 3);
+ return result;
+ }
+
+ public int currentSegment(double[] coords)
+ {
+ int result;
+ switch (current)
+ {
+ case 0:
+ coords[0] = getX1();
+ coords[1] = getY1();
+ result = SEG_MOVETO;
+ break;
+ case 1:
+ coords[0] = getCtrlX1();
+ coords[1] = getCtrlY1();
+ coords[2] = getCtrlX2();
+ coords[3] = getCtrlY2();
+ coords[4] = getX2();
+ coords[5] = getY2();
+ result = SEG_CUBICTO;
+ break;
+ default:
+ throw new NoSuchElementException("cubic iterator out of bounds");
+ }
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 3);
+ return result;
+ }
+ };
+ }
+
+ public PathIterator getPathIterator(AffineTransform at, double flatness)
+ {
+ return new FlatteningPathIterator(getPathIterator(at), flatness);
+ }
+
+ /**
+ * Create a new curve with the same contents as this one.
+ *
+ * @return the clone.
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // Impossible
+ }
+ }
+
+ /**
+ * Helper method used by contains() and intersects() methods, that
+ * returns the number of curve/line intersections on a given axis
+ * extending from a certain point.
+ *
+ * @param x x coordinate of the origin point
+ * @param y y coordinate of the origin point
+ * @param useYaxis axis used, if true the positive Y axis is used,
+ * false uses the positive X axis.
+ *
+ * This is an implementation of the line-crossings algorithm,
+ * Detailed in an article on Eric Haines' page:
+ * http://www.acm.org/tog/editors/erich/ptinpoly/
+ *
+ * A special-case not adressed in this code is self-intersections
+ * of the curve, e.g. if the axis intersects the self-itersection,
+ * the degenerate roots of the polynomial will erroneously count as
+ * a single intersection of the curve, and not two.
+ */
+ private int getAxisIntersections(double x, double y, boolean useYaxis,
+ double distance)
+ {
+ int nCrossings = 0;
+ double a0;
+ double a1;
+ double a2;
+ double a3;
+ double b0;
+ double b1;
+ double b2;
+ double b3;
+ double[] r = new double[4];
+ int nRoots;
+
+ a0 = a3 = 0.0;
+
+ if (useYaxis)
+ {
+ a0 = getY1() - y;
+ a1 = getCtrlY1() - y;
+ a2 = getCtrlY2() - y;
+ a3 = getY2() - y;
+ b0 = getX1() - x;
+ b1 = getCtrlX1() - x;
+ b2 = getCtrlX2() - x;
+ b3 = getX2() - x;
+ }
+ else
+ {
+ a0 = getX1() - x;
+ a1 = getCtrlX1() - x;
+ a2 = getCtrlX2() - x;
+ a3 = getX2() - x;
+ b0 = getY1() - y;
+ b1 = getCtrlY1() - y;
+ b2 = getCtrlY2() - y;
+ b3 = getY2() - y;
+ }
+
+ /* If the axis intersects a start/endpoint, shift it up by some small
+ amount to guarantee the line is 'inside'
+ If this is not done, bad behaviour may result for points on that axis.*/
+ if (a0 == 0.0 || a3 == 0.0)
+ {
+ double small = getFlatness() * EPSILON;
+ if (a0 == 0.0)
+ a0 -= small;
+ if (a3 == 0.0)
+ a3 -= small;
+ }
+
+ if (useYaxis)
+ {
+ if (Line2D.linesIntersect(b0, a0, b3, a3, EPSILON, 0.0, distance, 0.0))
+ nCrossings++;
+ }
+ else
+ {
+ if (Line2D.linesIntersect(a0, b0, a3, b3, 0.0, EPSILON, 0.0, distance))
+ nCrossings++;
+ }
+
+ r[0] = a0;
+ r[1] = 3 * (a1 - a0);
+ r[2] = 3 * (a2 + a0 - 2 * a1);
+ r[3] = a3 - 3 * a2 + 3 * a1 - a0;
+
+ if ((nRoots = solveCubic(r)) != 0)
+ for (int i = 0; i < nRoots; i++)
+ {
+ double t = r[i];
+ if (t >= 0.0 && t <= 1.0)
+ {
+ double crossing = -(t * t * t) * (b0 - 3 * b1 + 3 * b2 - b3)
+ + 3 * t * t * (b0 - 2 * b1 + b2)
+ + 3 * t * (b1 - b0) + b0;
+ if (crossing > 0.0 && crossing <= distance)
+ nCrossings++;
+ }
+ }
+
+ return (nCrossings);
+ }
+
+ /**
+ * A two-dimensional curve that is parameterized with a cubic
+ * function and stores coordinate values in double-precision
+ * floating-point format.
+ *
+ * @see CubicCurve2D.Float
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ */
+ public static class Double extends CubicCurve2D
+ {
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s start point.
+ */
+ public double x1;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s start point.
+ */
+ public double y1;
+
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s first control point.
+ */
+ public double ctrlx1;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s first control point.
+ */
+ public double ctrly1;
+
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s second control point.
+ */
+ public double ctrlx2;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s second control point.
+ */
+ public double ctrly2;
+
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s end point.
+ */
+ public double x2;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s end point.
+ */
+ public double y2;
+
+ /**
+ * Constructs a new CubicCurve2D that stores its coordinate values
+ * in double-precision floating-point format. All points are
+ * initially at position (0, 0).
+ */
+ public Double()
+ {
+ }
+
+ /**
+ * Constructs a new CubicCurve2D that stores its coordinate values
+ * in double-precision floating-point format, specifying the
+ * initial position of each point.
+ *
+ * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180"
+ * alt="A drawing of a CubicCurve2D" />
+ *
+ * @param x1 the <i>x</i> coordinate of the curve&#x2019;s start
+ * point.
+ *
+ * @param y1 the <i>y</i> coordinate of the curve&#x2019;s start
+ * point.
+ *
+ * @param cx1 the <i>x</i> coordinate of the curve&#x2019;s first
+ * control point.
+ *
+ * @param cy1 the <i>y</i> coordinate of the curve&#x2019;s first
+ * control point.
+ *
+ * @param cx2 the <i>x</i> coordinate of the curve&#x2019;s second
+ * control point.
+ *
+ * @param cy2 the <i>y</i> coordinate of the curve&#x2019;s second
+ * control point.
+ *
+ * @param x2 the <i>x</i> coordinate of the curve&#x2019;s end
+ * point.
+ *
+ * @param y2 the <i>y</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public Double(double x1, double y1, double cx1, double cy1, double cx2,
+ double cy2, double x2, double y2)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ ctrlx1 = cx1;
+ ctrly1 = cy1;
+ ctrlx2 = cx2;
+ ctrly2 = cy2;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s start
+ * point.
+ */
+ public double getX1()
+ {
+ return x1;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s start
+ * point.
+ */
+ public double getY1()
+ {
+ return y1;
+ }
+
+ /**
+ * Returns the curve&#x2019;s start point.
+ */
+ public Point2D getP1()
+ {
+ return new Point2D.Double(x1, y1);
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s first
+ * control point.
+ */
+ public double getCtrlX1()
+ {
+ return ctrlx1;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s first
+ * control point.
+ */
+ public double getCtrlY1()
+ {
+ return ctrly1;
+ }
+
+ /**
+ * Returns the curve&#x2019;s first control point.
+ */
+ public Point2D getCtrlP1()
+ {
+ return new Point2D.Double(ctrlx1, ctrly1);
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s second
+ * control point.
+ */
+ public double getCtrlX2()
+ {
+ return ctrlx2;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s second
+ * control point.
+ */
+ public double getCtrlY2()
+ {
+ return ctrly2;
+ }
+
+ /**
+ * Returns the curve&#x2019;s second control point.
+ */
+ public Point2D getCtrlP2()
+ {
+ return new Point2D.Double(ctrlx2, ctrly2);
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public double getX2()
+ {
+ return x2;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public double getY2()
+ {
+ return y2;
+ }
+
+ /**
+ * Returns the curve&#x2019;s end point.
+ */
+ public Point2D getP2()
+ {
+ return new Point2D.Double(x2, y2);
+ }
+
+ /**
+ * Changes the curve geometry, separately specifying each coordinate
+ * value.
+ *
+ * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180"
+ * alt="A drawing of a CubicCurve2D" />
+ *
+ * @param x1 the <i>x</i> coordinate of the curve&#x2019;s new start
+ * point.
+ *
+ * @param y1 the <i>y</i> coordinate of the curve&#x2019;s new start
+ * point.
+ *
+ * @param cx1 the <i>x</i> coordinate of the curve&#x2019;s new
+ * first control point.
+ *
+ * @param cy1 the <i>y</i> coordinate of the curve&#x2019;s new
+ * first control point.
+ *
+ * @param cx2 the <i>x</i> coordinate of the curve&#x2019;s new
+ * second control point.
+ *
+ * @param cy2 the <i>y</i> coordinate of the curve&#x2019;s new
+ * second control point.
+ *
+ * @param x2 the <i>x</i> coordinate of the curve&#x2019;s new end
+ * point.
+ *
+ * @param y2 the <i>y</i> coordinate of the curve&#x2019;s new end
+ * point.
+ */
+ public void setCurve(double x1, double y1, double cx1, double cy1,
+ double cx2, double cy2, double x2, double y2)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ ctrlx1 = cx1;
+ ctrly1 = cy1;
+ ctrlx2 = cx2;
+ ctrly2 = cy2;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+
+ /**
+ * Determines the smallest rectangle that encloses the
+ * curve&#x2019;s start, end and control points. As the
+ * illustration below shows, the invisible control points may cause
+ * the bounds to be much larger than the area that is actually
+ * covered by the curve.
+ *
+ * <p><img src="doc-files/CubicCurve2D-2.png" width="350" height="180"
+ * alt="An illustration of the bounds of a CubicCurve2D" />
+ */
+ public Rectangle2D getBounds2D()
+ {
+ double nx1 = Math.min(Math.min(x1, ctrlx1), Math.min(ctrlx2, x2));
+ double ny1 = Math.min(Math.min(y1, ctrly1), Math.min(ctrly2, y2));
+ double nx2 = Math.max(Math.max(x1, ctrlx1), Math.max(ctrlx2, x2));
+ double ny2 = Math.max(Math.max(y1, ctrly1), Math.max(ctrly2, y2));
+ return new Rectangle2D.Double(nx1, ny1, nx2 - nx1, ny2 - ny1);
+ }
+ }
+
+ /**
+ * A two-dimensional curve that is parameterized with a cubic
+ * function and stores coordinate values in single-precision
+ * floating-point format.
+ *
+ * @see CubicCurve2D.Float
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ */
+ public static class Float extends CubicCurve2D
+ {
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s start point.
+ */
+ public float x1;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s start point.
+ */
+ public float y1;
+
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s first control point.
+ */
+ public float ctrlx1;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s first control point.
+ */
+ public float ctrly1;
+
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s second control point.
+ */
+ public float ctrlx2;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s second control point.
+ */
+ public float ctrly2;
+
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s end point.
+ */
+ public float x2;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s end point.
+ */
+ public float y2;
+
+ /**
+ * Constructs a new CubicCurve2D that stores its coordinate values
+ * in single-precision floating-point format. All points are
+ * initially at position (0, 0).
+ */
+ public Float()
+ {
+ }
+
+ /**
+ * Constructs a new CubicCurve2D that stores its coordinate values
+ * in single-precision floating-point format, specifying the
+ * initial position of each point.
+ *
+ * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180"
+ * alt="A drawing of a CubicCurve2D" />
+ *
+ * @param x1 the <i>x</i> coordinate of the curve&#x2019;s start
+ * point.
+ *
+ * @param y1 the <i>y</i> coordinate of the curve&#x2019;s start
+ * point.
+ *
+ * @param cx1 the <i>x</i> coordinate of the curve&#x2019;s first
+ * control point.
+ *
+ * @param cy1 the <i>y</i> coordinate of the curve&#x2019;s first
+ * control point.
+ *
+ * @param cx2 the <i>x</i> coordinate of the curve&#x2019;s second
+ * control point.
+ *
+ * @param cy2 the <i>y</i> coordinate of the curve&#x2019;s second
+ * control point.
+ *
+ * @param x2 the <i>x</i> coordinate of the curve&#x2019;s end
+ * point.
+ *
+ * @param y2 the <i>y</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public Float(float x1, float y1, float cx1, float cy1, float cx2,
+ float cy2, float x2, float y2)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ ctrlx1 = cx1;
+ ctrly1 = cy1;
+ ctrlx2 = cx2;
+ ctrly2 = cy2;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s start
+ * point.
+ */
+ public double getX1()
+ {
+ return x1;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s start
+ * point.
+ */
+ public double getY1()
+ {
+ return y1;
+ }
+
+ /**
+ * Returns the curve&#x2019;s start point.
+ */
+ public Point2D getP1()
+ {
+ return new Point2D.Float(x1, y1);
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s first
+ * control point.
+ */
+ public double getCtrlX1()
+ {
+ return ctrlx1;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s first
+ * control point.
+ */
+ public double getCtrlY1()
+ {
+ return ctrly1;
+ }
+
+ /**
+ * Returns the curve&#x2019;s first control point.
+ */
+ public Point2D getCtrlP1()
+ {
+ return new Point2D.Float(ctrlx1, ctrly1);
+ }
+
+ /**
+ * Returns the <i>s</i> coordinate of the curve&#x2019;s second
+ * control point.
+ */
+ public double getCtrlX2()
+ {
+ return ctrlx2;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s second
+ * control point.
+ */
+ public double getCtrlY2()
+ {
+ return ctrly2;
+ }
+
+ /**
+ * Returns the curve&#x2019;s second control point.
+ */
+ public Point2D getCtrlP2()
+ {
+ return new Point2D.Float(ctrlx2, ctrly2);
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public double getX2()
+ {
+ return x2;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public double getY2()
+ {
+ return y2;
+ }
+
+ /**
+ * Returns the curve&#x2019;s end point.
+ */
+ public Point2D getP2()
+ {
+ return new Point2D.Float(x2, y2);
+ }
+
+ /**
+ * Changes the curve geometry, separately specifying each coordinate
+ * value as a double-precision floating-point number.
+ *
+ * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180"
+ * alt="A drawing of a CubicCurve2D" />
+ *
+ * @param x1 the <i>x</i> coordinate of the curve&#x2019;s new start
+ * point.
+ *
+ * @param y1 the <i>y</i> coordinate of the curve&#x2019;s new start
+ * point.
+ *
+ * @param cx1 the <i>x</i> coordinate of the curve&#x2019;s new
+ * first control point.
+ *
+ * @param cy1 the <i>y</i> coordinate of the curve&#x2019;s new
+ * first control point.
+ *
+ * @param cx2 the <i>x</i> coordinate of the curve&#x2019;s new
+ * second control point.
+ *
+ * @param cy2 the <i>y</i> coordinate of the curve&#x2019;s new
+ * second control point.
+ *
+ * @param x2 the <i>x</i> coordinate of the curve&#x2019;s new end
+ * point.
+ *
+ * @param y2 the <i>y</i> coordinate of the curve&#x2019;s new end
+ * point.
+ */
+ public void setCurve(double x1, double y1, double cx1, double cy1,
+ double cx2, double cy2, double x2, double y2)
+ {
+ this.x1 = (float) x1;
+ this.y1 = (float) y1;
+ ctrlx1 = (float) cx1;
+ ctrly1 = (float) cy1;
+ ctrlx2 = (float) cx2;
+ ctrly2 = (float) cy2;
+ this.x2 = (float) x2;
+ this.y2 = (float) y2;
+ }
+
+ /**
+ * Changes the curve geometry, separately specifying each coordinate
+ * value as a single-precision floating-point number.
+ *
+ * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180"
+ * alt="A drawing of a CubicCurve2D" />
+ *
+ * @param x1 the <i>x</i> coordinate of the curve&#x2019;s new start
+ * point.
+ *
+ * @param y1 the <i>y</i> coordinate of the curve&#x2019;s new start
+ * point.
+ *
+ * @param cx1 the <i>x</i> coordinate of the curve&#x2019;s new
+ * first control point.
+ *
+ * @param cy1 the <i>y</i> coordinate of the curve&#x2019;s new
+ * first control point.
+ *
+ * @param cx2 the <i>x</i> coordinate of the curve&#x2019;s new
+ * second control point.
+ *
+ * @param cy2 the <i>y</i> coordinate of the curve&#x2019;s new
+ * second control point.
+ *
+ * @param x2 the <i>x</i> coordinate of the curve&#x2019;s new end
+ * point.
+ *
+ * @param y2 the <i>y</i> coordinate of the curve&#x2019;s new end
+ * point.
+ */
+ public void setCurve(float x1, float y1, float cx1, float cy1, float cx2,
+ float cy2, float x2, float y2)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ ctrlx1 = cx1;
+ ctrly1 = cy1;
+ ctrlx2 = cx2;
+ ctrly2 = cy2;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+
+ /**
+ * Determines the smallest rectangle that encloses the
+ * curve&#x2019;s start, end and control points. As the
+ * illustration below shows, the invisible control points may cause
+ * the bounds to be much larger than the area that is actually
+ * covered by the curve.
+ *
+ * <p><img src="doc-files/CubicCurve2D-2.png" width="350" height="180"
+ * alt="An illustration of the bounds of a CubicCurve2D" />
+ */
+ public Rectangle2D getBounds2D()
+ {
+ float nx1 = Math.min(Math.min(x1, ctrlx1), Math.min(ctrlx2, x2));
+ float ny1 = Math.min(Math.min(y1, ctrly1), Math.min(ctrly2, y2));
+ float nx2 = Math.max(Math.max(x1, ctrlx1), Math.max(ctrlx2, x2));
+ float ny2 = Math.max(Math.max(y1, ctrly1), Math.max(ctrly2, y2));
+ return new Rectangle2D.Float(nx1, ny1, nx2 - nx1, ny2 - ny1);
+ }
+ }
+}
diff --git a/libjava/classpath/java/awt/geom/Dimension2D.java b/libjava/classpath/java/awt/geom/Dimension2D.java
new file mode 100644
index 000000000..6b5ce8830
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/Dimension2D.java
@@ -0,0 +1,118 @@
+/* Dimension2D.java -- abstraction of a dimension
+ Copyright (C) 1999, 2000, 2002 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.geom;
+
+/**
+ * This stores a dimension in 2-dimensional space - a width (along the x-axis)
+ * and height (along the y-axis). The storage is left to subclasses.
+ *
+ * @author Per Bothner (bothner@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public abstract class Dimension2D implements Cloneable
+{
+ /**
+ * The default constructor.
+ */
+ protected Dimension2D()
+ {
+ }
+
+ /**
+ * Get the width of this dimension. A negative result, while legal, is
+ * undefined in meaning.
+ *
+ * @return the width
+ */
+ public abstract double getWidth();
+
+ /**
+ * Get the height of this dimension. A negative result, while legal, is
+ * undefined in meaning.
+ *
+ * @return the height
+ */
+ public abstract double getHeight();
+
+ /**
+ * Set the size of this dimension to the requested values. Loss of precision
+ * may occur.
+ *
+ * @param w the new width
+ * @param h the new height
+ */
+ public abstract void setSize(double w, double h);
+
+ /**
+ * Set the size of this dimension to the requested value. Loss of precision
+ * may occur.
+ *
+ * @param d the dimension containing the new values
+ *
+ * @throws NullPointerException if d is null
+ */
+ public void setSize(Dimension2D d)
+ {
+ setSize(d.getWidth(), d.getHeight());
+ }
+
+ /**
+ * Create a new dimension of the same run-time type with the same contents
+ * as this one.
+ *
+ * @return the clone
+ *
+ * @exception OutOfMemoryError If there is not enough memory available.
+ *
+ * @since 1.2
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // Impossible
+ }
+ }
+} // class Dimension2D
diff --git a/libjava/classpath/java/awt/geom/Ellipse2D.java b/libjava/classpath/java/awt/geom/Ellipse2D.java
new file mode 100644
index 000000000..3bbf2f010
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/Ellipse2D.java
@@ -0,0 +1,413 @@
+/* Ellipse2D.java -- represents an ellipse in 2-D space
+ Copyright (C) 2000, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.geom;
+
+
+/**
+ * Ellipse2D is the shape of an ellipse.
+ * <BR>
+ * <img src="doc-files/Ellipse-1.png" width="347" height="221"
+ * alt="A drawing of an ellipse" /><BR>
+ * The ellipse is defined by it's bounding box (shown in red),
+ * and is defined by the implicit curve:<BR>
+ * <blockquote>(<i>x</i>/<i>a</i>)<sup>2</sup> +
+ * (<i>y</i>/<i>b</i>)<sup>2</sup> = 1<BR><BR></blockquote>
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ *
+ * @since 1.2
+ */
+public abstract class Ellipse2D extends RectangularShape
+{
+ /**
+ * Ellipse2D is defined as abstract.
+ * Implementing classes are Ellipse2D.Float and Ellipse2D.Double.
+ */
+ protected Ellipse2D()
+ {
+ }
+
+ /**
+ * Determines if a point is contained within the ellipse. <P>
+ * @param x - x coordinate of the point.
+ * @param y - y coordinate of the point.
+ * @return true if the point is within the ellipse, false otherwise.
+ */
+ public boolean contains(double x, double y)
+ {
+ double rx = getWidth() / 2;
+ double ry = getHeight() / 2;
+ double tx = (x - (getX() + rx)) / rx;
+ double ty = (y - (getY() + ry)) / ry;
+ return tx * tx + ty * ty < 1.0;
+ }
+
+ /**
+ * Determines if a rectangle is completely contained within the
+ * ellipse. <P>
+ * @param x - x coordinate of the upper-left corner of the rectangle
+ * @param y - y coordinate of the upper-left corner of the rectangle
+ * @param w - width of the rectangle
+ * @param h - height of the rectangle
+ * @return true if the rectangle is completely contained, false otherwise.
+ */
+ public boolean contains(double x, double y, double w, double h)
+ {
+ double x2 = x + w;
+ double y2 = y + h;
+ return (contains(x, y) && contains(x, y2) && contains(x2, y)
+ && contains(x2, y2));
+ }
+
+ /**
+ * Returns a PathIterator object corresponding to the ellipse.<P>
+ *
+ * Note: An ellipse cannot be represented exactly in PathIterator
+ * segments, the outline is thefore approximated with cubic
+ * Bezier segments.
+ *
+ * @param at an optional transform.
+ * @return A path iterator.
+ */
+ public PathIterator getPathIterator(AffineTransform at)
+ {
+ // An ellipse is just a complete arc.
+ return new Arc2D.ArcIterator(this, at);
+ }
+
+ /**
+ * Determines if a rectangle intersects any part of the ellipse.<P>
+ * @param x - x coordinate of the upper-left corner of the rectangle
+ * @param y - y coordinate of the upper-left corner of the rectangle
+ * @param w - width of the rectangle
+ * @param h - height of the rectangle
+ * @return true if the rectangle intersects the ellipse, false otherwise.
+ */
+ public boolean intersects(double x, double y, double w, double h)
+ {
+ Rectangle2D r = new Rectangle2D.Double(x, y, w, h);
+ if (! r.intersects(getX(), getY(), getWidth(), getHeight()))
+ return false;
+
+ if (contains(x, y) || contains(x, y + h) || contains(x + w, y)
+ || contains(x + w, y + h))
+ return true;
+
+ Line2D l1 = new Line2D.Double(getX(), getY() + (getHeight() / 2),
+ getX() + getWidth(),
+ getY() + (getHeight() / 2));
+ Line2D l2 = new Line2D.Double(getX() + (getWidth() / 2), getY(),
+ getX() + (getWidth() / 2),
+ getY() + getHeight());
+
+ if (l1.intersects(r) || l2.intersects(r))
+ return true;
+
+ return false;
+ }
+
+ /**
+ * An {@link Ellipse2D} that stores its coordinates using <code>double</code>
+ * primitives.
+ */
+ public static class Double extends Ellipse2D
+ {
+ /**
+ * The height of the ellipse.
+ */
+ public double height;
+
+ /**
+ * The width of the ellipse.
+ */
+ public double width;
+
+ /**
+ * The upper-left x coordinate of the bounding-box
+ */
+ public double x;
+
+ /**
+ * The upper-left y coordinate of the bounding-box
+ */
+ public double y;
+
+ /**
+ * Creates a new Ellipse2D with an upper-left coordinate of (0,0)
+ * and a zero size.
+ */
+ public Double()
+ {
+ }
+
+ /**
+ * Creates a new Ellipse2D within a given rectangle
+ * using double-precision coordinates.<P>
+ * @param x - x coordinate of the upper-left of the bounding rectangle
+ * @param y - y coordinate of the upper-left of the bounding rectangle
+ * @param w - width of the ellipse
+ * @param h - height of the ellipse
+ */
+ public Double(double x, double y, double w, double h)
+ {
+ this.x = x;
+ this.y = y;
+ height = h;
+ width = w;
+ }
+
+ /**
+ * Returns the bounding-box of the ellipse.
+ * @return The bounding box.
+ */
+ public Rectangle2D getBounds2D()
+ {
+ return new Rectangle2D.Double(x, y, width, height);
+ }
+
+ /**
+ * Returns the height of the ellipse.
+ * @return The height of the ellipse.
+ */
+ public double getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * Returns the width of the ellipse.
+ * @return The width of the ellipse.
+ */
+ public double getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Returns x coordinate of the upper-left corner of
+ * the ellipse's bounding-box.
+ * @return The x coordinate.
+ */
+ public double getX()
+ {
+ return x;
+ }
+
+ /**
+ * Returns y coordinate of the upper-left corner of
+ * the ellipse's bounding-box.
+ * @return The y coordinate.
+ */
+ public double getY()
+ {
+ return y;
+ }
+
+ /**
+ * Returns <code>true</code> if the ellipse encloses no area, and
+ * <code>false</code> otherwise.
+ *
+ * @return A boolean.
+ */
+ public boolean isEmpty()
+ {
+ return height <= 0 || width <= 0;
+ }
+
+ /**
+ * Sets the geometry of the ellipse's bounding box.<P>
+ *
+ * @param x - x coordinate of the upper-left of the bounding rectangle
+ * @param y - y coordinate of the upper-left of the bounding rectangle
+ * @param w - width of the ellipse
+ * @param h - height of the ellipse
+ */
+ public void setFrame(double x, double y, double w, double h)
+ {
+ this.x = x;
+ this.y = y;
+ height = h;
+ width = w;
+ }
+ } // class Double
+
+ /**
+ * An {@link Ellipse2D} that stores its coordinates using <code>float</code>
+ * primitives.
+ */
+ public static class Float extends Ellipse2D
+ {
+ /**
+ * The height of the ellipse.
+ */
+ public float height;
+
+ /**
+ * The width of the ellipse.
+ */
+ public float width;
+
+ /**
+ * The upper-left x coordinate of the bounding-box
+ */
+ public float x;
+
+ /**
+ * The upper-left y coordinate of the bounding-box
+ */
+ public float y;
+
+ /**
+ * Creates a new Ellipse2D with an upper-left coordinate of (0,0)
+ * and a zero size.
+ */
+ public Float()
+ {
+ }
+
+ /**
+ * Creates a new Ellipse2D within a given rectangle
+ * using floating-point precision.<P>
+ * @param x - x coordinate of the upper-left of the bounding rectangle
+ * @param y - y coordinate of the upper-left of the bounding rectangle
+ * @param w - width of the ellipse
+ * @param h - height of the ellipse
+ *
+ */
+ public Float(float x, float y, float w, float h)
+ {
+ this.x = x;
+ this.y = y;
+ this.height = h;
+ this.width = w;
+ }
+
+ /**
+ * Returns the bounding-box of the ellipse.
+ * @return The bounding box.
+ */
+ public Rectangle2D getBounds2D()
+ {
+ return new Rectangle2D.Float(x, y, width, height);
+ }
+
+ /**
+ * Returns the height of the ellipse.
+ * @return The height of the ellipse.
+ */
+ public double getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * Returns the width of the ellipse.
+ * @return The width of the ellipse.
+ */
+ public double getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Returns x coordinate of the upper-left corner of
+ * the ellipse's bounding-box.
+ * @return The x coordinate.
+ */
+ public double getX()
+ {
+ return x;
+ }
+
+ /**
+ * Returns y coordinate of the upper-left corner of
+ * the ellipse's bounding-box.
+ * @return The y coordinate.
+ */
+ public double getY()
+ {
+ return y;
+ }
+
+ /**
+ * Returns <code>true</code> if the ellipse encloses no area, and
+ * <code>false</code> otherwise.
+ *
+ * @return A boolean.
+ */
+ public boolean isEmpty()
+ {
+ return height <= 0 || width <= 0;
+ }
+
+ /**
+ * Sets the geometry of the ellipse's bounding box.<P>
+ *
+ * @param x - x coordinate of the upper-left of the bounding rectangle
+ * @param y - y coordinate of the upper-left of the bounding rectangle
+ * @param w - width of the ellipse
+ * @param h - height of the ellipse
+ */
+ public void setFrame(float x, float y, float w, float h)
+ {
+ this.x = x;
+ this.y = y;
+ height = h;
+ width = w;
+ }
+
+ /**
+ * Sets the geometry of the ellipse's bounding box.
+ *
+ * Note: This leads to a loss of precision.<P>
+ *
+ * @param x - x coordinate of the upper-left of the bounding rectangle
+ * @param y - y coordinate of the upper-left of the bounding rectangle
+ * @param w - width of the ellipse
+ * @param h - height of the ellipse
+ */
+ public void setFrame(double x, double y, double w, double h)
+ {
+ this.x = (float) x;
+ this.y = (float) y;
+ height = (float) h;
+ width = (float) w;
+ }
+ } // class Float
+} // class Ellipse2D
diff --git a/libjava/classpath/java/awt/geom/FlatteningPathIterator.java b/libjava/classpath/java/awt/geom/FlatteningPathIterator.java
new file mode 100644
index 000000000..629936bf7
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/FlatteningPathIterator.java
@@ -0,0 +1,579 @@
+/* FlatteningPathIterator.java -- Approximates curves by straight lines
+ Copyright (C) 2003 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.geom;
+
+import java.util.NoSuchElementException;
+
+
+/**
+ * A PathIterator for approximating curved path segments by sequences
+ * of straight lines. Instances of this class will only return
+ * segments of type {@link PathIterator#SEG_MOVETO}, {@link
+ * PathIterator#SEG_LINETO}, and {@link PathIterator#SEG_CLOSE}.
+ *
+ * <p>The accuracy of the approximation is determined by two
+ * parameters:
+ *
+ * <ul><li>The <i>flatness</i> is a threshold value for deciding when
+ * a curved segment is consided flat enough for being approximated by
+ * a single straight line. Flatness is defined as the maximal distance
+ * of a curve control point to the straight line that connects the
+ * curve start and end. A lower flatness threshold means a closer
+ * approximation. See {@link QuadCurve2D#getFlatness()} and {@link
+ * CubicCurve2D#getFlatness()} for drawings which illustrate the
+ * meaning of flatness.</li>
+ *
+ * <li>The <i>recursion limit</i> imposes an upper bound for how often
+ * a curved segment gets subdivided. A limit of <i>n</i> means that
+ * for each individual quadratic and cubic B&#xe9;zier spline
+ * segment, at most 2<sup><small><i>n</i></small></sup> {@link
+ * PathIterator#SEG_LINETO} segments will be created.</li></ul>
+ *
+ * <p><b>Memory Efficiency:</b> The memory consumption grows linearly
+ * with the recursion limit. Neither the <i>flatness</i> parameter nor
+ * the number of segments in the flattened path will affect the memory
+ * consumption.
+ *
+ * <p><b>Thread Safety:</b> Multiple threads can safely work on
+ * separate instances of this class. However, multiple threads should
+ * not concurrently access the same instance, as no synchronization is
+ * performed.
+ *
+ * @see <a href="doc-files/FlatteningPathIterator-1.html"
+ * >Implementation Note</a>
+ *
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ *
+ * @since 1.2
+ */
+public class FlatteningPathIterator
+ implements PathIterator
+{
+ /**
+ * The PathIterator whose curved segments are being approximated.
+ */
+ private final PathIterator srcIter;
+
+
+ /**
+ * The square of the flatness threshold value, which determines when
+ * a curve segment is considered flat enough that no further
+ * subdivision is needed.
+ *
+ * <p>Calculating flatness actually produces the squared flatness
+ * value. To avoid the relatively expensive calculation of a square
+ * root for each curve segment, we perform all flatness comparisons
+ * on squared values.
+ *
+ * @see QuadCurve2D#getFlatnessSq()
+ * @see CubicCurve2D#getFlatnessSq()
+ */
+ private final double flatnessSq;
+
+
+ /**
+ * The maximal number of subdivions that are performed to
+ * approximate a quadratic or cubic curve segment.
+ */
+ private final int recursionLimit;
+
+
+ /**
+ * A stack for holding the coordinates of subdivided segments.
+ *
+ * @see <a href="doc-files/FlatteningPathIterator-1.html"
+ * >Implementation Note</a>
+ */
+ private double[] stack;
+
+
+ /**
+ * The current stack size.
+ *
+ * @see <a href="doc-files/FlatteningPathIterator-1.html"
+ * >Implementation Note</a>
+ */
+ private int stackSize;
+
+
+ /**
+ * The number of recursions that were performed to arrive at
+ * a segment on the stack.
+ *
+ * @see <a href="doc-files/FlatteningPathIterator-1.html"
+ * >Implementation Note</a>
+ */
+ private int[] recLevel;
+
+
+
+ private final double[] scratch = new double[6];
+
+
+ /**
+ * The segment type of the last segment that was returned by
+ * the source iterator.
+ */
+ private int srcSegType;
+
+
+ /**
+ * The current <i>x</i> position of the source iterator.
+ */
+ private double srcPosX;
+
+
+ /**
+ * The current <i>y</i> position of the source iterator.
+ */
+ private double srcPosY;
+
+
+ /**
+ * A flag that indicates when this path iterator has finished its
+ * iteration over path segments.
+ */
+ private boolean done;
+
+
+ /**
+ * Constructs a new PathIterator for approximating an input
+ * PathIterator with straight lines. The approximation works by
+ * recursive subdivisons, until the specified flatness threshold is
+ * not exceeded.
+ *
+ * <p>There will not be more than 10 nested recursion steps, which
+ * means that a single <code>SEG_QUADTO</code> or
+ * <code>SEG_CUBICTO</code> segment is approximated by at most
+ * 2<sup><small>10</small></sup> = 1024 straight lines.
+ */
+ public FlatteningPathIterator(PathIterator src, double flatness)
+ {
+ this(src, flatness, 10);
+ }
+
+
+ /**
+ * Constructs a new PathIterator for approximating an input
+ * PathIterator with straight lines. The approximation works by
+ * recursive subdivisons, until the specified flatness threshold is
+ * not exceeded. Additionally, the number of recursions is also
+ * bound by the specified recursion limit.
+ */
+ public FlatteningPathIterator(PathIterator src, double flatness,
+ int limit)
+ {
+ if (flatness < 0 || limit < 0)
+ throw new IllegalArgumentException();
+
+ srcIter = src;
+ flatnessSq = flatness * flatness;
+ recursionLimit = limit;
+ fetchSegment();
+ }
+
+
+ /**
+ * Returns the maximally acceptable flatness.
+ *
+ * @see QuadCurve2D#getFlatness()
+ * @see CubicCurve2D#getFlatness()
+ */
+ public double getFlatness()
+ {
+ return Math.sqrt(flatnessSq);
+ }
+
+
+ /**
+ * Returns the maximum number of recursive curve subdivisions.
+ */
+ public int getRecursionLimit()
+ {
+ return recursionLimit;
+ }
+
+
+ // Documentation will be copied from PathIterator.
+ public int getWindingRule()
+ {
+ return srcIter.getWindingRule();
+ }
+
+
+ // Documentation will be copied from PathIterator.
+ public boolean isDone()
+ {
+ return done;
+ }
+
+
+ // Documentation will be copied from PathIterator.
+ public void next()
+ {
+ if (stackSize > 0)
+ {
+ --stackSize;
+ if (stackSize > 0)
+ {
+ switch (srcSegType)
+ {
+ case PathIterator.SEG_QUADTO:
+ subdivideQuadratic();
+ return;
+
+ case PathIterator.SEG_CUBICTO:
+ subdivideCubic();
+ return;
+
+ default:
+ throw new IllegalStateException();
+ }
+ }
+ }
+
+ srcIter.next();
+ fetchSegment();
+ }
+
+
+ // Documentation will be copied from PathIterator.
+ public int currentSegment(double[] coords)
+ {
+ if (done)
+ throw new NoSuchElementException();
+
+ switch (srcSegType)
+ {
+ case PathIterator.SEG_CLOSE:
+ return srcSegType;
+
+ case PathIterator.SEG_MOVETO:
+ case PathIterator.SEG_LINETO:
+ coords[0] = srcPosX;
+ coords[1] = srcPosY;
+ return srcSegType;
+
+ case PathIterator.SEG_QUADTO:
+ if (stackSize == 0)
+ {
+ coords[0] = srcPosX;
+ coords[1] = srcPosY;
+ }
+ else
+ {
+ int sp = stack.length - 4 * stackSize;
+ coords[0] = stack[sp + 2];
+ coords[1] = stack[sp + 3];
+ }
+ return PathIterator.SEG_LINETO;
+
+ case PathIterator.SEG_CUBICTO:
+ if (stackSize == 0)
+ {
+ coords[0] = srcPosX;
+ coords[1] = srcPosY;
+ }
+ else
+ {
+ int sp = stack.length - 6 * stackSize;
+ coords[0] = stack[sp + 4];
+ coords[1] = stack[sp + 5];
+ }
+ return PathIterator.SEG_LINETO;
+ }
+
+ throw new IllegalStateException();
+ }
+
+
+ // Documentation will be copied from PathIterator.
+ public int currentSegment(float[] coords)
+ {
+ if (done)
+ throw new NoSuchElementException();
+
+ switch (srcSegType)
+ {
+ case PathIterator.SEG_CLOSE:
+ return srcSegType;
+
+ case PathIterator.SEG_MOVETO:
+ case PathIterator.SEG_LINETO:
+ coords[0] = (float) srcPosX;
+ coords[1] = (float) srcPosY;
+ return srcSegType;
+
+ case PathIterator.SEG_QUADTO:
+ if (stackSize == 0)
+ {
+ coords[0] = (float) srcPosX;
+ coords[1] = (float) srcPosY;
+ }
+ else
+ {
+ int sp = stack.length - 4 * stackSize;
+ coords[0] = (float) stack[sp + 2];
+ coords[1] = (float) stack[sp + 3];
+ }
+ return PathIterator.SEG_LINETO;
+
+ case PathIterator.SEG_CUBICTO:
+ if (stackSize == 0)
+ {
+ coords[0] = (float) srcPosX;
+ coords[1] = (float) srcPosY;
+ }
+ else
+ {
+ int sp = stack.length - 6 * stackSize;
+ coords[0] = (float) stack[sp + 4];
+ coords[1] = (float) stack[sp + 5];
+ }
+ return PathIterator.SEG_LINETO;
+ }
+
+ throw new IllegalStateException();
+ }
+
+
+ /**
+ * Fetches the next segment from the source iterator.
+ */
+ private void fetchSegment()
+ {
+ int sp;
+
+ if (srcIter.isDone())
+ {
+ done = true;
+ return;
+ }
+
+ srcSegType = srcIter.currentSegment(scratch);
+
+ switch (srcSegType)
+ {
+ case PathIterator.SEG_CLOSE:
+ return;
+
+ case PathIterator.SEG_MOVETO:
+ case PathIterator.SEG_LINETO:
+ srcPosX = scratch[0];
+ srcPosY = scratch[1];
+ return;
+
+ case PathIterator.SEG_QUADTO:
+ if (recursionLimit == 0)
+ {
+ srcPosX = scratch[2];
+ srcPosY = scratch[3];
+ stackSize = 0;
+ return;
+ }
+ sp = 4 * recursionLimit;
+ stackSize = 1;
+ if (stack == null)
+ {
+ stack = new double[sp + /* 4 + 2 */ 6];
+ recLevel = new int[recursionLimit + 1];
+ }
+ recLevel[0] = 0;
+ stack[sp] = srcPosX; // P1.x
+ stack[sp + 1] = srcPosY; // P1.y
+ stack[sp + 2] = scratch[0]; // C.x
+ stack[sp + 3] = scratch[1]; // C.y
+ srcPosX = stack[sp + 4] = scratch[2]; // P2.x
+ srcPosY = stack[sp + 5] = scratch[3]; // P2.y
+ subdivideQuadratic();
+ break;
+
+ case PathIterator.SEG_CUBICTO:
+ if (recursionLimit == 0)
+ {
+ srcPosX = scratch[4];
+ srcPosY = scratch[5];
+ stackSize = 0;
+ return;
+ }
+ sp = 6 * recursionLimit;
+ stackSize = 1;
+ if ((stack == null) || (stack.length < sp + 8))
+ {
+ stack = new double[sp + /* 6 + 2 */ 8];
+ recLevel = new int[recursionLimit + 1];
+ }
+ recLevel[0] = 0;
+ stack[sp] = srcPosX; // P1.x
+ stack[sp + 1] = srcPosY; // P1.y
+ stack[sp + 2] = scratch[0]; // C1.x
+ stack[sp + 3] = scratch[1]; // C1.y
+ stack[sp + 4] = scratch[2]; // C2.x
+ stack[sp + 5] = scratch[3]; // C2.y
+ srcPosX = stack[sp + 6] = scratch[4]; // P2.x
+ srcPosY = stack[sp + 7] = scratch[5]; // P2.y
+ subdivideCubic();
+ return;
+ }
+ }
+
+
+ /**
+ * Repeatedly subdivides the quadratic curve segment that is on top
+ * of the stack. The iteration terminates when the recursion limit
+ * has been reached, or when the resulting segment is flat enough.
+ */
+ private void subdivideQuadratic()
+ {
+ int sp;
+ int level;
+
+ sp = stack.length - 4 * stackSize - 2;
+ level = recLevel[stackSize - 1];
+ while ((level < recursionLimit)
+ && (QuadCurve2D.getFlatnessSq(stack, sp) >= flatnessSq))
+ {
+ recLevel[stackSize] = recLevel[stackSize - 1] = ++level;
+ QuadCurve2D.subdivide(stack, sp, stack, sp - 4, stack, sp);
+ ++stackSize;
+ sp -= 4;
+ }
+ }
+
+
+ /**
+ * Repeatedly subdivides the cubic curve segment that is on top
+ * of the stack. The iteration terminates when the recursion limit
+ * has been reached, or when the resulting segment is flat enough.
+ */
+ private void subdivideCubic()
+ {
+ int sp;
+ int level;
+
+ sp = stack.length - 6 * stackSize - 2;
+ level = recLevel[stackSize - 1];
+ while ((level < recursionLimit)
+ && (CubicCurve2D.getFlatnessSq(stack, sp) >= flatnessSq))
+ {
+ recLevel[stackSize] = recLevel[stackSize - 1] = ++level;
+
+ CubicCurve2D.subdivide(stack, sp, stack, sp - 6, stack, sp);
+ ++stackSize;
+ sp -= 6;
+ }
+ }
+
+
+ /* These routines were useful for debugging. Since they would
+ * just bloat the implementation, they are commented out.
+ *
+ *
+
+ private static String segToString(int segType, double[] d, int offset)
+ {
+ String s;
+
+ switch (segType)
+ {
+ case PathIterator.SEG_CLOSE:
+ return "SEG_CLOSE";
+
+ case PathIterator.SEG_MOVETO:
+ return "SEG_MOVETO (" + d[offset] + ", " + d[offset + 1] + ")";
+
+ case PathIterator.SEG_LINETO:
+ return "SEG_LINETO (" + d[offset] + ", " + d[offset + 1] + ")";
+
+ case PathIterator.SEG_QUADTO:
+ return "SEG_QUADTO (" + d[offset] + ", " + d[offset + 1]
+ + ") (" + d[offset + 2] + ", " + d[offset + 3] + ")";
+
+ case PathIterator.SEG_CUBICTO:
+ return "SEG_CUBICTO (" + d[offset] + ", " + d[offset + 1]
+ + ") (" + d[offset + 2] + ", " + d[offset + 3]
+ + ") (" + d[offset + 4] + ", " + d[offset + 5] + ")";
+ }
+
+ throw new IllegalStateException();
+ }
+
+
+ private void dumpQuadraticStack(String msg)
+ {
+ int sp = stack.length - 4 * stackSize - 2;
+ int i = 0;
+ System.err.print(" " + msg + ":");
+ while (sp < stack.length)
+ {
+ System.err.print(" (" + stack[sp] + ", " + stack[sp+1] + ")");
+ if (i < recLevel.length)
+ System.out.print("/" + recLevel[i++]);
+ if (sp + 3 < stack.length)
+ System.err.print(" [" + stack[sp+2] + ", " + stack[sp+3] + "]");
+ sp += 4;
+ }
+ System.err.println();
+ }
+
+
+ private void dumpCubicStack(String msg)
+ {
+ int sp = stack.length - 6 * stackSize - 2;
+ int i = 0;
+ System.err.print(" " + msg + ":");
+ while (sp < stack.length)
+ {
+ System.err.print(" (" + stack[sp] + ", " + stack[sp+1] + ")");
+ if (i < recLevel.length)
+ System.out.print("/" + recLevel[i++]);
+ if (sp + 3 < stack.length)
+ {
+ System.err.print(" [" + stack[sp+2] + ", " + stack[sp+3] + "]");
+ System.err.print(" [" + stack[sp+4] + ", " + stack[sp+5] + "]");
+ }
+ sp += 6;
+ }
+ System.err.println();
+ }
+
+ *
+ *
+ */
+}
diff --git a/libjava/classpath/java/awt/geom/GeneralPath.java b/libjava/classpath/java/awt/geom/GeneralPath.java
new file mode 100644
index 000000000..99f1905e2
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/GeneralPath.java
@@ -0,0 +1,992 @@
+/* GeneralPath.java -- represents a shape built from subpaths
+ Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.geom;
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+
+
+/**
+ * A general geometric path, consisting of any number of subpaths
+ * constructed out of straight lines and cubic or quadratic Bezier
+ * curves.
+ *
+ * <p>The inside of the curve is defined for drawing purposes by a winding
+ * rule. Either the WIND_EVEN_ODD or WIND_NON_ZERO winding rule can be chosen.
+ *
+ * <p><img src="doc-files/GeneralPath-1.png" width="300" height="210"
+ * alt="A drawing of a GeneralPath" />
+ * <p>The EVEN_ODD winding rule defines a point as inside a path if:
+ * A ray from the point towards infinity in an arbitrary direction
+ * intersects the path an odd number of times. Points <b>A</b> and
+ * <b>C</b> in the image are considered to be outside the path.
+ * (both intersect twice)
+ * Point <b>B</b> intersects once, and is inside.
+ *
+ * <p>The NON_ZERO winding rule defines a point as inside a path if:
+ * The path intersects the ray in an equal number of opposite directions.
+ * Point <b>A</b> in the image is outside (one intersection in the
+ * &#x2019;up&#x2019;
+ * direction, one in the &#x2019;down&#x2019; direction) Point <b>B</b> in
+ * the image is inside (one intersection &#x2019;down&#x2019;)
+ * Point <b>C</b> in the image is inside (two intersections in the
+ * &#x2019;down&#x2019; direction)
+ *
+ * @see Line2D
+ * @see CubicCurve2D
+ * @see QuadCurve2D
+ *
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ * @author Sven de Marothy (sven@physto.se)
+ *
+ * @since 1.2
+ */
+public final class GeneralPath implements Shape, Cloneable
+{
+ /** Same constant as {@link PathIterator#WIND_EVEN_ODD}. */
+ public static final int WIND_EVEN_ODD = PathIterator.WIND_EVEN_ODD;
+
+ /** Same constant as {@link PathIterator#WIND_NON_ZERO}. */
+ public static final int WIND_NON_ZERO = PathIterator.WIND_NON_ZERO;
+
+ /** Initial size if not specified. */
+ private static final int INIT_SIZE = 10;
+
+ /** A big number, but not so big it can't survive a few float operations */
+ private static final double BIG_VALUE = Double.MAX_VALUE / 10.0;
+
+ /** The winding rule.
+ * This is package-private to avoid an accessor method.
+ */
+ int rule;
+
+ /**
+ * The path type in points. Note that xpoints[index] and ypoints[index] maps
+ * to types[index]; the control points of quad and cubic paths map as
+ * well but are ignored.
+ * This is package-private to avoid an accessor method.
+ */
+ byte[] types;
+
+ /**
+ * The list of all points seen. Since you can only append floats, it makes
+ * sense for these to be float[]. I have no idea why Sun didn't choose to
+ * allow a general path of double precision points.
+ * Note: Storing x and y coords seperately makes for a slower transforms,
+ * But it speeds up and simplifies box-intersection checking a lot.
+ * These are package-private to avoid accessor methods.
+ */
+ float[] xpoints;
+ float[] ypoints;
+
+ /** The index of the most recent moveto point, or null. */
+ private int subpath = -1;
+
+ /** The next available index into points.
+ * This is package-private to avoid an accessor method.
+ */
+ int index;
+
+ /**
+ * Constructs a GeneralPath with the default (NON_ZERO)
+ * winding rule and initial capacity (20).
+ */
+ public GeneralPath()
+ {
+ this(WIND_NON_ZERO, INIT_SIZE);
+ }
+
+ /**
+ * Constructs a GeneralPath with a specific winding rule
+ * and the default initial capacity (20).
+ * @param rule the winding rule ({@link #WIND_NON_ZERO} or
+ * {@link #WIND_EVEN_ODD})
+ *
+ * @throws IllegalArgumentException if <code>rule</code> is not one of the
+ * listed values.
+ */
+ public GeneralPath(int rule)
+ {
+ this(rule, INIT_SIZE);
+ }
+
+ /**
+ * Constructs a GeneralPath with a specific winding rule
+ * and the initial capacity. The initial capacity should be
+ * the approximate number of path segments to be used.
+ * @param rule the winding rule ({@link #WIND_NON_ZERO} or
+ * {@link #WIND_EVEN_ODD})
+ * @param capacity the inital capacity, in path segments
+ *
+ * @throws IllegalArgumentException if <code>rule</code> is not one of the
+ * listed values.
+ */
+ public GeneralPath(int rule, int capacity)
+ {
+ if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO)
+ throw new IllegalArgumentException();
+ this.rule = rule;
+ if (capacity < INIT_SIZE)
+ capacity = INIT_SIZE;
+ types = new byte[capacity];
+ xpoints = new float[capacity];
+ ypoints = new float[capacity];
+ }
+
+ /**
+ * Constructs a GeneralPath from an arbitrary shape object.
+ * The Shapes PathIterator path and winding rule will be used.
+ *
+ * @param s the shape (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>shape</code> is <code>null</code>.
+ */
+ public GeneralPath(Shape s)
+ {
+ types = new byte[INIT_SIZE];
+ xpoints = new float[INIT_SIZE];
+ ypoints = new float[INIT_SIZE];
+ PathIterator pi = s.getPathIterator(null);
+ setWindingRule(pi.getWindingRule());
+ append(pi, false);
+ }
+
+ /**
+ * Adds a new point to a path.
+ *
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ */
+ public void moveTo(float x, float y)
+ {
+ subpath = index;
+ ensureSize(index + 1);
+ types[index] = PathIterator.SEG_MOVETO;
+ xpoints[index] = x;
+ ypoints[index++] = y;
+ }
+
+ /**
+ * Appends a straight line to the current path.
+ * @param x x coordinate of the line endpoint.
+ * @param y y coordinate of the line endpoint.
+ */
+ public void lineTo(float x, float y)
+ {
+ ensureSize(index + 1);
+ types[index] = PathIterator.SEG_LINETO;
+ xpoints[index] = x;
+ ypoints[index++] = y;
+ }
+
+ /**
+ * Appends a quadratic Bezier curve to the current path.
+ * @param x1 x coordinate of the control point
+ * @param y1 y coordinate of the control point
+ * @param x2 x coordinate of the curve endpoint.
+ * @param y2 y coordinate of the curve endpoint.
+ */
+ public void quadTo(float x1, float y1, float x2, float y2)
+ {
+ ensureSize(index + 2);
+ types[index] = PathIterator.SEG_QUADTO;
+ xpoints[index] = x1;
+ ypoints[index++] = y1;
+ xpoints[index] = x2;
+ ypoints[index++] = y2;
+ }
+
+ /**
+ * Appends a cubic Bezier curve to the current path.
+ * @param x1 x coordinate of the first control point
+ * @param y1 y coordinate of the first control point
+ * @param x2 x coordinate of the second control point
+ * @param y2 y coordinate of the second control point
+ * @param x3 x coordinate of the curve endpoint.
+ * @param y3 y coordinate of the curve endpoint.
+ */
+ public void curveTo(float x1, float y1, float x2, float y2, float x3,
+ float y3)
+ {
+ ensureSize(index + 3);
+ types[index] = PathIterator.SEG_CUBICTO;
+ xpoints[index] = x1;
+ ypoints[index++] = y1;
+ xpoints[index] = x2;
+ ypoints[index++] = y2;
+ xpoints[index] = x3;
+ ypoints[index++] = y3;
+ }
+
+ /**
+ * Closes the current subpath by drawing a line
+ * back to the point of the last moveTo, unless the path is already closed.
+ */
+ public void closePath()
+ {
+ if (index >= 1 && types[index - 1] == PathIterator.SEG_CLOSE)
+ return;
+ ensureSize(index + 1);
+ types[index] = PathIterator.SEG_CLOSE;
+ xpoints[index] = xpoints[subpath];
+ ypoints[index++] = ypoints[subpath];
+ }
+
+ /**
+ * Appends the segments of a Shape to the path. If <code>connect</code> is
+ * true, the new path segments are connected to the existing one with a line.
+ * The winding rule of the Shape is ignored.
+ *
+ * @param s the shape (<code>null</code> not permitted).
+ * @param connect whether to connect the new shape to the existing path.
+ *
+ * @throws NullPointerException if <code>s</code> is <code>null</code>.
+ */
+ public void append(Shape s, boolean connect)
+ {
+ append(s.getPathIterator(null), connect);
+ }
+
+ /**
+ * Appends the segments of a PathIterator to this GeneralPath.
+ * Optionally, the initial {@link PathIterator#SEG_MOVETO} segment
+ * of the appended path is changed into a {@link
+ * PathIterator#SEG_LINETO} segment.
+ *
+ * @param iter the PathIterator specifying which segments shall be
+ * appended (<code>null</code> not permitted).
+ *
+ * @param connect <code>true</code> for substituting the initial
+ * {@link PathIterator#SEG_MOVETO} segment by a {@link
+ * PathIterator#SEG_LINETO}, or <code>false</code> for not
+ * performing any substitution. If this GeneralPath is currently
+ * empty, <code>connect</code> is assumed to be <code>false</code>,
+ * thus leaving the initial {@link PathIterator#SEG_MOVETO}
+ * unchanged.
+ */
+ public void append(PathIterator iter, boolean connect)
+ {
+ // A bad implementation of this method had caused Classpath bug #6076.
+ float[] f = new float[6];
+ while (! iter.isDone())
+ {
+ switch (iter.currentSegment(f))
+ {
+ case PathIterator.SEG_MOVETO:
+ if (! connect || (index == 0))
+ {
+ moveTo(f[0], f[1]);
+ break;
+ }
+ if ((index >= 1) && (types[index - 1] == PathIterator.SEG_CLOSE)
+ && (f[0] == xpoints[index - 1])
+ && (f[1] == ypoints[index - 1]))
+ break;
+
+ // Fall through.
+ case PathIterator.SEG_LINETO:
+ lineTo(f[0], f[1]);
+ break;
+ case PathIterator.SEG_QUADTO:
+ quadTo(f[0], f[1], f[2], f[3]);
+ break;
+ case PathIterator.SEG_CUBICTO:
+ curveTo(f[0], f[1], f[2], f[3], f[4], f[5]);
+ break;
+ case PathIterator.SEG_CLOSE:
+ closePath();
+ break;
+ }
+
+ connect = false;
+ iter.next();
+ }
+ }
+
+ /**
+ * Returns the path&#x2019;s current winding rule.
+ *
+ * @return {@link #WIND_EVEN_ODD} or {@link #WIND_NON_ZERO}.
+ */
+ public int getWindingRule()
+ {
+ return rule;
+ }
+
+ /**
+ * Sets the path&#x2019;s winding rule, which controls which areas are
+ * considered &#x2019;inside&#x2019; or &#x2019;outside&#x2019; the path
+ * on drawing. Valid rules are WIND_EVEN_ODD for an even-odd winding rule,
+ * or WIND_NON_ZERO for a non-zero winding rule.
+ *
+ * @param rule the rule ({@link #WIND_EVEN_ODD} or {@link #WIND_NON_ZERO}).
+ */
+ public void setWindingRule(int rule)
+ {
+ if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO)
+ throw new IllegalArgumentException();
+ this.rule = rule;
+ }
+
+ /**
+ * Returns the current appending point of the path.
+ *
+ * @return The point.
+ */
+ public Point2D getCurrentPoint()
+ {
+ if (subpath < 0)
+ return null;
+ return new Point2D.Float(xpoints[index - 1], ypoints[index - 1]);
+ }
+
+ /**
+ * Resets the path. All points and segments are destroyed.
+ */
+ public void reset()
+ {
+ subpath = -1;
+ index = 0;
+ }
+
+ /**
+ * Applies a transform to the path.
+ *
+ * @param xform the transform (<code>null</code> not permitted).
+ */
+ public void transform(AffineTransform xform)
+ {
+ double nx;
+ double ny;
+ double[] m = new double[6];
+ xform.getMatrix(m);
+ for (int i = 0; i < index; i++)
+ {
+ nx = m[0] * xpoints[i] + m[2] * ypoints[i] + m[4];
+ ny = m[1] * xpoints[i] + m[3] * ypoints[i] + m[5];
+ xpoints[i] = (float) nx;
+ ypoints[i] = (float) ny;
+ }
+ }
+
+ /**
+ * Creates a transformed version of the path.
+ * @param xform the transform to apply
+ * @return a new transformed GeneralPath
+ */
+ public Shape createTransformedShape(AffineTransform xform)
+ {
+ GeneralPath p = new GeneralPath(this);
+ p.transform(xform);
+ return p;
+ }
+
+ /**
+ * Returns the path&#x2019;s bounding box.
+ */
+ public Rectangle getBounds()
+ {
+ return getBounds2D().getBounds();
+ }
+
+ /**
+ * Returns the path&#x2019;s bounding box, in <code>float</code> precision
+ */
+ public Rectangle2D getBounds2D()
+ {
+ float x1;
+ float y1;
+ float x2;
+ float y2;
+
+ if (index > 0)
+ {
+ x1 = x2 = xpoints[0];
+ y1 = y2 = ypoints[0];
+ }
+ else
+ x1 = x2 = y1 = y2 = 0.0f;
+
+ for (int i = 0; i < index; i++)
+ {
+ x1 = Math.min(xpoints[i], x1);
+ y1 = Math.min(ypoints[i], y1);
+ x2 = Math.max(xpoints[i], x2);
+ y2 = Math.max(ypoints[i], y2);
+ }
+ return (new Rectangle2D.Float(x1, y1, x2 - x1, y2 - y1));
+ }
+
+ /**
+ * Evaluates if a point is within the GeneralPath,
+ * The NON_ZERO winding rule is used, regardless of the
+ * set winding rule.
+ * @param x x coordinate of the point to evaluate
+ * @param y y coordinate of the point to evaluate
+ * @return true if the point is within the path, false otherwise
+ */
+ public boolean contains(double x, double y)
+ {
+ return (getWindingNumber(x, y) != 0);
+ }
+
+ /**
+ * Evaluates if a Point2D is within the GeneralPath,
+ * The NON_ZERO winding rule is used, regardless of the
+ * set winding rule.
+ * @param p The Point2D to evaluate
+ * @return true if the point is within the path, false otherwise
+ */
+ public boolean contains(Point2D p)
+ {
+ return contains(p.getX(), p.getY());
+ }
+
+ /**
+ * Evaluates if a rectangle is completely contained within the path.
+ * This method will return false in the cases when the box
+ * intersects an inner segment of the path.
+ * (i.e.: The method is accurate for the EVEN_ODD winding rule)
+ */
+ public boolean contains(double x, double y, double w, double h)
+ {
+ if (! getBounds2D().intersects(x, y, w, h))
+ return false;
+
+ /* Does any edge intersect? */
+ if (getAxisIntersections(x, y, false, w) != 0 /* top */
+ || getAxisIntersections(x, y + h, false, w) != 0 /* bottom */
+ || getAxisIntersections(x + w, y, true, h) != 0 /* right */
+ || getAxisIntersections(x, y, true, h) != 0) /* left */
+ return false;
+
+ /* No intersections, is any point inside? */
+ if (getWindingNumber(x, y) != 0)
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Evaluates if a rectangle is completely contained within the path.
+ * This method will return false in the cases when the box
+ * intersects an inner segment of the path.
+ * (i.e.: The method is accurate for the EVEN_ODD winding rule)
+ * @param r the rectangle
+ * @return <code>true</code> if the rectangle is completely contained
+ * within the path, <code>false</code> otherwise
+ */
+ public boolean contains(Rectangle2D r)
+ {
+ return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Evaluates if a rectangle intersects the path.
+ * @param x x coordinate of the rectangle
+ * @param y y coordinate of the rectangle
+ * @param w width of the rectangle
+ * @param h height of the rectangle
+ * @return <code>true</code> if the rectangle intersects the path,
+ * <code>false</code> otherwise
+ */
+ public boolean intersects(double x, double y, double w, double h)
+ {
+ /* Does any edge intersect? */
+ if (getAxisIntersections(x, y, false, w) != 0 /* top */
+ || getAxisIntersections(x, y + h, false, w) != 0 /* bottom */
+ || getAxisIntersections(x + w, y, true, h) != 0 /* right */
+ || getAxisIntersections(x, y, true, h) != 0) /* left */
+ return true;
+
+ /* No intersections, is any point inside? */
+ if (getWindingNumber(x, y) != 0)
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Evaluates if a Rectangle2D intersects the path.
+ * @param r The rectangle
+ * @return <code>true</code> if the rectangle intersects the path,
+ * <code>false</code> otherwise
+ */
+ public boolean intersects(Rectangle2D r)
+ {
+ return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * A PathIterator that iterates over the segments of a GeneralPath.
+ *
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ */
+ private static class GeneralPathIterator implements PathIterator
+ {
+ /**
+ * The number of coordinate values for each segment type.
+ */
+ private static final int[] NUM_COORDS = {
+ /* 0: SEG_MOVETO */ 1,
+ /* 1: SEG_LINETO */ 1,
+ /* 2: SEG_QUADTO */ 2,
+ /* 3: SEG_CUBICTO */ 3,
+ /* 4: SEG_CLOSE */ 0};
+
+ /**
+ * The GeneralPath whose segments are being iterated.
+ * This is package-private to avoid an accessor method.
+ */
+ final GeneralPath path;
+
+ /**
+ * The affine transformation used to transform coordinates.
+ */
+ private final AffineTransform transform;
+
+ /**
+ * The current position of the iterator.
+ */
+ private int pos;
+
+ /**
+ * Constructs a new iterator for enumerating the segments of a
+ * GeneralPath.
+ *
+ * @param path the path to enumerate
+ * @param transform an affine transformation for projecting the returned
+ * points, or <code>null</code> to return the original points
+ * without any mapping.
+ */
+ GeneralPathIterator(GeneralPath path, AffineTransform transform)
+ {
+ this.path = path;
+ this.transform = transform;
+ }
+
+ /**
+ * Returns the current winding rule of the GeneralPath.
+ */
+ public int getWindingRule()
+ {
+ return path.rule;
+ }
+
+ /**
+ * Determines whether the iterator has reached the last segment in
+ * the path.
+ */
+ public boolean isDone()
+ {
+ return pos >= path.index;
+ }
+
+ /**
+ * Advances the iterator position by one segment.
+ */
+ public void next()
+ {
+ int seg;
+
+ /*
+ * Increment pos by the number of coordinate pairs.
+ */
+ seg = path.types[pos];
+ if (seg == SEG_CLOSE)
+ pos++;
+ else
+ pos += NUM_COORDS[seg];
+ }
+
+ /**
+ * Returns the current segment in float coordinates.
+ */
+ public int currentSegment(float[] coords)
+ {
+ int seg;
+ int numCoords;
+
+ seg = path.types[pos];
+ numCoords = NUM_COORDS[seg];
+ if (numCoords > 0)
+ {
+ for (int i = 0; i < numCoords; i++)
+ {
+ coords[i << 1] = path.xpoints[pos + i];
+ coords[(i << 1) + 1] = path.ypoints[pos + i];
+ }
+
+ if (transform != null)
+ transform.transform( /* src */
+ coords, /* srcOffset */
+ 0, /* dest */ coords, /* destOffset */
+ 0, /* numPoints */ numCoords);
+ }
+ return seg;
+ }
+
+ /**
+ * Returns the current segment in double coordinates.
+ */
+ public int currentSegment(double[] coords)
+ {
+ int seg;
+ int numCoords;
+
+ seg = path.types[pos];
+ numCoords = NUM_COORDS[seg];
+ if (numCoords > 0)
+ {
+ for (int i = 0; i < numCoords; i++)
+ {
+ coords[i << 1] = (double) path.xpoints[pos + i];
+ coords[(i << 1) + 1] = (double) path.ypoints[pos + i];
+ }
+ if (transform != null)
+ transform.transform( /* src */
+ coords, /* srcOffset */
+ 0, /* dest */ coords, /* destOffset */
+ 0, /* numPoints */ numCoords);
+ }
+ return seg;
+ }
+ }
+
+ /**
+ * Creates a PathIterator for iterating along the segments of the path.
+ *
+ * @param at an affine transformation for projecting the returned
+ * points, or <code>null</code> to let the created iterator return
+ * the original points without any mapping.
+ */
+ public PathIterator getPathIterator(AffineTransform at)
+ {
+ return new GeneralPathIterator(this, at);
+ }
+
+ /**
+ * Creates a new FlatteningPathIterator for the path
+ */
+ public PathIterator getPathIterator(AffineTransform at, double flatness)
+ {
+ return new FlatteningPathIterator(getPathIterator(at), flatness);
+ }
+
+ /**
+ * Creates a new shape of the same run-time type with the same contents
+ * as this one.
+ *
+ * @return the clone
+ *
+ * @exception OutOfMemoryError If there is not enough memory available.
+ *
+ * @since 1.2
+ */
+ public Object clone()
+ {
+ // This class is final; no need to use super.clone().
+ return new GeneralPath(this);
+ }
+
+ /**
+ * Helper method - ensure the size of the data arrays,
+ * otherwise, reallocate new ones twice the size
+ *
+ * @param size the minimum array size.
+ */
+ private void ensureSize(int size)
+ {
+ if (subpath < 0)
+ throw new IllegalPathStateException("need initial moveto");
+ if (size <= xpoints.length)
+ return;
+ byte[] b = new byte[types.length << 1];
+ System.arraycopy(types, 0, b, 0, index);
+ types = b;
+ float[] f = new float[xpoints.length << 1];
+ System.arraycopy(xpoints, 0, f, 0, index);
+ xpoints = f;
+ f = new float[ypoints.length << 1];
+ System.arraycopy(ypoints, 0, f, 0, index);
+ ypoints = f;
+ }
+
+ /**
+ * Helper method - Get the total number of intersections from (x,y) along
+ * a given axis, within a given distance.
+ */
+ private int getAxisIntersections(double x, double y, boolean useYaxis,
+ double distance)
+ {
+ return (evaluateCrossings(x, y, false, useYaxis, distance));
+ }
+
+ /**
+ * Helper method - returns the winding number of a point.
+ */
+ private int getWindingNumber(double x, double y)
+ {
+ /* Evaluate the crossings from x,y to infinity on the y axis (arbitrary
+ choice). Note that we don't actually use Double.INFINITY, since that's
+ slower, and may cause problems. */
+ return (evaluateCrossings(x, y, true, true, BIG_VALUE));
+ }
+
+ /**
+ * Helper method - evaluates the number of intersections on an axis from
+ * the point (x,y) to the point (x,y+distance) or (x+distance,y).
+ * @param x x coordinate.
+ * @param y y coordinate.
+ * @param neg True if opposite-directed intersections should cancel,
+ * false to sum all intersections.
+ * @param useYaxis Use the Y axis, false uses the X axis.
+ * @param distance Interval from (x,y) on the selected axis to find
+ * intersections.
+ */
+ private int evaluateCrossings(double x, double y, boolean neg,
+ boolean useYaxis, double distance)
+ {
+ float cx = 0.0f;
+ float cy = 0.0f;
+ float firstx = 0.0f;
+ float firsty = 0.0f;
+
+ int negative = (neg) ? -1 : 1;
+ double x0;
+ double x1;
+ double x2;
+ double x3;
+ double y0;
+ double y1;
+ double y2;
+ double y3;
+ double[] r = new double[4];
+ int nRoots;
+ double epsilon = 0.0;
+ int pos = 0;
+ int windingNumber = 0;
+ boolean pathStarted = false;
+
+ if (index == 0)
+ return (0);
+ if (useYaxis)
+ {
+ float[] swap1;
+ swap1 = ypoints;
+ ypoints = xpoints;
+ xpoints = swap1;
+ double swap2;
+ swap2 = y;
+ y = x;
+ x = swap2;
+ }
+
+ /* Get a value which is hopefully small but not insignificant relative
+ the path. */
+ epsilon = ypoints[0] * 1E-7;
+
+ if(epsilon == 0)
+ epsilon = 1E-7;
+
+ pos = 0;
+ while (pos < index)
+ {
+ switch (types[pos])
+ {
+ case PathIterator.SEG_MOVETO:
+ if (pathStarted) // close old path
+ {
+ x0 = cx;
+ y0 = cy;
+ x1 = firstx;
+ y1 = firsty;
+
+ if (y0 == 0.0)
+ y0 -= epsilon;
+ if (y1 == 0.0)
+ y1 -= epsilon;
+ if (Line2D.linesIntersect(x0, y0, x1, y1,
+ epsilon, 0.0, distance, 0.0))
+ windingNumber += (y1 < y0) ? 1 : negative;
+
+ cx = firstx;
+ cy = firsty;
+ }
+ cx = firstx = xpoints[pos] - (float) x;
+ cy = firsty = ypoints[pos++] - (float) y;
+ pathStarted = true;
+ break;
+ case PathIterator.SEG_CLOSE:
+ x0 = cx;
+ y0 = cy;
+ x1 = firstx;
+ y1 = firsty;
+
+ if (y0 == 0.0)
+ y0 -= epsilon;
+ if (y1 == 0.0)
+ y1 -= epsilon;
+ if (Line2D.linesIntersect(x0, y0, x1, y1,
+ epsilon, 0.0, distance, 0.0))
+ windingNumber += (y1 < y0) ? 1 : negative;
+
+ cx = firstx;
+ cy = firsty;
+ pos++;
+ pathStarted = false;
+ break;
+ case PathIterator.SEG_LINETO:
+ x0 = cx;
+ y0 = cy;
+ x1 = xpoints[pos] - (float) x;
+ y1 = ypoints[pos++] - (float) y;
+
+ if (y0 == 0.0)
+ y0 -= epsilon;
+ if (y1 == 0.0)
+ y1 -= epsilon;
+ if (Line2D.linesIntersect(x0, y0, x1, y1,
+ epsilon, 0.0, distance, 0.0))
+ windingNumber += (y1 < y0) ? 1 : negative;
+
+ cx = xpoints[pos - 1] - (float) x;
+ cy = ypoints[pos - 1] - (float) y;
+ break;
+ case PathIterator.SEG_QUADTO:
+ x0 = cx;
+ y0 = cy;
+ x1 = xpoints[pos] - x;
+ y1 = ypoints[pos++] - y;
+ x2 = xpoints[pos] - x;
+ y2 = ypoints[pos++] - y;
+
+ /* check if curve may intersect X+ axis. */
+ if ((x0 > 0.0 || x1 > 0.0 || x2 > 0.0)
+ && (y0 * y1 <= 0 || y1 * y2 <= 0))
+ {
+ if (y0 == 0.0)
+ y0 -= epsilon;
+ if (y2 == 0.0)
+ y2 -= epsilon;
+
+ r[0] = y0;
+ r[1] = 2 * (y1 - y0);
+ r[2] = (y2 - 2 * y1 + y0);
+
+ /* degenerate roots (=tangent points) do not
+ contribute to the winding number. */
+ if ((nRoots = QuadCurve2D.solveQuadratic(r)) == 2)
+ for (int i = 0; i < nRoots; i++)
+ {
+ float t = (float) r[i];
+ if (t > 0.0f && t < 1.0f)
+ {
+ double crossing = t * t * (x2 - 2 * x1 + x0)
+ + 2 * t * (x1 - x0) + x0;
+ if (crossing >= 0.0 && crossing <= distance)
+ windingNumber += (2 * t * (y2 - 2 * y1 + y0)
+ + 2 * (y1 - y0) < 0) ? 1 : negative;
+ }
+ }
+ }
+
+ cx = xpoints[pos - 1] - (float) x;
+ cy = ypoints[pos - 1] - (float) y;
+ break;
+ case PathIterator.SEG_CUBICTO:
+ x0 = cx;
+ y0 = cy;
+ x1 = xpoints[pos] - x;
+ y1 = ypoints[pos++] - y;
+ x2 = xpoints[pos] - x;
+ y2 = ypoints[pos++] - y;
+ x3 = xpoints[pos] - x;
+ y3 = ypoints[pos++] - y;
+
+ /* check if curve may intersect X+ axis. */
+ if ((x0 > 0.0 || x1 > 0.0 || x2 > 0.0 || x3 > 0.0)
+ && (y0 * y1 <= 0 || y1 * y2 <= 0 || y2 * y3 <= 0))
+ {
+ if (y0 == 0.0)
+ y0 -= epsilon;
+ if (y3 == 0.0)
+ y3 -= epsilon;
+
+ r[0] = y0;
+ r[1] = 3 * (y1 - y0);
+ r[2] = 3 * (y2 + y0 - 2 * y1);
+ r[3] = y3 - 3 * y2 + 3 * y1 - y0;
+
+ if ((nRoots = CubicCurve2D.solveCubic(r)) != 0)
+ for (int i = 0; i < nRoots; i++)
+ {
+ float t = (float) r[i];
+ if (t > 0.0 && t < 1.0)
+ {
+ double crossing = -(t * t * t) * (x0 - 3 * x1
+ + 3 * x2 - x3)
+ + 3 * t * t * (x0 - 2 * x1 + x2)
+ + 3 * t * (x1 - x0) + x0;
+ if (crossing >= 0 && crossing <= distance)
+ windingNumber += (3 * t * t * (y3 + 3 * y1
+ - 3 * y2 - y0)
+ + 6 * t * (y0 - 2 * y1 + y2)
+ + 3 * (y1 - y0) < 0) ? 1 : negative;
+ }
+ }
+ }
+
+ cx = xpoints[pos - 1] - (float) x;
+ cy = ypoints[pos - 1] - (float) y;
+ break;
+ }
+ }
+
+ // swap coordinates back
+ if (useYaxis)
+ {
+ float[] swap;
+ swap = ypoints;
+ ypoints = xpoints;
+ xpoints = swap;
+ }
+ return (windingNumber);
+ }
+} // class GeneralPath
diff --git a/libjava/classpath/java/awt/geom/IllegalPathStateException.java b/libjava/classpath/java/awt/geom/IllegalPathStateException.java
new file mode 100644
index 000000000..4d190c748
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/IllegalPathStateException.java
@@ -0,0 +1,71 @@
+/* IllegalPathStateException.java -- an operation was in an illegal path state
+ Copyright (C) 2000, 2002 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.geom;
+
+/**
+ * Thrown when an operation on a path is in an illegal state, such as appending
+ * a segment to a <code>GeneralPath</code> without an initial moveto.
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @see GeneralPath
+ * @status updated to 1.4
+ */
+public class IllegalPathStateException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = -5158084205220481094L;
+
+ /**
+ * Create an exception with no message.
+ */
+ public IllegalPathStateException()
+ {
+ }
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param msg the message
+ */
+ public IllegalPathStateException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/java/awt/geom/Line2D.java b/libjava/classpath/java/awt/geom/Line2D.java
new file mode 100644
index 000000000..c92aab004
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/Line2D.java
@@ -0,0 +1,1182 @@
+/* Line2D.java -- represents a line in 2-D space, plus operations on a line
+ Copyright (C) 2000, 2001, 2002 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.geom;
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.util.NoSuchElementException;
+
+/**
+ * Represents a directed line bewteen two points in (x,y) Cartesian space.
+ * Remember, on-screen graphics have increasing x from left-to-right, and
+ * increasing y from top-to-bottom. The storage is left to subclasses.
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author David Gilbert
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public abstract class Line2D implements Shape, Cloneable
+{
+ /**
+ * The default constructor.
+ */
+ protected Line2D()
+ {
+ }
+
+ /**
+ * Return the x coordinate of the first point.
+ *
+ * @return the starting x coordinate
+ */
+ public abstract double getX1();
+
+ /**
+ * Return the y coordinate of the first point.
+ *
+ * @return the starting y coordinate
+ */
+ public abstract double getY1();
+
+ /**
+ * Return the first point.
+ *
+ * @return the starting point
+ */
+ public abstract Point2D getP1();
+
+ /**
+ * Return the x coordinate of the second point.
+ *
+ * @return the ending x coordinate
+ */
+ public abstract double getX2();
+
+ /**
+ * Return the y coordinate of the second point.
+ *
+ * @return the ending y coordinate
+ */
+ public abstract double getY2();
+
+ /**
+ * Return the second point.
+ *
+ * @return the ending point
+ */
+ public abstract Point2D getP2();
+
+ /**
+ * Set the coordinates of the line to the given coordinates. Loss of
+ * precision may occur due to rounding issues.
+ *
+ * @param x1 the first x coordinate
+ * @param y1 the first y coordinate
+ * @param x2 the second x coordinate
+ * @param y2 the second y coordinate
+ */
+ public abstract void setLine(double x1, double y1, double x2, double y2);
+
+ /**
+ * Set the coordinates to the given points.
+ *
+ * @param p1 the first point
+ * @param p2 the second point
+ * @throws NullPointerException if either point is null
+ */
+ public void setLine(Point2D p1, Point2D p2)
+ {
+ setLine(p1.getX(), p1.getY(), p2.getX(), p2.getY());
+ }
+
+ /**
+ * Set the coordinates to those of the given line.
+ *
+ * @param l the line to copy
+ * @throws NullPointerException if l is null
+ */
+ public void setLine(Line2D l)
+ {
+ setLine(l.getX1(), l.getY1(), l.getX2(), l.getY2());
+ }
+
+ /**
+ * Computes the relative rotation direction needed to pivot the line about
+ * the first point in order to have the second point colinear with point p.
+ * Because of floating point rounding, don't expect this to be a perfect
+ * measure of colinearity. The answer is 1 if the line has a shorter rotation
+ * in the direction of the positive X axis to the negative Y axis
+ * (counter-clockwise in the default Java coordinate system), or -1 if the
+ * shortest rotation is in the opposite direction (clockwise). If p
+ * is already colinear, the return value is -1 if it lies beyond the first
+ * point, 0 if it lies in the segment, or 1 if it lies beyond the second
+ * point. If the first and second point are coincident, this returns 0.
+ *
+ * @param x1 the first x coordinate
+ * @param y1 the first y coordinate
+ * @param x2 the second x coordinate
+ * @param y2 the second y coordinate
+ * @param px the reference x coordinate
+ * @param py the reference y coordinate
+ * @return the relative rotation direction
+ */
+ public static int relativeCCW(double x1, double y1, double x2, double y2,
+ double px, double py)
+ {
+ if ((x1 == x2 && y1 == y2)
+ || (x1 == px && y1 == py))
+ return 0; // Coincident points.
+ // Translate to the origin.
+ x2 -= x1;
+ y2 -= y1;
+ px -= x1;
+ py -= y1;
+ double slope2 = y2 / x2;
+ double slopep = py / px;
+ if (slope2 == slopep || (x2 == 0 && px == 0))
+ return y2 > 0 // Colinear.
+ ? (py < 0 ? -1 : py > y2 ? 1 : 0)
+ : (py > 0 ? -1 : py < y2 ? 1 : 0);
+ if (x2 >= 0 && slope2 >= 0)
+ return px >= 0 // Quadrant 1.
+ ? (slope2 > slopep ? 1 : -1)
+ : (slope2 < slopep ? 1 : -1);
+ if (y2 > 0)
+ return px < 0 // Quadrant 2.
+ ? (slope2 > slopep ? 1 : -1)
+ : (slope2 < slopep ? 1 : -1);
+ if (slope2 >= 0.0)
+ return px >= 0 // Quadrant 3.
+ ? (slope2 < slopep ? 1 : -1)
+ : (slope2 > slopep ? 1 : -1);
+ return px < 0 // Quadrant 4.
+ ? (slope2 < slopep ? 1 : -1)
+ : (slope2 > slopep ? 1 : -1);
+ }
+
+ /**
+ * Computes the relative rotation direction needed to pivot this line about
+ * the first point in order to have the second point colinear with point p.
+ * Because of floating point rounding, don't expect this to be a perfect
+ * measure of colinearity. The answer is 1 if the line has a shorter rotation
+ * in the direction of the positive X axis to the negative Y axis
+ * (counter-clockwise in the default Java coordinate system), or -1 if the
+ * shortest rotation is in the opposite direction (clockwise). If p
+ * is already colinear, the return value is -1 if it lies beyond the first
+ * point, 0 if it lies in the segment, or 1 if it lies beyond the second
+ * point. If the first and second point are coincident, this returns 0.
+ *
+ * @param px the reference x coordinate
+ * @param py the reference y coordinate
+ * @return the relative rotation direction
+ * @see #relativeCCW(double, double, double, double, double, double)
+ */
+ public int relativeCCW(double px, double py)
+ {
+ return relativeCCW(getX1(), getY1(), getX2(), getY2(), px, py);
+ }
+
+ /**
+ * Computes the relative rotation direction needed to pivot this line about
+ * the first point in order to have the second point colinear with point p.
+ * Because of floating point rounding, don't expect this to be a perfect
+ * measure of colinearity. The answer is 1 if the line has a shorter rotation
+ * in the direction of the positive X axis to the negative Y axis
+ * (counter-clockwise in the default Java coordinate system), or -1 if the
+ * shortest rotation is in the opposite direction (clockwise). If p
+ * is already colinear, the return value is -1 if it lies beyond the first
+ * point, 0 if it lies in the segment, or 1 if it lies beyond the second
+ * point. If the first and second point are coincident, this returns 0.
+ *
+ * @param p the reference point
+ * @return the relative rotation direction
+ * @throws NullPointerException if p is null
+ * @see #relativeCCW(double, double, double, double, double, double)
+ */
+ public int relativeCCW(Point2D p)
+ {
+ return relativeCCW(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
+ }
+
+ /**
+ * Computes twice the (signed) area of the triangle defined by the three
+ * points. This method is used for intersection testing.
+ *
+ * @param x1 the x-coordinate of the first point.
+ * @param y1 the y-coordinate of the first point.
+ * @param x2 the x-coordinate of the second point.
+ * @param y2 the y-coordinate of the second point.
+ * @param x3 the x-coordinate of the third point.
+ * @param y3 the y-coordinate of the third point.
+ *
+ * @return Twice the area.
+ */
+ private static double area2(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3)
+ {
+ return (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);
+ }
+
+ /**
+ * Returns <code>true</code> if (x3, y3) lies between (x1, y1) and (x2, y2),
+ * and false otherwise, This test assumes that the three points are
+ * collinear, and is used for intersection testing.
+ *
+ * @param x1 the x-coordinate of the first point.
+ * @param y1 the y-coordinate of the first point.
+ * @param x2 the x-coordinate of the second point.
+ * @param y2 the y-coordinate of the second point.
+ * @param x3 the x-coordinate of the third point.
+ * @param y3 the y-coordinate of the third point.
+ *
+ * @return A boolean.
+ */
+ private static boolean between(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3)
+ {
+ if (x1 != x2) {
+ return (x1 <= x3 && x3 <= x2) || (x1 >= x3 && x3 >= x2);
+ }
+ else {
+ return (y1 <= y3 && y3 <= y2) || (y1 >= y3 && y3 >= y2);
+ }
+ }
+
+ /**
+ * Test if the line segment (x1,y1)-&gt;(x2,y2) intersects the line segment
+ * (x3,y3)-&gt;(x4,y4).
+ *
+ * @param x1 the first x coordinate of the first segment
+ * @param y1 the first y coordinate of the first segment
+ * @param x2 the second x coordinate of the first segment
+ * @param y2 the second y coordinate of the first segment
+ * @param x3 the first x coordinate of the second segment
+ * @param y3 the first y coordinate of the second segment
+ * @param x4 the second x coordinate of the second segment
+ * @param y4 the second y coordinate of the second segment
+ * @return true if the segments intersect
+ */
+ public static boolean linesIntersect(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double x4, double y4)
+ {
+ double a1, a2, a3, a4;
+
+ // deal with special cases
+ if ((a1 = area2(x1, y1, x2, y2, x3, y3)) == 0.0)
+ {
+ // check if p3 is between p1 and p2 OR
+ // p4 is collinear also AND either between p1 and p2 OR at opposite ends
+ if (between(x1, y1, x2, y2, x3, y3))
+ {
+ return true;
+ }
+ else
+ {
+ if (area2(x1, y1, x2, y2, x4, y4) == 0.0)
+ {
+ return between(x3, y3, x4, y4, x1, y1)
+ || between (x3, y3, x4, y4, x2, y2);
+ }
+ else {
+ return false;
+ }
+ }
+ }
+ else if ((a2 = area2(x1, y1, x2, y2, x4, y4)) == 0.0)
+ {
+ // check if p4 is between p1 and p2 (we already know p3 is not
+ // collinear)
+ return between(x1, y1, x2, y2, x4, y4);
+ }
+
+ if ((a3 = area2(x3, y3, x4, y4, x1, y1)) == 0.0) {
+ // check if p1 is between p3 and p4 OR
+ // p2 is collinear also AND either between p1 and p2 OR at opposite ends
+ if (between(x3, y3, x4, y4, x1, y1)) {
+ return true;
+ }
+ else {
+ if (area2(x3, y3, x4, y4, x2, y2) == 0.0) {
+ return between(x1, y1, x2, y2, x3, y3)
+ || between (x1, y1, x2, y2, x4, y4);
+ }
+ else {
+ return false;
+ }
+ }
+ }
+ else if ((a4 = area2(x3, y3, x4, y4, x2, y2)) == 0.0) {
+ // check if p2 is between p3 and p4 (we already know p1 is not
+ // collinear)
+ return between(x3, y3, x4, y4, x2, y2);
+ }
+ else { // test for regular intersection
+ return ((a1 > 0.0) ^ (a2 > 0.0)) && ((a3 > 0.0) ^ (a4 > 0.0));
+ }
+ }
+
+ /**
+ * Test if this line intersects the line given by (x1,y1)-&gt;(x2,y2).
+ *
+ * @param x1 the first x coordinate of the other segment
+ * @param y1 the first y coordinate of the other segment
+ * @param x2 the second x coordinate of the other segment
+ * @param y2 the second y coordinate of the other segment
+ * @return true if the segments intersect
+ * @see #linesIntersect(double, double, double, double,
+ * double, double, double, double)
+ */
+ public boolean intersectsLine(double x1, double y1, double x2, double y2)
+ {
+ return linesIntersect(getX1(), getY1(), getX2(), getY2(),
+ x1, y1, x2, y2);
+ }
+
+ /**
+ * Test if this line intersects the given line.
+ *
+ * @param l the other segment
+ * @return true if the segments intersect
+ * @throws NullPointerException if l is null
+ * @see #linesIntersect(double, double, double, double,
+ * double, double, double, double)
+ */
+ public boolean intersectsLine(Line2D l)
+ {
+ return linesIntersect(getX1(), getY1(), getX2(), getY2(),
+ l.getX1(), l.getY1(), l.getX2(), l.getY2());
+ }
+
+ /**
+ * Measures the square of the shortest distance from the reference point
+ * to a point on the line segment. If the point is on the segment, the
+ * result will be 0.
+ *
+ * @param x1 the first x coordinate of the segment
+ * @param y1 the first y coordinate of the segment
+ * @param x2 the second x coordinate of the segment
+ * @param y2 the second y coordinate of the segment
+ * @param px the x coordinate of the point
+ * @param py the y coordinate of the point
+ * @return the square of the distance from the point to the segment
+ * @see #ptSegDist(double, double, double, double, double, double)
+ * @see #ptLineDistSq(double, double, double, double, double, double)
+ */
+ public static double ptSegDistSq(double x1, double y1, double x2, double y2,
+ double px, double py)
+ {
+ double pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
+
+ double x, y;
+ if (pd2 == 0)
+ {
+ // Points are coincident.
+ x = x1;
+ y = y2;
+ }
+ else
+ {
+ double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2;
+
+ if (u < 0)
+ {
+ // "Off the end"
+ x = x1;
+ y = y1;
+ }
+ else if (u > 1.0)
+ {
+ x = x2;
+ y = y2;
+ }
+ else
+ {
+ x = x1 + u * (x2 - x1);
+ y = y1 + u * (y2 - y1);
+ }
+ }
+
+ return (x - px) * (x - px) + (y - py) * (y - py);
+ }
+
+ /**
+ * Measures the shortest distance from the reference point to a point on
+ * the line segment. If the point is on the segment, the result will be 0.
+ *
+ * @param x1 the first x coordinate of the segment
+ * @param y1 the first y coordinate of the segment
+ * @param x2 the second x coordinate of the segment
+ * @param y2 the second y coordinate of the segment
+ * @param px the x coordinate of the point
+ * @param py the y coordinate of the point
+ * @return the distance from the point to the segment
+ * @see #ptSegDistSq(double, double, double, double, double, double)
+ * @see #ptLineDist(double, double, double, double, double, double)
+ */
+ public static double ptSegDist(double x1, double y1, double x2, double y2,
+ double px, double py)
+ {
+ return Math.sqrt(ptSegDistSq(x1, y1, x2, y2, px, py));
+ }
+
+ /**
+ * Measures the square of the shortest distance from the reference point
+ * to a point on this line segment. If the point is on the segment, the
+ * result will be 0.
+ *
+ * @param px the x coordinate of the point
+ * @param py the y coordinate of the point
+ * @return the square of the distance from the point to the segment
+ * @see #ptSegDistSq(double, double, double, double, double, double)
+ */
+ public double ptSegDistSq(double px, double py)
+ {
+ return ptSegDistSq(getX1(), getY1(), getX2(), getY2(), px, py);
+ }
+
+ /**
+ * Measures the square of the shortest distance from the reference point
+ * to a point on this line segment. If the point is on the segment, the
+ * result will be 0.
+ *
+ * @param p the point
+ * @return the square of the distance from the point to the segment
+ * @throws NullPointerException if p is null
+ * @see #ptSegDistSq(double, double, double, double, double, double)
+ */
+ public double ptSegDistSq(Point2D p)
+ {
+ return ptSegDistSq(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
+ }
+
+ /**
+ * Measures the shortest distance from the reference point to a point on
+ * this line segment. If the point is on the segment, the result will be 0.
+ *
+ * @param px the x coordinate of the point
+ * @param py the y coordinate of the point
+ * @return the distance from the point to the segment
+ * @see #ptSegDist(double, double, double, double, double, double)
+ */
+ public double ptSegDist(double px, double py)
+ {
+ return ptSegDist(getX1(), getY1(), getX2(), getY2(), px, py);
+ }
+
+ /**
+ * Measures the shortest distance from the reference point to a point on
+ * this line segment. If the point is on the segment, the result will be 0.
+ *
+ * @param p the point
+ * @return the distance from the point to the segment
+ * @throws NullPointerException if p is null
+ * @see #ptSegDist(double, double, double, double, double, double)
+ */
+ public double ptSegDist(Point2D p)
+ {
+ return ptSegDist(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
+ }
+
+ /**
+ * Measures the square of the shortest distance from the reference point
+ * to a point on the infinite line extended from the segment. If the point
+ * is on the segment, the result will be 0. If the segment is length 0,
+ * the distance is to the common endpoint.
+ *
+ * @param x1 the first x coordinate of the segment
+ * @param y1 the first y coordinate of the segment
+ * @param x2 the second x coordinate of the segment
+ * @param y2 the second y coordinate of the segment
+ * @param px the x coordinate of the point
+ * @param py the y coordinate of the point
+ * @return the square of the distance from the point to the extended line
+ * @see #ptLineDist(double, double, double, double, double, double)
+ * @see #ptSegDistSq(double, double, double, double, double, double)
+ */
+ public static double ptLineDistSq(double x1, double y1, double x2, double y2,
+ double px, double py)
+ {
+ double pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
+
+ double x, y;
+ if (pd2 == 0)
+ {
+ // Points are coincident.
+ x = x1;
+ y = y2;
+ }
+ else
+ {
+ double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2;
+ x = x1 + u * (x2 - x1);
+ y = y1 + u * (y2 - y1);
+ }
+
+ return (x - px) * (x - px) + (y - py) * (y - py);
+ }
+
+ /**
+ * Measures the shortest distance from the reference point to a point on
+ * the infinite line extended from the segment. If the point is on the
+ * segment, the result will be 0. If the segment is length 0, the distance
+ * is to the common endpoint.
+ *
+ * @param x1 the first x coordinate of the segment
+ * @param y1 the first y coordinate of the segment
+ * @param x2 the second x coordinate of the segment
+ * @param y2 the second y coordinate of the segment
+ * @param px the x coordinate of the point
+ * @param py the y coordinate of the point
+ * @return the distance from the point to the extended line
+ * @see #ptLineDistSq(double, double, double, double, double, double)
+ * @see #ptSegDist(double, double, double, double, double, double)
+ */
+ public static double ptLineDist(double x1, double y1,
+ double x2, double y2,
+ double px, double py)
+ {
+ return Math.sqrt(ptLineDistSq(x1, y1, x2, y2, px, py));
+ }
+
+ /**
+ * Measures the square of the shortest distance from the reference point
+ * to a point on the infinite line extended from this segment. If the point
+ * is on the segment, the result will be 0. If the segment is length 0,
+ * the distance is to the common endpoint.
+ *
+ * @param px the x coordinate of the point
+ * @param py the y coordinate of the point
+ * @return the square of the distance from the point to the extended line
+ * @see #ptLineDistSq(double, double, double, double, double, double)
+ */
+ public double ptLineDistSq(double px, double py)
+ {
+ return ptLineDistSq(getX1(), getY1(), getX2(), getY2(), px, py);
+ }
+
+ /**
+ * Measures the square of the shortest distance from the reference point
+ * to a point on the infinite line extended from this segment. If the point
+ * is on the segment, the result will be 0. If the segment is length 0,
+ * the distance is to the common endpoint.
+ *
+ * @param p the point
+ * @return the square of the distance from the point to the extended line
+ * @throws NullPointerException if p is null
+ * @see #ptLineDistSq(double, double, double, double, double, double)
+ */
+ public double ptLineDistSq(Point2D p)
+ {
+ return ptLineDistSq(getX1(), getY1(), getX2(), getY2(),
+ p.getX(), p.getY());
+ }
+
+ /**
+ * Measures the shortest distance from the reference point to a point on
+ * the infinite line extended from this segment. If the point is on the
+ * segment, the result will be 0. If the segment is length 0, the distance
+ * is to the common endpoint.
+ *
+ * @param px the x coordinate of the point
+ * @param py the y coordinate of the point
+ * @return the distance from the point to the extended line
+ * @see #ptLineDist(double, double, double, double, double, double)
+ */
+ public double ptLineDist(double px, double py)
+ {
+ return ptLineDist(getX1(), getY1(), getX2(), getY2(), px, py);
+ }
+
+ /**
+ * Measures the shortest distance from the reference point to a point on
+ * the infinite line extended from this segment. If the point is on the
+ * segment, the result will be 0. If the segment is length 0, the distance
+ * is to the common endpoint.
+ *
+ * @param p the point
+ * @return the distance from the point to the extended line
+ * @throws NullPointerException if p is null
+ * @see #ptLineDist(double, double, double, double, double, double)
+ */
+ public double ptLineDist(Point2D p)
+ {
+ return ptLineDist(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
+ }
+
+ /**
+ * Test if a point is contained inside the line. Since a line has no area,
+ * this returns false.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @return false; the line does not contain points
+ */
+ public boolean contains(double x, double y)
+ {
+ return false;
+ }
+
+ /**
+ * Test if a point is contained inside the line. Since a line has no area,
+ * this returns false.
+ *
+ * @param p the point
+ * @return false; the line does not contain points
+ */
+ public boolean contains(Point2D p)
+ {
+ return false;
+ }
+
+ /**
+ * Tests if this line intersects the interior of the specified rectangle.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @return true if the line intersects the rectangle
+ */
+ public boolean intersects(double x, double y, double w, double h)
+ {
+ if (w <= 0 || h <= 0)
+ return false;
+ double x1 = getX1();
+ double y1 = getY1();
+ double x2 = getX2();
+ double y2 = getY2();
+
+ if (x1 >= x && x1 <= x + w && y1 >= y && y1 <= y + h)
+ return true;
+ if (x2 >= x && x2 <= x + w && y2 >= y && y2 <= y + h)
+ return true;
+
+ double x3 = x + w;
+ double y3 = y + h;
+
+ return (linesIntersect(x1, y1, x2, y2, x, y, x, y3)
+ || linesIntersect(x1, y1, x2, y2, x, y3, x3, y3)
+ || linesIntersect(x1, y1, x2, y2, x3, y3, x3, y)
+ || linesIntersect(x1, y1, x2, y2, x3, y, x, y));
+ }
+
+ /**
+ * Tests if this line intersects the interior of the specified rectangle.
+ *
+ * @param r the rectangle
+ * @return true if the line intersects the rectangle
+ * @throws NullPointerException if r is null
+ */
+ public boolean intersects(Rectangle2D r)
+ {
+ return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Tests if the line contains a rectangle. Since lines have no area, this
+ * always returns false.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @return false; the line does not contain points
+ */
+ public boolean contains(double x, double y, double w, double h)
+ {
+ return false;
+ }
+
+ /**
+ * Tests if the line contains a rectangle. Since lines have no area, this
+ * always returns false.
+ *
+ * @param r the rectangle
+ * @return false; the line does not contain points
+ */
+ public boolean contains(Rectangle2D r)
+ {
+ return false;
+ }
+
+ /**
+ * Gets a bounding box (not necessarily minimal) for this line.
+ *
+ * @return the integer bounding box
+ * @see #getBounds2D()
+ */
+ public Rectangle getBounds()
+ {
+ return getBounds2D().getBounds();
+ }
+
+ /**
+ * Return a path iterator, possibly applying a transform on the result. This
+ * iterator is not threadsafe.
+ *
+ * @param at the transform, or null
+ * @return a new path iterator
+ */
+ public PathIterator getPathIterator(final AffineTransform at)
+ {
+ return new PathIterator()
+ {
+ /** Current coordinate. */
+ private int current = 0;
+
+ public int getWindingRule()
+ {
+ return WIND_NON_ZERO;
+ }
+
+ public boolean isDone()
+ {
+ return current >= 2;
+ }
+
+ public void next()
+ {
+ current++;
+ }
+
+ public int currentSegment(float[] coords)
+ {
+ int result;
+ switch (current)
+ {
+ case 0:
+ coords[0] = (float) getX1();
+ coords[1] = (float) getY1();
+ result = SEG_MOVETO;
+ break;
+ case 1:
+ coords[0] = (float) getX2();
+ coords[1] = (float) getY2();
+ result = SEG_LINETO;
+ break;
+ default:
+ throw new NoSuchElementException("line iterator out of bounds");
+ }
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 1);
+ return result;
+ }
+
+ public int currentSegment(double[] coords)
+ {
+ int result;
+ switch (current)
+ {
+ case 0:
+ coords[0] = getX1();
+ coords[1] = getY1();
+ result = SEG_MOVETO;
+ break;
+ case 1:
+ coords[0] = getX2();
+ coords[1] = getY2();
+ result = SEG_LINETO;
+ break;
+ default:
+ throw new NoSuchElementException("line iterator out of bounds");
+ }
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 1);
+ return result;
+ }
+ };
+ }
+
+ /**
+ * Return a flat path iterator, possibly applying a transform on the result.
+ * This iterator is not threadsafe.
+ *
+ * @param at the transform, or null
+ * @param flatness ignored, since lines are already flat
+ * @return a new path iterator
+ * @see #getPathIterator(AffineTransform)
+ */
+ public PathIterator getPathIterator(AffineTransform at, double flatness)
+ {
+ return getPathIterator(at);
+ }
+
+ /**
+ * Create a new line of the same run-time type with the same contents as
+ * this one.
+ *
+ * @return the clone
+ *
+ * @exception OutOfMemoryError If there is not enough memory available.
+ *
+ * @since 1.2
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // Impossible
+ }
+ }
+
+ /**
+ * This class defines a point in <code>double</code> precision.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+ public static class Double extends Line2D
+ {
+ /** The x coordinate of the first point. */
+ public double x1;
+
+ /** The y coordinate of the first point. */
+ public double y1;
+
+ /** The x coordinate of the second point. */
+ public double x2;
+
+ /** The y coordinate of the second point. */
+ public double y2;
+
+ /**
+ * Construct the line segment (0,0)-&gt;(0,0).
+ */
+ public Double()
+ {
+ }
+
+ /**
+ * Construct the line segment with the specified points.
+ *
+ * @param x1 the x coordinate of the first point
+ * @param y1 the y coordinate of the first point
+ * @param x2 the x coordinate of the second point
+ * @param y2 the y coordinate of the second point
+ */
+ public Double(double x1, double y1, double x2, double y2)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+
+ /**
+ * Construct the line segment with the specified points.
+ *
+ * @param p1 the first point
+ * @param p2 the second point
+ * @throws NullPointerException if either point is null
+ */
+ public Double(Point2D p1, Point2D p2)
+ {
+ x1 = p1.getX();
+ y1 = p1.getY();
+ x2 = p2.getX();
+ y2 = p2.getY();
+ }
+
+ /**
+ * Return the x coordinate of the first point.
+ *
+ * @return the value of x1
+ */
+ public double getX1()
+ {
+ return x1;
+ }
+
+ /**
+ * Return the y coordinate of the first point.
+ *
+ * @return the value of y1
+ */
+ public double getY1()
+ {
+ return y1;
+ }
+
+ /**
+ * Return the first point.
+ *
+ * @return the point (x1,y1)
+ */
+ public Point2D getP1()
+ {
+ return new Point2D.Double(x1, y1);
+ }
+
+ /**
+ * Return the x coordinate of the second point.
+ *
+ * @return the value of x2
+ */
+ public double getX2()
+ {
+ return x2;
+ }
+
+ /**
+ * Return the y coordinate of the second point.
+ *
+ * @return the value of y2
+ */
+ public double getY2()
+ {
+ return y2;
+ }
+
+ /**
+ * Return the second point.
+ *
+ * @return the point (x2,y2)
+ */
+ public Point2D getP2()
+ {
+ return new Point2D.Double(x2, y2);
+ }
+
+ /**
+ * Set this line to the given points.
+ *
+ * @param x1 the new x coordinate of the first point
+ * @param y1 the new y coordinate of the first point
+ * @param x2 the new x coordinate of the second point
+ * @param y2 the new y coordinate of the second point
+ */
+ public void setLine(double x1, double y1, double x2, double y2)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+
+ /**
+ * Return the exact bounds of this line segment.
+ *
+ * @return the bounding box
+ */
+ public Rectangle2D getBounds2D()
+ {
+ double x = Math.min(x1, x2);
+ double y = Math.min(y1, y2);
+ double w = Math.abs(x1 - x2);
+ double h = Math.abs(y1 - y2);
+ return new Rectangle2D.Double(x, y, w, h);
+ }
+ } // class Double
+
+ /**
+ * This class defines a point in <code>float</code> precision.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+ public static class Float extends Line2D
+ {
+ /** The x coordinate of the first point. */
+ public float x1;
+
+ /** The y coordinate of the first point. */
+ public float y1;
+
+ /** The x coordinate of the second point. */
+ public float x2;
+
+ /** The y coordinate of the second point. */
+ public float y2;
+
+ /**
+ * Construct the line segment (0,0)-&gt;(0,0).
+ */
+ public Float()
+ {
+ }
+
+ /**
+ * Construct the line segment with the specified points.
+ *
+ * @param x1 the x coordinate of the first point
+ * @param y1 the y coordinate of the first point
+ * @param x2 the x coordinate of the second point
+ * @param y2 the y coordinate of the second point
+ */
+ public Float(float x1, float y1, float x2, float y2)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+
+ /**
+ * Construct the line segment with the specified points.
+ *
+ * @param p1 the first point
+ * @param p2 the second point
+ * @throws NullPointerException if either point is null
+ */
+ public Float(Point2D p1, Point2D p2)
+ {
+ x1 = (float) p1.getX();
+ y1 = (float) p1.getY();
+ x2 = (float) p2.getX();
+ y2 = (float) p2.getY();
+ }
+
+ /**
+ * Return the x coordinate of the first point.
+ *
+ * @return the value of x1
+ */
+ public double getX1()
+ {
+ return x1;
+ }
+
+ /**
+ * Return the y coordinate of the first point.
+ *
+ * @return the value of y1
+ */
+ public double getY1()
+ {
+ return y1;
+ }
+
+ /**
+ * Return the first point.
+ *
+ * @return the point (x1,y1)
+ */
+ public Point2D getP1()
+ {
+ return new Point2D.Float(x1, y1);
+ }
+
+ /**
+ * Return the x coordinate of the second point.
+ *
+ * @return the value of x2
+ */
+ public double getX2()
+ {
+ return x2;
+ }
+
+ /**
+ * Return the y coordinate of the second point.
+ *
+ * @return the value of y2
+ */
+ public double getY2()
+ {
+ return y2;
+ }
+
+ /**
+ * Return the second point.
+ *
+ * @return the point (x2,y2)
+ */
+ public Point2D getP2()
+ {
+ return new Point2D.Float(x2, y2);
+ }
+
+ /**
+ * Set this line to the given points.
+ *
+ * @param x1 the new x coordinate of the first point
+ * @param y1 the new y coordinate of the first point
+ * @param x2 the new x coordinate of the second point
+ * @param y2 the new y coordinate of the second point
+ */
+ public void setLine(double x1, double y1, double x2, double y2)
+ {
+ this.x1 = (float) x1;
+ this.y1 = (float) y1;
+ this.x2 = (float) x2;
+ this.y2 = (float) y2;
+ }
+
+ /**
+ * Set this line to the given points.
+ *
+ * @param x1 the new x coordinate of the first point
+ * @param y1 the new y coordinate of the first point
+ * @param x2 the new x coordinate of the second point
+ * @param y2 the new y coordinate of the second point
+ */
+ public void setLine(float x1, float y1, float x2, float y2)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+
+ /**
+ * Return the exact bounds of this line segment.
+ *
+ * @return the bounding box
+ */
+ public Rectangle2D getBounds2D()
+ {
+ float x = Math.min(x1, x2);
+ float y = Math.min(y1, y2);
+ float w = Math.abs(x1 - x2);
+ float h = Math.abs(y1 - y2);
+ return new Rectangle2D.Float(x, y, w, h);
+ }
+ } // class Float
+} // class Line2D
diff --git a/libjava/classpath/java/awt/geom/NoninvertibleTransformException.java b/libjava/classpath/java/awt/geom/NoninvertibleTransformException.java
new file mode 100644
index 000000000..7995a52eb
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/NoninvertibleTransformException.java
@@ -0,0 +1,65 @@
+/* NoninvertibleTransformException.java -- a transform can't be inverted
+ Copyright (C) 2000, 2002 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.geom;
+
+/**
+ * Thrown if an operation requires an inverse of an
+ * <code>AffineTransform</code>, but the transform is in a non-invertible
+ * state.
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @see AffineTransform
+ * @status updated to 1.4
+ */
+public class NoninvertibleTransformException extends Exception
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 6137225240503990466L;
+
+ /**
+ * Create an exception with a message.
+ *
+ * @param s the message
+ */
+ public NoninvertibleTransformException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/libjava/classpath/java/awt/geom/PathIterator.java b/libjava/classpath/java/awt/geom/PathIterator.java
new file mode 100644
index 000000000..2cd08b9b4
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/PathIterator.java
@@ -0,0 +1,189 @@
+/* PathIterator.java -- describes a shape by iterating over its vertices
+ Copyright (C) 2000, 2002, 2003 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.geom;
+
+/**
+ * This interface provides a directed path over the boundary of a shape. The
+ * path can contain 1st through 3rd order Bezier curves (lines, and quadratic
+ * and cubic splines). A shape can have multiple disjoint paths via the
+ * MOVETO directive, and can close a circular path back to the previos
+ * MOVETO via the CLOSE directive.
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see java.awt.Shape
+ * @see java.awt.Stroke
+ * @see FlatteningPathIterator
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface PathIterator
+{
+ /**
+ * The even-odd winding mode: a point is internal to the shape if a ray
+ * from the point to infinity (in any direction) crosses an odd number of
+ * segments.
+ */
+ int WIND_EVEN_ODD = 0;
+
+ /**
+ * The non-zero winding mode: a point is internal to the shape if a ray
+ * from the point to infinity (in any direction) crosses a different number
+ * of segments headed clockwise than those headed counterclockwise.
+ */
+ int WIND_NON_ZERO = 1;
+
+ /**
+ * Starts a new subpath. There is no segment from the previous vertex.
+ */
+ int SEG_MOVETO = 0;
+
+ /**
+ * The current segment is a line.
+ */
+ int SEG_LINETO = 1;
+
+ /**
+ * The current segment is a quadratic parametric curve. It is interpolated
+ * as t varies from 0 to 1 over the current point (CP), first control point
+ * (P1), and final interpolated control point (P2):
+ * <pre>
+ * P(t) = B(2,0)*CP + B(2,1)*P1 + B(2,2)*P2
+ * 0 &lt;= t &lt;= 1
+ * B(n,m) = mth coefficient of nth degree Bernstein polynomial
+ * = C(n,m) * t^(m) * (1 - t)^(n-m)
+ * C(n,m) = Combinations of n things, taken m at a time
+ * = n! / (m! * (n-m)!)
+ * </pre>
+ */
+ int SEG_QUADTO = 2;
+
+ /**
+ * The current segment is a cubic parametric curve (more commonly known as
+ * a Bezier curve). It is interpolated as t varies from 0 to 1 over the
+ * current point (CP), first control point (P1), the second control point
+ * (P2), and final interpolated control point (P3):
+ * <pre>
+ * P(t) = B(3,0)*CP + B(3,1)*P1 + B(3,2)*P2 + B(3,3)*P3
+ * 0 &lt;= t &lt;= 1
+ * B(n,m) = mth coefficient of nth degree Bernstein polynomial
+ * = C(n,m) * t^(m) * (1 - t)^(n-m)
+ * C(n,m) = Combinations of n things, taken m at a time
+ * = n! / (m! * (n-m)!)
+ * </pre>
+ */
+ int SEG_CUBICTO = 3;
+
+ /**
+ * The current segment closes a loop by an implicit line to the previous
+ * SEG_MOVETO coordinate.
+ */
+ int SEG_CLOSE = 4;
+
+ /**
+ * Returns the winding rule to determine which points are inside this path.
+ *
+ * @return the winding rule
+ * @see #WIND_EVEN_ODD
+ * @see #WIND_NON_ZERO
+ */
+ int getWindingRule();
+
+ /**
+ * Tests if the iterator is exhausted. If this returns true, currentSegment
+ * and next may throw a NoSuchElementException (although this is not
+ * required).
+ *
+ * @return true if the iteration is complete
+ */
+ boolean isDone();
+
+ /**
+ * Advance to the next segment in the iteration. It is not specified what
+ * this does if called when isDone() returns true.
+ *
+ * @throws java.util.NoSuchElementException optional when isDone() is true
+ */
+ void next();
+
+ /**
+ * Returns the coordinates of the next point(s), as well as the type of
+ * line segment. The input array must be at least a float[6], to accomodate
+ * up to three (x,y) point pairs (although if you know the iterator is
+ * flat, you can probably get by with a float[2]). If the returned type is
+ * SEG_MOVETO or SEG_LINETO, the first point in the array is modified; if
+ * the returned type is SEG_QUADTO, the first two points are modified; if
+ * the returned type is SEG_CUBICTO, all three points are modified; and if
+ * the returned type is SEG_CLOSE, the array is untouched.
+ *
+ * @param coords the array to place the point coordinates in
+ * @return the segment type
+ * @throws NullPointerException if coords is null
+ * @throws ArrayIndexOutOfBoundsException if coords is too small
+ * @throws java.util.NoSuchElementException optional when isDone() is true
+ * @see #SEG_MOVETO
+ * @see #SEG_LINETO
+ * @see #SEG_QUADTO
+ * @see #SEG_CUBICTO
+ * @see #SEG_CLOSE
+ */
+ int currentSegment(float[] coords);
+
+ /**
+ * Returns the coordinates of the next point(s), as well as the type of
+ * line segment. The input array must be at least a double[6], to accomodate
+ * up to three (x,y) point pairs (although if you know the iterator is
+ * flat, you can probably get by with a double[2]). If the returned type is
+ * SEG_MOVETO or SEG_LINETO, the first point in the array is modified; if
+ * the returned type is SEG_QUADTO, the first two points are modified; if
+ * the returned type is SEG_CUBICTO, all three points are modified; and if
+ * the returned type is SEG_CLOSE, the array is untouched.
+ *
+ * @param coords the array to place the point coordinates in
+ * @return the segment type
+ * @throws NullPointerException if coords is null
+ * @throws ArrayIndexOutOfBoundsException if coords is too small
+ * @throws java.util.NoSuchElementException optional when isDone() is true
+ * @see #SEG_MOVETO
+ * @see #SEG_LINETO
+ * @see #SEG_QUADTO
+ * @see #SEG_CUBICTO
+ * @see #SEG_CLOSE
+ */
+ int currentSegment(double[] coords);
+} // interface PathIterator
diff --git a/libjava/classpath/java/awt/geom/Point2D.java b/libjava/classpath/java/awt/geom/Point2D.java
new file mode 100644
index 000000000..a2689abf8
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/Point2D.java
@@ -0,0 +1,396 @@
+/* Point2D.java -- generic point in 2-D space
+ Copyright (C) 1999, 2000, 2002, 2004, 2006, Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.geom;
+
+/**
+ * This class implements a generic point in 2D Cartesian space. The storage
+ * representation is left up to the subclass. Point includes two useful
+ * nested classes, for float and double storage respectively.
+ *
+ * @author Per Bothner (bothner@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public abstract class Point2D implements Cloneable
+{
+ /**
+ * The default constructor.
+ *
+ * @see java.awt.Point
+ * @see Point2D.Float
+ * @see Point2D.Double
+ */
+ protected Point2D()
+ {
+ }
+
+ /**
+ * Get the X coordinate, in double precision.
+ *
+ * @return the x coordinate
+ */
+ public abstract double getX();
+
+ /**
+ * Get the Y coordinate, in double precision.
+ *
+ * @return the y coordinate
+ */
+ public abstract double getY();
+
+ /**
+ * Set the location of this point to the new coordinates. There may be a
+ * loss of precision.
+ *
+ * @param x the new x coordinate
+ * @param y the new y coordinate
+ */
+ public abstract void setLocation(double x, double y);
+
+ /**
+ * Set the location of this point to the new coordinates. There may be a
+ * loss of precision.
+ *
+ * @param p the point to copy
+ * @throws NullPointerException if p is null
+ */
+ public void setLocation(Point2D p)
+ {
+ setLocation(p.getX(), p.getY());
+ }
+
+ /**
+ * Return the square of the distance between two points.
+ *
+ * @param x1 the x coordinate of point 1
+ * @param y1 the y coordinate of point 1
+ * @param x2 the x coordinate of point 2
+ * @param y2 the y coordinate of point 2
+ * @return (x2 - x1)^2 + (y2 - y1)^2
+ */
+ public static double distanceSq(double x1, double y1, double x2, double y2)
+ {
+ x2 -= x1;
+ y2 -= y1;
+ return x2 * x2 + y2 * y2;
+ }
+
+ /**
+ * Return the distance between two points.
+ *
+ * @param x1 the x coordinate of point 1
+ * @param y1 the y coordinate of point 1
+ * @param x2 the x coordinate of point 2
+ * @param y2 the y coordinate of point 2
+ * @return the distance from (x1,y1) to (x2,y2)
+ */
+ public static double distance(double x1, double y1, double x2, double y2)
+ {
+ return Math.sqrt(distanceSq(x1, y1, x2, y2));
+ }
+
+ /**
+ * Return the square of the distance from this point to the given one.
+ *
+ * @param x the x coordinate of the other point
+ * @param y the y coordinate of the other point
+ * @return the square of the distance
+ */
+ public double distanceSq(double x, double y)
+ {
+ return distanceSq(getX(), getY(), x, y);
+ }
+
+ /**
+ * Return the square of the distance from this point to the given one.
+ *
+ * @param p the other point
+ * @return the square of the distance
+ * @throws NullPointerException if p is null
+ */
+ public double distanceSq(Point2D p)
+ {
+ return distanceSq(getX(), getY(), p.getX(), p.getY());
+ }
+
+ /**
+ * Return the distance from this point to the given one.
+ *
+ * @param x the x coordinate of the other point
+ * @param y the y coordinate of the other point
+ * @return the distance
+ */
+ public double distance(double x, double y)
+ {
+ return distance(getX(), getY(), x, y);
+ }
+
+ /**
+ * Return the distance from this point to the given one.
+ *
+ * @param p the other point
+ * @return the distance
+ * @throws NullPointerException if p is null
+ */
+ public double distance(Point2D p)
+ {
+ return distance(getX(), getY(), p.getX(), p.getY());
+ }
+
+ /**
+ * Create a new point of the same run-time type with the same contents as
+ * this one.
+ *
+ * @return the clone
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // Impossible
+ }
+ }
+
+ /**
+ * Return the hashcode for this point. The formula is not documented, but
+ * appears to be the same as:
+ * <pre>
+ * long l = Double.doubleToLongBits(getY());
+ * l = l * 31 ^ Double.doubleToLongBits(getX());
+ * return (int) ((l >> 32) ^ l);
+ * </pre>
+ *
+ * @return the hashcode
+ */
+ public int hashCode()
+ {
+ // Talk about a fun time reverse engineering this one!
+ long l = java.lang.Double.doubleToLongBits(getY());
+ l = l * 31 ^ java.lang.Double.doubleToLongBits(getX());
+ return (int) ((l >> 32) ^ l);
+ }
+
+ /**
+ * Compares two points for equality. This returns true if they have the
+ * same coordinates.
+ *
+ * @param o the point to compare
+ * @return true if it is equal
+ */
+ public boolean equals(Object o)
+ {
+ if (! (o instanceof Point2D))
+ return false;
+ Point2D p = (Point2D) o;
+ return getX() == p.getX() && getY() == p.getY();
+ }
+
+ /**
+ * This class defines a point in <code>double</code> precision.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+ public static class Double extends Point2D
+ {
+ /** The X coordinate. */
+ public double x;
+
+ /** The Y coordinate. */
+ public double y;
+
+ /**
+ * Create a new point at (0,0).
+ */
+ public Double()
+ {
+ }
+
+ /**
+ * Create a new point at (x,y).
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ */
+ public Double(double x, double y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ * Return the x coordinate.
+ *
+ * @return the x coordinate
+ */
+ public double getX()
+ {
+ return x;
+ }
+
+ /**
+ * Return the y coordinate.
+ *
+ * @return the y coordinate
+ */
+ public double getY()
+ {
+ return y;
+ }
+
+ /**
+ * Sets the location of this point.
+ *
+ * @param x the new x coordinate
+ * @param y the new y coordinate
+ */
+ public void setLocation(double x, double y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ * Returns a string representation of this object. The format is:
+ * <code>"Point2D.Double[" + x + ", " + y + ']'</code>.
+ *
+ * @return a string representation of this object
+ */
+ public String toString()
+ {
+ return "Point2D.Double[" + x + ", " + y + ']';
+ }
+ } // class Double
+
+ /**
+ * This class defines a point in <code>float</code> precision.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+ public static class Float extends Point2D
+ {
+ /** The X coordinate. */
+ public float x;
+
+ /** The Y coordinate. */
+ public float y;
+
+ /**
+ * Create a new point at (0,0).
+ */
+ public Float()
+ {
+ }
+
+ /**
+ * Create a new point at (x,y).
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ */
+ public Float(float x, float y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ * Return the x coordinate.
+ *
+ * @return the x coordinate
+ */
+ public double getX()
+ {
+ return x;
+ }
+
+ /**
+ * Return the y coordinate.
+ *
+ * @return the y coordinate
+ */
+ public double getY()
+ {
+ return y;
+ }
+
+ /**
+ * Sets the location of this point.
+ *
+ * @param x the new x coordinate
+ * @param y the new y coordinate
+ */
+ public void setLocation(double x, double y)
+ {
+ this.x = (float) x;
+ this.y = (float) y;
+ }
+
+ /**
+ * Sets the location of this point.
+ *
+ * @param x the new x coordinate
+ * @param y the new y coordinate
+ */
+ public void setLocation(float x, float y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ * Returns a string representation of this object. The format is:
+ * <code>"Point2D.Float[" + x + ", " + y + ']'</code>.
+ *
+ * @return a string representation of this object
+ */
+ public String toString()
+ {
+ return "Point2D.Float[" + x + ", " + y + ']';
+ }
+ } // class Float
+} // class Point2D
diff --git a/libjava/classpath/java/awt/geom/QuadCurve2D.java b/libjava/classpath/java/awt/geom/QuadCurve2D.java
new file mode 100644
index 000000000..62c829d30
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/QuadCurve2D.java
@@ -0,0 +1,1467 @@
+/* QuadCurve2D.java -- represents a parameterized quadratic curve in 2-D space
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.geom;
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.util.NoSuchElementException;
+
+/**
+ * A two-dimensional curve that is parameterized with a quadratic
+ * function.
+ *
+ * <p><img src="doc-files/QuadCurve2D-1.png" width="350" height="180"
+ * alt="A drawing of a QuadCurve2D" />
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Graydon Hoare (graydon@redhat.com)
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ * @author Sven de Marothy (sven@physto.se)
+ *
+ * @since 1.2
+ */
+public abstract class QuadCurve2D implements Shape, Cloneable
+{
+ private static final double BIG_VALUE = java.lang.Double.MAX_VALUE / 10.0;
+ private static final double EPSILON = 1E-10;
+
+ /**
+ * Constructs a new QuadCurve2D. Typical users will want to
+ * construct instances of a subclass, such as {@link
+ * QuadCurve2D.Float} or {@link QuadCurve2D.Double}.
+ */
+ protected QuadCurve2D()
+ {
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s start
+ * point.
+ */
+ public abstract double getX1();
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s start
+ * point.
+ */
+ public abstract double getY1();
+
+ /**
+ * Returns the curve&#x2019;s start point.
+ */
+ public abstract Point2D getP1();
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s control
+ * point.
+ */
+ public abstract double getCtrlX();
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s control
+ * point.
+ */
+ public abstract double getCtrlY();
+
+ /**
+ * Returns the curve&#x2019;s control point.
+ */
+ public abstract Point2D getCtrlPt();
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public abstract double getX2();
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public abstract double getY2();
+
+ /**
+ * Returns the curve&#x2019;s end point.
+ */
+ public abstract Point2D getP2();
+
+ /**
+ * Changes the curve geometry, separately specifying each coordinate
+ * value.
+ *
+ * @param x1 the <i>x</i> coordinate of the curve&#x2019;s new start
+ * point.
+ *
+ * @param y1 the <i>y</i> coordinate of the curve&#x2019;s new start
+ * point.
+ *
+ * @param cx the <i>x</i> coordinate of the curve&#x2019;s new
+ * control point.
+ *
+ * @param cy the <i>y</i> coordinate of the curve&#x2019;s new
+ * control point.
+ *
+ * @param x2 the <i>x</i> coordinate of the curve&#x2019;s new end
+ * point.
+ *
+ * @param y2 the <i>y</i> coordinate of the curve&#x2019;s new end
+ * point.
+ */
+ public abstract void setCurve(double x1, double y1, double cx, double cy,
+ double x2, double y2);
+
+ /**
+ * Changes the curve geometry, passing coordinate values in an
+ * array.
+ *
+ * @param coords an array containing the new coordinate values. The
+ * <i>x</i> coordinate of the new start point is located at
+ * <code>coords[offset]</code>, its <i>y</i> coordinate at
+ * <code>coords[offset + 1]</code>. The <i>x</i> coordinate of the
+ * new control point is located at <code>coords[offset + 2]</code>,
+ * its <i>y</i> coordinate at <code>coords[offset + 3]</code>. The
+ * <i>x</i> coordinate of the new end point is located at
+ * <code>coords[offset + 4]</code>, its <i>y</i> coordinate at
+ * <code>coords[offset + 5]</code>.
+ *
+ * @param offset the offset of the first coordinate value in
+ * <code>coords</code>.
+ */
+ public void setCurve(double[] coords, int offset)
+ {
+ setCurve(coords[offset++], coords[offset++], coords[offset++],
+ coords[offset++], coords[offset++], coords[offset++]);
+ }
+
+ /**
+ * Changes the curve geometry, specifying coordinate values in
+ * separate Point objects.
+ *
+ * <p><img src="doc-files/QuadCurve2D-1.png" width="350" height="180"
+ * alt="A drawing of a QuadCurve2D" />
+ *
+ * <p>The curve does not keep any reference to the passed point
+ * objects. Therefore, a later change to <code>p1</code>,
+ * <code>c</code> <code>p2</code> will not affect the curve
+ * geometry.
+ *
+ * @param p1 the new start point.
+ * @param c the new control point.
+ * @param p2 the new end point.
+ */
+ public void setCurve(Point2D p1, Point2D c, Point2D p2)
+ {
+ setCurve(p1.getX(), p1.getY(), c.getX(), c.getY(), p2.getX(), p2.getY());
+ }
+
+ /**
+ * Changes the curve geometry, specifying coordinate values in an
+ * array of Point objects.
+ *
+ * <p><img src="doc-files/QuadCurve2D-1.png" width="350" height="180"
+ * alt="A drawing of a QuadCurve2D" />
+ *
+ * <p>The curve does not keep references to the passed point
+ * objects. Therefore, a later change to the <code>pts</code> array
+ * or any of its elements will not affect the curve geometry.
+ *
+ * @param pts an array containing the points. The new start point
+ * is located at <code>pts[offset]</code>, the new control
+ * point at <code>pts[offset + 1]</code>, and the new end point
+ * at <code>pts[offset + 2]</code>.
+ *
+ * @param offset the offset of the start point in <code>pts</code>.
+ */
+ public void setCurve(Point2D[] pts, int offset)
+ {
+ setCurve(pts[offset].getX(), pts[offset].getY(), pts[offset + 1].getX(),
+ pts[offset + 1].getY(), pts[offset + 2].getX(),
+ pts[offset + 2].getY());
+ }
+
+ /**
+ * Changes the geometry of the curve to that of another curve.
+ *
+ * @param c the curve whose coordinates will be copied.
+ */
+ public void setCurve(QuadCurve2D c)
+ {
+ setCurve(c.getX1(), c.getY1(), c.getCtrlX(), c.getCtrlY(), c.getX2(),
+ c.getY2());
+ }
+
+ /**
+ * Calculates the squared flatness of a quadratic curve, directly
+ * specifying each coordinate value. The flatness is the distance of
+ * the control point to the line between start and end point.
+ *
+ * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180"
+ * alt="A drawing that illustrates the flatness" />
+ *
+ * <p>In the above drawing, the straight line connecting start point
+ * P1 and end point P2 is depicted in gray. The result will be the
+ * the square of the distance between C and the gray line, i.e.
+ * the squared length of the red line.
+ *
+ * @param x1 the <i>x</i> coordinate of the start point P1.
+ * @param y1 the <i>y</i> coordinate of the start point P1.
+ * @param cx the <i>x</i> coordinate of the control point C.
+ * @param cy the <i>y</i> coordinate of the control point C.
+ * @param x2 the <i>x</i> coordinate of the end point P2.
+ * @param y2 the <i>y</i> coordinate of the end point P2.
+ */
+ public static double getFlatnessSq(double x1, double y1, double cx,
+ double cy, double x2, double y2)
+ {
+ return Line2D.ptSegDistSq(x1, y1, x2, y2, cx, cy);
+ }
+
+ /**
+ * Calculates the flatness of a quadratic curve, directly specifying
+ * each coordinate value. The flatness is the distance of the
+ * control point to the line between start and end point.
+ *
+ * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180"
+ * alt="A drawing that illustrates the flatness" />
+ *
+ * <p>In the above drawing, the straight line connecting start point
+ * P1 and end point P2 is depicted in gray. The result will be the
+ * the distance between C and the gray line, i.e. the length of
+ * the red line.
+ *
+ * @param x1 the <i>x</i> coordinate of the start point P1.
+ * @param y1 the <i>y</i> coordinate of the start point P1.
+ * @param cx the <i>x</i> coordinate of the control point C.
+ * @param cy the <i>y</i> coordinate of the control point C.
+ * @param x2 the <i>x</i> coordinate of the end point P2.
+ * @param y2 the <i>y</i> coordinate of the end point P2.
+ */
+ public static double getFlatness(double x1, double y1, double cx, double cy,
+ double x2, double y2)
+ {
+ return Line2D.ptSegDist(x1, y1, x2, y2, cx, cy);
+ }
+
+ /**
+ * Calculates the squared flatness of a quadratic curve, specifying
+ * the coordinate values in an array. The flatness is the distance
+ * of the control point to the line between start and end point.
+ *
+ * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180"
+ * alt="A drawing that illustrates the flatness" />
+ *
+ * <p>In the above drawing, the straight line connecting start point
+ * P1 and end point P2 is depicted in gray. The result will be the
+ * the square of the distance between C and the gray line, i.e.
+ * the squared length of the red line.
+ *
+ * @param coords an array containing the coordinate values. The
+ * <i>x</i> coordinate of the start point P1 is located at
+ * <code>coords[offset]</code>, its <i>y</i> coordinate at
+ * <code>coords[offset + 1]</code>. The <i>x</i> coordinate of the
+ * control point C is located at <code>coords[offset + 2]</code>,
+ * its <i>y</i> coordinate at <code>coords[offset + 3]</code>. The
+ * <i>x</i> coordinate of the end point P2 is located at
+ * <code>coords[offset + 4]</code>, its <i>y</i> coordinate at
+ * <code>coords[offset + 5]</code>.
+ *
+ * @param offset the offset of the first coordinate value in
+ * <code>coords</code>.
+ */
+ public static double getFlatnessSq(double[] coords, int offset)
+ {
+ return Line2D.ptSegDistSq(coords[offset], coords[offset + 1],
+ coords[offset + 4], coords[offset + 5],
+ coords[offset + 2], coords[offset + 3]);
+ }
+
+ /**
+ * Calculates the flatness of a quadratic curve, specifying the
+ * coordinate values in an array. The flatness is the distance of
+ * the control point to the line between start and end point.
+ *
+ * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180"
+ * alt="A drawing that illustrates the flatness" />
+ *
+ * <p>In the above drawing, the straight line connecting start point
+ * P1 and end point P2 is depicted in gray. The result will be the
+ * the the distance between C and the gray line, i.e. the length of
+ * the red line.
+ *
+ * @param coords an array containing the coordinate values. The
+ * <i>x</i> coordinate of the start point P1 is located at
+ * <code>coords[offset]</code>, its <i>y</i> coordinate at
+ * <code>coords[offset + 1]</code>. The <i>x</i> coordinate of the
+ * control point C is located at <code>coords[offset + 2]</code>,
+ * its <i>y</i> coordinate at <code>coords[offset + 3]</code>. The
+ * <i>x</i> coordinate of the end point P2 is located at
+ * <code>coords[offset + 4]</code>, its <i>y</i> coordinate at
+ * <code>coords[offset + 5]</code>.
+ *
+ * @param offset the offset of the first coordinate value in
+ * <code>coords</code>.
+ */
+ public static double getFlatness(double[] coords, int offset)
+ {
+ return Line2D.ptSegDist(coords[offset], coords[offset + 1],
+ coords[offset + 4], coords[offset + 5],
+ coords[offset + 2], coords[offset + 3]);
+ }
+
+ /**
+ * Calculates the squared flatness of this curve. The flatness is
+ * the distance of the control point to the line between start and
+ * end point.
+ *
+ * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180"
+ * alt="A drawing that illustrates the flatness" />
+ *
+ * <p>In the above drawing, the straight line connecting start point
+ * P1 and end point P2 is depicted in gray. The result will be the
+ * the square of the distance between C and the gray line, i.e. the
+ * squared length of the red line.
+ */
+ public double getFlatnessSq()
+ {
+ return Line2D.ptSegDistSq(getX1(), getY1(), getX2(), getY2(), getCtrlX(),
+ getCtrlY());
+ }
+
+ /**
+ * Calculates the flatness of this curve. The flatness is the
+ * distance of the control point to the line between start and end
+ * point.
+ *
+ * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180"
+ * alt="A drawing that illustrates the flatness" />
+ *
+ * <p>In the above drawing, the straight line connecting start point
+ * P1 and end point P2 is depicted in gray. The result will be the
+ * the distance between C and the gray line, i.e. the length of the
+ * red line.
+ */
+ public double getFlatness()
+ {
+ return Line2D.ptSegDist(getX1(), getY1(), getX2(), getY2(), getCtrlX(),
+ getCtrlY());
+ }
+
+ /**
+ * Subdivides this curve into two halves.
+ *
+ * <p><img src="doc-files/QuadCurve2D-3.png" width="700"
+ * height="180" alt="A drawing that illustrates the effects of
+ * subdividing a QuadCurve2D" />
+ *
+ * @param left a curve whose geometry will be set to the left half
+ * of this curve, or <code>null</code> if the caller is not
+ * interested in the left half.
+ *
+ * @param right a curve whose geometry will be set to the right half
+ * of this curve, or <code>null</code> if the caller is not
+ * interested in the right half.
+ */
+ public void subdivide(QuadCurve2D left, QuadCurve2D right)
+ {
+ // Use empty slots at end to share single array.
+ double[] d = new double[]
+ {
+ getX1(), getY1(), getCtrlX(), getCtrlY(), getX2(), getY2(),
+ 0, 0, 0, 0
+ };
+ subdivide(d, 0, d, 0, d, 4);
+ if (left != null)
+ left.setCurve(d, 0);
+ if (right != null)
+ right.setCurve(d, 4);
+ }
+
+ /**
+ * Subdivides a quadratic curve into two halves.
+ *
+ * <p><img src="doc-files/QuadCurve2D-3.png" width="700"
+ * height="180" alt="A drawing that illustrates the effects of
+ * subdividing a QuadCurve2D" />
+ *
+ * @param src the curve to be subdivided.
+ *
+ * @param left a curve whose geometry will be set to the left half
+ * of <code>src</code>, or <code>null</code> if the caller is not
+ * interested in the left half.
+ *
+ * @param right a curve whose geometry will be set to the right half
+ * of <code>src</code>, or <code>null</code> if the caller is not
+ * interested in the right half.
+ */
+ public static void subdivide(QuadCurve2D src, QuadCurve2D left,
+ QuadCurve2D right)
+ {
+ src.subdivide(left, right);
+ }
+
+ /**
+ * Subdivides a quadratic curve into two halves, passing all
+ * coordinates in an array.
+ *
+ * <p><img src="doc-files/QuadCurve2D-3.png" width="700"
+ * height="180" alt="A drawing that illustrates the effects of
+ * subdividing a QuadCurve2D" />
+ *
+ * <p>The left end point and the right start point will always be
+ * identical. Memory-concious programmers thus may want to pass the
+ * same array for both <code>left</code> and <code>right</code>, and
+ * set <code>rightOff</code> to <code>leftOff + 4</code>.
+ *
+ * @param src an array containing the coordinates of the curve to be
+ * subdivided. The <i>x</i> coordinate of the start point is
+ * located at <code>src[srcOff]</code>, its <i>y</i> at
+ * <code>src[srcOff + 1]</code>. The <i>x</i> coordinate of the
+ * control point is located at <code>src[srcOff + 2]</code>, its
+ * <i>y</i> at <code>src[srcOff + 3]</code>. The <i>x</i>
+ * coordinate of the end point is located at <code>src[srcOff +
+ * 4]</code>, its <i>y</i> at <code>src[srcOff + 5]</code>.
+ *
+ * @param srcOff an offset into <code>src</code>, specifying
+ * the index of the start point&#x2019;s <i>x</i> coordinate.
+ *
+ * @param left an array that will receive the coordinates of the
+ * left half of <code>src</code>. It is acceptable to pass
+ * <code>src</code>. A caller who is not interested in the left half
+ * can pass <code>null</code>.
+ *
+ * @param leftOff an offset into <code>left</code>, specifying the
+ * index where the start point&#x2019;s <i>x</i> coordinate will be
+ * stored.
+ *
+ * @param right an array that will receive the coordinates of the
+ * right half of <code>src</code>. It is acceptable to pass
+ * <code>src</code> or <code>left</code>. A caller who is not
+ * interested in the right half can pass <code>null</code>.
+ *
+ * @param rightOff an offset into <code>right</code>, specifying the
+ * index where the start point&#x2019;s <i>x</i> coordinate will be
+ * stored.
+ */
+ public static void subdivide(double[] src, int srcOff, double[] left,
+ int leftOff, double[] right, int rightOff)
+ {
+ double x1;
+ double y1;
+ double xc;
+ double yc;
+ double x2;
+ double y2;
+
+ x1 = src[srcOff];
+ y1 = src[srcOff + 1];
+ xc = src[srcOff + 2];
+ yc = src[srcOff + 3];
+ x2 = src[srcOff + 4];
+ y2 = src[srcOff + 5];
+
+ if (left != null)
+ {
+ left[leftOff] = x1;
+ left[leftOff + 1] = y1;
+ }
+
+ if (right != null)
+ {
+ right[rightOff + 4] = x2;
+ right[rightOff + 5] = y2;
+ }
+
+ x1 = (x1 + xc) / 2;
+ x2 = (xc + x2) / 2;
+ xc = (x1 + x2) / 2;
+ y1 = (y1 + yc) / 2;
+ y2 = (y2 + yc) / 2;
+ yc = (y1 + y2) / 2;
+
+ if (left != null)
+ {
+ left[leftOff + 2] = x1;
+ left[leftOff + 3] = y1;
+ left[leftOff + 4] = xc;
+ left[leftOff + 5] = yc;
+ }
+
+ if (right != null)
+ {
+ right[rightOff] = xc;
+ right[rightOff + 1] = yc;
+ right[rightOff + 2] = x2;
+ right[rightOff + 3] = y2;
+ }
+ }
+
+ /**
+ * Finds the non-complex roots of a quadratic equation, placing the
+ * results into the same array as the equation coefficients. The
+ * following equation is being solved:
+ *
+ * <blockquote><code>eqn[2]</code> &#xb7; <i>x</i><sup>2</sup>
+ * + <code>eqn[1]</code> &#xb7; <i>x</i>
+ * + <code>eqn[0]</code>
+ * = 0
+ * </blockquote>
+ *
+ * <p>For some background about solving quadratic equations, see the
+ * article <a href=
+ * "http://planetmath.org/encyclopedia/QuadraticFormula.html"
+ * >&#x201c;Quadratic Formula&#x201d;</a> in <a href=
+ * "http://planetmath.org/">PlanetMath</a>. For an extensive library
+ * of numerical algorithms written in the C programming language,
+ * see the <a href="http://www.gnu.org/software/gsl/">GNU Scientific
+ * Library</a>.
+ *
+ * @see #solveQuadratic(double[], double[])
+ * @see CubicCurve2D#solveCubic(double[], double[])
+ *
+ * @param eqn an array with the coefficients of the equation. When
+ * this procedure has returned, <code>eqn</code> will contain the
+ * non-complex solutions of the equation, in no particular order.
+ *
+ * @return the number of non-complex solutions. A result of 0
+ * indicates that the equation has no non-complex solutions. A
+ * result of -1 indicates that the equation is constant (i.e.,
+ * always or never zero).
+ *
+ * @author Brian Gough (bjg@network-theory.com)
+ * (original C implementation in the <a href=
+ * "http://www.gnu.org/software/gsl/">GNU Scientific Library</a>)
+ *
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ * (adaptation to Java)
+ */
+ public static int solveQuadratic(double[] eqn)
+ {
+ return solveQuadratic(eqn, eqn);
+ }
+
+ /**
+ * Finds the non-complex roots of a quadratic equation. The
+ * following equation is being solved:
+ *
+ * <blockquote><code>eqn[2]</code> &#xb7; <i>x</i><sup>2</sup>
+ * + <code>eqn[1]</code> &#xb7; <i>x</i>
+ * + <code>eqn[0]</code>
+ * = 0
+ * </blockquote>
+ *
+ * <p>For some background about solving quadratic equations, see the
+ * article <a href=
+ * "http://planetmath.org/encyclopedia/QuadraticFormula.html"
+ * >&#x201c;Quadratic Formula&#x201d;</a> in <a href=
+ * "http://planetmath.org/">PlanetMath</a>. For an extensive library
+ * of numerical algorithms written in the C programming language,
+ * see the <a href="http://www.gnu.org/software/gsl/">GNU Scientific
+ * Library</a>.
+ *
+ * @see CubicCurve2D#solveCubic(double[],double[])
+ *
+ * @param eqn an array with the coefficients of the equation.
+ *
+ * @param res an array into which the non-complex roots will be
+ * stored. The results may be in an arbitrary order. It is safe to
+ * pass the same array object reference for both <code>eqn</code>
+ * and <code>res</code>.
+ *
+ * @return the number of non-complex solutions. A result of 0
+ * indicates that the equation has no non-complex solutions. A
+ * result of -1 indicates that the equation is constant (i.e.,
+ * always or never zero).
+ *
+ * @author Brian Gough (bjg@network-theory.com)
+ * (original C implementation in the <a href=
+ * "http://www.gnu.org/software/gsl/">GNU Scientific Library</a>)
+ *
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ * (adaptation to Java)
+ */
+ public static int solveQuadratic(double[] eqn, double[] res)
+ {
+ // Taken from poly/solve_quadratic.c in the GNU Scientific Library
+ // (GSL), cvs revision 1.7 of 2003-07-26. For the original source,
+ // see http://www.gnu.org/software/gsl/
+ //
+ // Brian Gough, the author of that code, has granted the
+ // permission to use it in GNU Classpath under the GNU Classpath
+ // license, and has assigned the copyright to the Free Software
+ // Foundation.
+ //
+ // The Java implementation is very similar to the GSL code, but
+ // not a strict one-to-one copy. For example, GSL would sort the
+ // result.
+ double a;
+ double b;
+ double c;
+ double disc;
+
+ c = eqn[0];
+ b = eqn[1];
+ a = eqn[2];
+
+ // Check for linear or constant functions. This is not done by the
+ // GNU Scientific Library. Without this special check, we
+ // wouldn't return -1 for constant functions, and 2 instead of 1
+ // for linear functions.
+ if (a == 0)
+ {
+ if (b == 0)
+ return -1;
+
+ res[0] = -c / b;
+ return 1;
+ }
+
+ disc = b * b - 4 * a * c;
+
+ if (disc < 0)
+ return 0;
+
+ if (disc == 0)
+ {
+ // The GNU Scientific Library returns two identical results here.
+ // We just return one.
+ res[0] = -0.5 * b / a;
+ return 1;
+ }
+
+ // disc > 0
+ if (b == 0)
+ {
+ double r;
+
+ r = Math.abs(0.5 * Math.sqrt(disc) / a);
+ res[0] = -r;
+ res[1] = r;
+ }
+ else
+ {
+ double sgnb;
+ double temp;
+
+ sgnb = (b > 0 ? 1 : -1);
+ temp = -0.5 * (b + sgnb * Math.sqrt(disc));
+
+ // The GNU Scientific Library sorts the result here. We don't.
+ res[0] = temp / a;
+ res[1] = c / temp;
+ }
+ return 2;
+ }
+
+ /**
+ * Determines whether a point is inside the area bounded
+ * by the curve and the straight line connecting its end points.
+ *
+ * <p><img src="doc-files/QuadCurve2D-5.png" width="350" height="180"
+ * alt="A drawing of the area spanned by the curve" />
+ *
+ * <p>The above drawing illustrates in which area points are
+ * considered &#x201c;inside&#x201d; a QuadCurve2D.
+ */
+ public boolean contains(double x, double y)
+ {
+ if (! getBounds2D().contains(x, y))
+ return false;
+
+ return ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0);
+ }
+
+ /**
+ * Determines whether a point is inside the area bounded
+ * by the curve and the straight line connecting its end points.
+ *
+ * <p><img src="doc-files/QuadCurve2D-5.png" width="350" height="180"
+ * alt="A drawing of the area spanned by the curve" />
+ *
+ * <p>The above drawing illustrates in which area points are
+ * considered &#x201c;inside&#x201d; a QuadCurve2D.
+ */
+ public boolean contains(Point2D p)
+ {
+ return contains(p.getX(), p.getY());
+ }
+
+ /**
+ * Determines whether any part of a rectangle is inside the area bounded
+ * by the curve and the straight line connecting its end points.
+ *
+ * <p><img src="doc-files/QuadCurve2D-5.png" width="350" height="180"
+ * alt="A drawing of the area spanned by the curve" />
+ *
+ * <p>The above drawing illustrates in which area points are
+ * considered &#x201c;inside&#x201d; in a CubicCurve2D.
+ */
+ public boolean intersects(double x, double y, double w, double h)
+ {
+ if (! getBounds2D().contains(x, y, w, h))
+ return false;
+
+ /* Does any edge intersect? */
+ if (getAxisIntersections(x, y, true, w) != 0 /* top */
+ || getAxisIntersections(x, y + h, true, w) != 0 /* bottom */
+ || getAxisIntersections(x + w, y, false, h) != 0 /* right */
+ || getAxisIntersections(x, y, false, h) != 0) /* left */
+ return true;
+
+ /* No intersections, is any point inside? */
+ if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0)
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Determines whether any part of a Rectangle2D is inside the area bounded
+ * by the curve and the straight line connecting its end points.
+ * @see #intersects(double, double, double, double)
+ */
+ public boolean intersects(Rectangle2D r)
+ {
+ return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Determines whether a rectangle is entirely inside the area bounded
+ * by the curve and the straight line connecting its end points.
+ *
+ * <p><img src="doc-files/QuadCurve2D-5.png" width="350" height="180"
+ * alt="A drawing of the area spanned by the curve" />
+ *
+ * <p>The above drawing illustrates in which area points are
+ * considered &#x201c;inside&#x201d; a QuadCurve2D.
+ * @see #contains(double, double)
+ */
+ public boolean contains(double x, double y, double w, double h)
+ {
+ if (! getBounds2D().intersects(x, y, w, h))
+ return false;
+
+ /* Does any edge intersect? */
+ if (getAxisIntersections(x, y, true, w) != 0 /* top */
+ || getAxisIntersections(x, y + h, true, w) != 0 /* bottom */
+ || getAxisIntersections(x + w, y, false, h) != 0 /* right */
+ || getAxisIntersections(x, y, false, h) != 0) /* left */
+ return false;
+
+ /* No intersections, is any point inside? */
+ if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0)
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Determines whether a Rectangle2D is entirely inside the area that is
+ * bounded by the curve and the straight line connecting its end points.
+ * @see #contains(double, double, double, double)
+ */
+ public boolean contains(Rectangle2D r)
+ {
+ return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Determines the smallest rectangle that encloses the
+ * curve&#x2019;s start, end and control point. As the illustration
+ * below shows, the invisible control point may cause the bounds to
+ * be much larger than the area that is actually covered by the
+ * curve.
+ *
+ * <p><img src="doc-files/QuadCurve2D-2.png" width="350" height="180"
+ * alt="An illustration of the bounds of a QuadCurve2D" />
+ */
+ public Rectangle getBounds()
+ {
+ return getBounds2D().getBounds();
+ }
+
+ public PathIterator getPathIterator(final AffineTransform at)
+ {
+ return new PathIterator()
+ {
+ /** Current coordinate. */
+ private int current = 0;
+
+ public int getWindingRule()
+ {
+ return WIND_NON_ZERO;
+ }
+
+ public boolean isDone()
+ {
+ return current >= 2;
+ }
+
+ public void next()
+ {
+ current++;
+ }
+
+ public int currentSegment(float[] coords)
+ {
+ int result;
+ switch (current)
+ {
+ case 0:
+ coords[0] = (float) getX1();
+ coords[1] = (float) getY1();
+ result = SEG_MOVETO;
+ break;
+ case 1:
+ coords[0] = (float) getCtrlX();
+ coords[1] = (float) getCtrlY();
+ coords[2] = (float) getX2();
+ coords[3] = (float) getY2();
+ result = SEG_QUADTO;
+ break;
+ default:
+ throw new NoSuchElementException("quad iterator out of bounds");
+ }
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 2);
+ return result;
+ }
+
+ public int currentSegment(double[] coords)
+ {
+ int result;
+ switch (current)
+ {
+ case 0:
+ coords[0] = getX1();
+ coords[1] = getY1();
+ result = SEG_MOVETO;
+ break;
+ case 1:
+ coords[0] = getCtrlX();
+ coords[1] = getCtrlY();
+ coords[2] = getX2();
+ coords[3] = getY2();
+ result = SEG_QUADTO;
+ break;
+ default:
+ throw new NoSuchElementException("quad iterator out of bounds");
+ }
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 2);
+ return result;
+ }
+ };
+ }
+
+ public PathIterator getPathIterator(AffineTransform at, double flatness)
+ {
+ return new FlatteningPathIterator(getPathIterator(at), flatness);
+ }
+
+ /**
+ * Creates a new curve with the same contents as this one.
+ *
+ * @return the clone.
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // Impossible
+ }
+ }
+
+ /**
+ * Helper method used by contains() and intersects() methods
+ * Return the number of curve/line intersections on a given axis
+ * extending from a certain point. useYaxis is true for using the Y axis,
+ * @param x x coordinate of the origin point
+ * @param y y coordinate of the origin point
+ * @param useYaxis axis to follow, if true the positive Y axis is used,
+ * false uses the positive X axis.
+ *
+ * This is an implementation of the line-crossings algorithm,
+ * Detailed in an article on Eric Haines' page:
+ * http://www.acm.org/tog/editors/erich/ptinpoly/
+ */
+ private int getAxisIntersections(double x, double y, boolean useYaxis,
+ double distance)
+ {
+ int nCrossings = 0;
+ double a0;
+ double a1;
+ double a2;
+ double b0;
+ double b1;
+ double b2;
+ double[] r = new double[3];
+ int nRoots;
+
+ a0 = a2 = 0.0;
+
+ if (useYaxis)
+ {
+ a0 = getY1() - y;
+ a1 = getCtrlY() - y;
+ a2 = getY2() - y;
+ b0 = getX1() - x;
+ b1 = getCtrlX() - x;
+ b2 = getX2() - x;
+ }
+ else
+ {
+ a0 = getX1() - x;
+ a1 = getCtrlX() - x;
+ a2 = getX2() - x;
+ b0 = getY1() - y;
+ b1 = getCtrlY() - y;
+ b2 = getY2() - y;
+ }
+
+ /* If the axis intersects a start/endpoint, shift it up by some small
+ amount to guarantee the line is 'inside'
+ If this is not done,bad behaviour may result for points on that axis. */
+ if (a0 == 0.0 || a2 == 0.0)
+ {
+ double small = getFlatness() * EPSILON;
+ if (a0 == 0.0)
+ a0 -= small;
+
+ if (a2 == 0.0)
+ a2 -= small;
+ }
+
+ r[0] = a0;
+ r[1] = 2 * (a1 - a0);
+ r[2] = (a2 - 2 * a1 + a0);
+
+ nRoots = solveQuadratic(r);
+ for (int i = 0; i < nRoots; i++)
+ {
+ double t = r[i];
+ if (t >= 0.0 && t <= 1.0)
+ {
+ double crossing = t * t * (b2 - 2 * b1 + b0) + 2 * t * (b1 - b0)
+ + b0;
+ /* single root is always doubly degenerate in quads */
+ if (crossing > 0 && crossing < distance)
+ nCrossings += (nRoots == 1) ? 2 : 1;
+ }
+ }
+
+ if (useYaxis)
+ {
+ if (Line2D.linesIntersect(b0, a0, b2, a2, EPSILON, 0.0, distance, 0.0))
+ nCrossings++;
+ }
+ else
+ {
+ if (Line2D.linesIntersect(a0, b0, a2, b2, 0.0, EPSILON, 0.0, distance))
+ nCrossings++;
+ }
+
+ return (nCrossings);
+ }
+
+ /**
+ * A two-dimensional curve that is parameterized with a quadratic
+ * function and stores coordinate values in double-precision
+ * floating-point format.
+ *
+ * @see QuadCurve2D.Float
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ */
+ public static class Double extends QuadCurve2D
+ {
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s start point.
+ */
+ public double x1;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s start point.
+ */
+ public double y1;
+
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s control point.
+ */
+ public double ctrlx;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s control point.
+ */
+ public double ctrly;
+
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s end point.
+ */
+ public double x2;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s end point.
+ */
+ public double y2;
+
+ /**
+ * Constructs a new QuadCurve2D that stores its coordinate values
+ * in double-precision floating-point format. All points are
+ * initially at position (0, 0).
+ */
+ public Double()
+ {
+ }
+
+ /**
+ * Constructs a new QuadCurve2D that stores its coordinate values
+ * in double-precision floating-point format, specifying the
+ * initial position of each point.
+ *
+ * @param x1 the <i>x</i> coordinate of the curve&#x2019;s start
+ * point.
+ *
+ * @param y1 the <i>y</i> coordinate of the curve&#x2019;s start
+ * point.
+ *
+ * @param cx the <i>x</i> coordinate of the curve&#x2019;s control
+ * point.
+ *
+ * @param cy the <i>y</i> coordinate of the curve&#x2019;s control
+ * point.
+ *
+ * @param x2 the <i>x</i> coordinate of the curve&#x2019;s end
+ * point.
+ *
+ * @param y2 the <i>y</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public Double(double x1, double y1, double cx, double cy, double x2,
+ double y2)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ ctrlx = cx;
+ ctrly = cy;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s start
+ * point.
+ */
+ public double getX1()
+ {
+ return x1;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s start
+ * point.
+ */
+ public double getY1()
+ {
+ return y1;
+ }
+
+ /**
+ * Returns the curve&#x2019;s start point.
+ */
+ public Point2D getP1()
+ {
+ return new Point2D.Double(x1, y1);
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s control
+ * point.
+ */
+ public double getCtrlX()
+ {
+ return ctrlx;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s control
+ * point.
+ */
+ public double getCtrlY()
+ {
+ return ctrly;
+ }
+
+ /**
+ * Returns the curve&#x2019;s control point.
+ */
+ public Point2D getCtrlPt()
+ {
+ return new Point2D.Double(ctrlx, ctrly);
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public double getX2()
+ {
+ return x2;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public double getY2()
+ {
+ return y2;
+ }
+
+ /**
+ * Returns the curve&#x2019;s end point.
+ */
+ public Point2D getP2()
+ {
+ return new Point2D.Double(x2, y2);
+ }
+
+ /**
+ * Changes the geometry of the curve.
+ *
+ * @param x1 the <i>x</i> coordinate of the curve&#x2019;s new
+ * start point.
+ *
+ * @param y1 the <i>y</i> coordinate of the curve&#x2019;s new
+ * start point.
+ *
+ * @param cx the <i>x</i> coordinate of the curve&#x2019;s new
+ * control point.
+ *
+ * @param cy the <i>y</i> coordinate of the curve&#x2019;s new
+ * control point.
+ *
+ * @param x2 the <i>x</i> coordinate of the curve&#x2019;s new
+ * end point.
+ *
+ * @param y2 the <i>y</i> coordinate of the curve&#x2019;s new
+ * end point.
+ */
+ public void setCurve(double x1, double y1, double cx, double cy,
+ double x2, double y2)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ ctrlx = cx;
+ ctrly = cy;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+
+ /**
+ * Determines the smallest rectangle that encloses the
+ * curve&#x2019;s start, end and control point. As the
+ * illustration below shows, the invisible control point may cause
+ * the bounds to be much larger than the area that is actually
+ * covered by the curve.
+ *
+ * <p><img src="doc-files/QuadCurve2D-2.png" width="350" height="180"
+ * alt="An illustration of the bounds of a QuadCurve2D" />
+ */
+ public Rectangle2D getBounds2D()
+ {
+ double nx1 = Math.min(Math.min(x1, ctrlx), x2);
+ double ny1 = Math.min(Math.min(y1, ctrly), y2);
+ double nx2 = Math.max(Math.max(x1, ctrlx), x2);
+ double ny2 = Math.max(Math.max(y1, ctrly), y2);
+ return new Rectangle2D.Double(nx1, ny1, nx2 - nx1, ny2 - ny1);
+ }
+ }
+
+ /**
+ * A two-dimensional curve that is parameterized with a quadratic
+ * function and stores coordinate values in single-precision
+ * floating-point format.
+ *
+ * @see QuadCurve2D.Double
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ */
+ public static class Float extends QuadCurve2D
+ {
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s start point.
+ */
+ public float x1;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s start point.
+ */
+ public float y1;
+
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s control point.
+ */
+ public float ctrlx;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s control point.
+ */
+ public float ctrly;
+
+ /**
+ * The <i>x</i> coordinate of the curve&#x2019;s end point.
+ */
+ public float x2;
+
+ /**
+ * The <i>y</i> coordinate of the curve&#x2019;s end point.
+ */
+ public float y2;
+
+ /**
+ * Constructs a new QuadCurve2D that stores its coordinate values
+ * in single-precision floating-point format. All points are
+ * initially at position (0, 0).
+ */
+ public Float()
+ {
+ }
+
+ /**
+ * Constructs a new QuadCurve2D that stores its coordinate values
+ * in single-precision floating-point format, specifying the
+ * initial position of each point.
+ *
+ * @param x1 the <i>x</i> coordinate of the curve&#x2019;s start
+ * point.
+ *
+ * @param y1 the <i>y</i> coordinate of the curve&#x2019;s start
+ * point.
+ *
+ * @param cx the <i>x</i> coordinate of the curve&#x2019;s control
+ * point.
+ *
+ * @param cy the <i>y</i> coordinate of the curve&#x2019;s control
+ * point.
+ *
+ * @param x2 the <i>x</i> coordinate of the curve&#x2019;s end
+ * point.
+ *
+ * @param y2 the <i>y</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public Float(float x1, float y1, float cx, float cy, float x2, float y2)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ ctrlx = cx;
+ ctrly = cy;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s start
+ * point.
+ */
+ public double getX1()
+ {
+ return x1;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s start
+ * point.
+ */
+ public double getY1()
+ {
+ return y1;
+ }
+
+ /**
+ * Returns the curve&#x2019;s start point.
+ */
+ public Point2D getP1()
+ {
+ return new Point2D.Float(x1, y1);
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s control
+ * point.
+ */
+ public double getCtrlX()
+ {
+ return ctrlx;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s control
+ * point.
+ */
+ public double getCtrlY()
+ {
+ return ctrly;
+ }
+
+ /**
+ * Returns the curve&#x2019;s control point.
+ */
+ public Point2D getCtrlPt()
+ {
+ return new Point2D.Float(ctrlx, ctrly);
+ }
+
+ /**
+ * Returns the <i>x</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public double getX2()
+ {
+ return x2;
+ }
+
+ /**
+ * Returns the <i>y</i> coordinate of the curve&#x2019;s end
+ * point.
+ */
+ public double getY2()
+ {
+ return y2;
+ }
+
+ /**
+ * Returns the curve&#x2019;s end point.
+ */
+ public Point2D getP2()
+ {
+ return new Point2D.Float(x2, y2);
+ }
+
+ /**
+ * Changes the geometry of the curve, specifying coordinate values
+ * as double-precision floating-point numbers.
+ *
+ * @param x1 the <i>x</i> coordinate of the curve&#x2019;s new
+ * start point.
+ *
+ * @param y1 the <i>y</i> coordinate of the curve&#x2019;s new
+ * start point.
+ *
+ * @param cx the <i>x</i> coordinate of the curve&#x2019;s new
+ * control point.
+ *
+ * @param cy the <i>y</i> coordinate of the curve&#x2019;s new
+ * control point.
+ *
+ * @param x2 the <i>x</i> coordinate of the curve&#x2019;s new
+ * end point.
+ *
+ * @param y2 the <i>y</i> coordinate of the curve&#x2019;s new
+ * end point.
+ */
+ public void setCurve(double x1, double y1, double cx, double cy,
+ double x2, double y2)
+ {
+ this.x1 = (float) x1;
+ this.y1 = (float) y1;
+ ctrlx = (float) cx;
+ ctrly = (float) cy;
+ this.x2 = (float) x2;
+ this.y2 = (float) y2;
+ }
+
+ /**
+ * Changes the geometry of the curve, specifying coordinate values
+ * as single-precision floating-point numbers.
+ *
+ * @param x1 the <i>x</i> coordinate of the curve&#x2019;s new
+ * start point.
+ *
+ * @param y1 the <i>y</i> coordinate of the curve&#x2019;s new
+ * start point.
+ *
+ * @param cx the <i>x</i> coordinate of the curve&#x2019;s new
+ * control point.
+ *
+ * @param cy the <i>y</i> coordinate of the curve&#x2019;s new
+ * control point.
+ *
+ * @param x2 the <i>x</i> coordinate of the curve&#x2019;s new
+ * end point.
+ *
+ * @param y2 the <i>y</i> coordinate of the curve&#x2019;s new
+ * end point.
+ */
+ public void setCurve(float x1, float y1, float cx, float cy, float x2,
+ float y2)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ ctrlx = cx;
+ ctrly = cy;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+
+ /**
+ * Determines the smallest rectangle that encloses the
+ * curve&#x2019;s start, end and control point. As the
+ * illustration below shows, the invisible control point may cause
+ * the bounds to be much larger than the area that is actually
+ * covered by the curve.
+ *
+ * <p><img src="doc-files/QuadCurve2D-2.png" width="350" height="180"
+ * alt="An illustration of the bounds of a QuadCurve2D" />
+ */
+ public Rectangle2D getBounds2D()
+ {
+ float nx1 = Math.min(Math.min(x1, ctrlx), x2);
+ float ny1 = Math.min(Math.min(y1, ctrly), y2);
+ float nx2 = Math.max(Math.max(x1, ctrlx), x2);
+ float ny2 = Math.max(Math.max(y1, ctrly), y2);
+ return new Rectangle2D.Float(nx1, ny1, nx2 - nx1, ny2 - ny1);
+ }
+ }
+}
diff --git a/libjava/classpath/java/awt/geom/Rectangle2D.java b/libjava/classpath/java/awt/geom/Rectangle2D.java
new file mode 100644
index 000000000..6a255f953
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/Rectangle2D.java
@@ -0,0 +1,992 @@
+/* Rectangle2D.java -- generic rectangles in 2-D space
+ Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.geom;
+
+import java.util.NoSuchElementException;
+
+/**
+ * This class describes a rectangle by a point (x,y) and dimension (w x h).
+ * The actual storage is left up to subclasses.
+ *
+ * <p>It is valid for a rectangle to have negative width or height; but it
+ * is considered to have no area or internal points. Therefore, the behavior
+ * in methods like <code>contains</code> or <code>intersects</code> is
+ * undefined unless the rectangle has positive width and height.
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public abstract class Rectangle2D extends RectangularShape
+{
+ /**
+ * The point lies left of the rectangle (p.x &lt; r.x).
+ *
+ * @see #outcode(double, double)
+ */
+ public static final int OUT_LEFT = 1;
+
+ /**
+ * The point lies above the rectangle (p.y &lt; r.y).
+ *
+ * @see #outcode(double, double)
+ */
+ public static final int OUT_TOP = 2;
+
+ /**
+ * The point lies right of the rectangle (p.x &gt; r.maxX).
+ *
+ * @see #outcode(double, double)
+ */
+ public static final int OUT_RIGHT = 4;
+
+ /**
+ * The point lies below of the rectangle (p.y &gt; r.maxY).
+ *
+ * @see #outcode(double, double)
+ */
+ public static final int OUT_BOTTOM = 8;
+
+ /**
+ * Default constructor.
+ */
+ protected Rectangle2D()
+ {
+ }
+
+ /**
+ * Set the bounding box of this rectangle.
+ *
+ * @param x the new X coordinate
+ * @param y the new Y coordinate
+ * @param w the new width
+ * @param h the new height
+ */
+ public abstract void setRect(double x, double y, double w, double h);
+
+ /**
+ * Set the bounding box of this rectangle from the given one.
+ *
+ * @param r rectangle to copy
+ * @throws NullPointerException if r is null
+ */
+ public void setRect(Rectangle2D r)
+ {
+ setRect(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Tests if the specified line intersects the interior of this rectangle.
+ *
+ * @param x1 the first x coordinate of line segment
+ * @param y1 the first y coordinate of line segment
+ * @param x2 the second x coordinate of line segment
+ * @param y2 the second y coordinate of line segment
+ * @return true if the line intersects the rectangle
+ */
+ public boolean intersectsLine(double x1, double y1, double x2, double y2)
+ {
+ double x = getX();
+ double y = getY();
+ double w = getWidth();
+ double h = getHeight();
+ if (w <= 0 || h <= 0)
+ return false;
+
+ if (x1 >= x && x1 <= x + w && y1 >= y && y1 <= y + h)
+ return true;
+ if (x2 >= x && x2 <= x + w && y2 >= y && y2 <= y + h)
+ return true;
+
+ double x3 = x + w;
+ double y3 = y + h;
+
+ return (Line2D.linesIntersect(x1, y1, x2, y2, x, y, x, y3)
+ || Line2D.linesIntersect(x1, y1, x2, y2, x, y3, x3, y3)
+ || Line2D.linesIntersect(x1, y1, x2, y2, x3, y3, x3, y)
+ || Line2D.linesIntersect(x1, y1, x2, y2, x3, y, x, y));
+ }
+
+ /**
+ * Tests if the specified line intersects the interior of this rectangle.
+ *
+ * @param l the line segment
+ * @return true if the line intersects the rectangle
+ * @throws NullPointerException if l is null
+ */
+ public boolean intersectsLine(Line2D l)
+ {
+ return intersectsLine(l.getX1(), l.getY1(), l.getX2(), l.getY2());
+ }
+
+ /**
+ * Determine where the point lies with respect to this rectangle. The
+ * result will be the binary OR of the appropriate bit masks.
+ *
+ * @param x the x coordinate to check
+ * @param y the y coordinate to check
+ * @return the binary OR of the result
+ * @see #OUT_LEFT
+ * @see #OUT_TOP
+ * @see #OUT_RIGHT
+ * @see #OUT_BOTTOM
+ */
+ public abstract int outcode(double x, double y);
+
+ /**
+ * Determine where the point lies with respect to this rectangle. The
+ * result will be the binary OR of the appropriate bit masks.
+ *
+ * @param p the point to check
+ * @return the binary OR of the result
+ * @throws NullPointerException if p is null
+ * @see #OUT_LEFT
+ * @see #OUT_TOP
+ * @see #OUT_RIGHT
+ * @see #OUT_BOTTOM
+ */
+ public int outcode(Point2D p)
+ {
+ return outcode(p.getX(), p.getY());
+ }
+
+ /**
+ * Set the bounding box of this rectangle.
+ *
+ * @param x the new X coordinate
+ * @param y the new Y coordinate
+ * @param w the new width
+ * @param h the new height
+ */
+ public void setFrame(double x, double y, double w, double h)
+ {
+ setRect(x, y, w, h);
+ }
+
+ /**
+ * Returns the bounds of this rectangle. A pretty useless method, as this
+ * is already a rectangle.
+ *
+ * @return a copy of this rectangle
+ */
+ public Rectangle2D getBounds2D()
+ {
+ return (Rectangle2D) clone();
+ }
+
+ /**
+ * Test if the given point is contained in the rectangle.
+ *
+ * @param x the x coordinate of the point
+ * @param y the y coordinate of the point
+ * @return true if (x,y) is in the rectangle
+ */
+ public boolean contains(double x, double y)
+ {
+ double mx = getX();
+ double my = getY();
+ double w = getWidth();
+ double h = getHeight();
+ return w > 0 && h > 0 && x >= mx && x < mx + w && y >= my && y < my + h;
+ }
+
+ /**
+ * Tests if the given rectangle intersects this one. In other words, test if
+ * the two rectangles share at least one internal point.
+ *
+ * @param x the x coordinate of the other rectangle
+ * @param y the y coordinate of the other rectangle
+ * @param w the width of the other rectangle
+ * @param h the height of the other rectangle
+ * @return true if the rectangles intersect
+ */
+ public boolean intersects(double x, double y, double w, double h)
+ {
+ double mx = getX();
+ double my = getY();
+ double mw = getWidth();
+ double mh = getHeight();
+ return w > 0 && h > 0 && mw > 0 && mh > 0
+ && x < mx + mw && x + w > mx && y < my + mh && y + h > my;
+ }
+
+ /**
+ * Tests if this rectangle contains the given one. In other words, test if
+ * this rectangle contains all points in the given one.
+ *
+ * @param x the x coordinate of the other rectangle
+ * @param y the y coordinate of the other rectangle
+ * @param w the width of the other rectangle
+ * @param h the height of the other rectangle
+ * @return true if this rectangle contains the other
+ */
+ public boolean contains(double x, double y, double w, double h)
+ {
+ double mx = getX();
+ double my = getY();
+ double mw = getWidth();
+ double mh = getHeight();
+ return w > 0 && h > 0 && mw > 0 && mh > 0
+ && x >= mx && x + w <= mx + mw && y >= my && y + h <= my + mh;
+ }
+
+ /**
+ * Return a new rectangle which is the intersection of this and the given
+ * one. The result will be empty if there is no intersection.
+ *
+ * @param r the rectangle to be intersected
+ * @return the intersection
+ * @throws NullPointerException if r is null
+ */
+ public abstract Rectangle2D createIntersection(Rectangle2D r);
+
+ /**
+ * Intersects a pair of rectangles, and places the result in the
+ * destination; this can be used to avoid object creation. This method
+ * even works when the destination is also a source, although you stand
+ * to lose the original data.
+ *
+ * @param src1 the first source
+ * @param src2 the second source
+ * @param dest the destination for the intersection
+ * @throws NullPointerException if any rectangle is null
+ */
+ public static void intersect(Rectangle2D src1, Rectangle2D src2,
+ Rectangle2D dest)
+ {
+ double x = Math.max(src1.getX(), src2.getX());
+ double y = Math.max(src1.getY(), src2.getY());
+ double maxx = Math.min(src1.getMaxX(), src2.getMaxX());
+ double maxy = Math.min(src1.getMaxY(), src2.getMaxY());
+ dest.setRect(x, y, maxx - x, maxy - y);
+ }
+
+ /**
+ * Return a new rectangle which is the union of this and the given one.
+ *
+ * @param r the rectangle to be merged
+ * @return the union
+ * @throws NullPointerException if r is null
+ */
+ public abstract Rectangle2D createUnion(Rectangle2D r);
+
+ /**
+ * Joins a pair of rectangles, and places the result in the destination;
+ * this can be used to avoid object creation. This method even works when
+ * the destination is also a source, although you stand to lose the
+ * original data.
+ *
+ * @param src1 the first source
+ * @param src2 the second source
+ * @param dest the destination for the union
+ * @throws NullPointerException if any rectangle is null
+ */
+ public static void union(Rectangle2D src1, Rectangle2D src2,
+ Rectangle2D dest)
+ {
+ double x = Math.min(src1.getX(), src2.getX());
+ double y = Math.min(src1.getY(), src2.getY());
+ double maxx = Math.max(src1.getMaxX(), src2.getMaxX());
+ double maxy = Math.max(src1.getMaxY(), src2.getMaxY());
+ dest.setRect(x, y, maxx - x, maxy - y);
+ }
+
+ /**
+ * Modifies this rectangle so that it represents the smallest rectangle
+ * that contains both the existing rectangle and the specified point.
+ * However, if the point falls on one of the two borders which are not
+ * inside the rectangle, a subsequent call to <code>contains</code> may
+ * return false.
+ *
+ * @param newx the X coordinate of the point to add to this rectangle
+ * @param newy the Y coordinate of the point to add to this rectangle
+ */
+ public void add(double newx, double newy)
+ {
+ double minx = Math.min(getX(), newx);
+ double maxx = Math.max(getMaxX(), newx);
+ double miny = Math.min(getY(), newy);
+ double maxy = Math.max(getMaxY(), newy);
+ setRect(minx, miny, maxx - minx, maxy - miny);
+ }
+
+ /**
+ * Modifies this rectangle so that it represents the smallest rectangle
+ * that contains both the existing rectangle and the specified point.
+ * However, if the point falls on one of the two borders which are not
+ * inside the rectangle, a subsequent call to <code>contains</code> may
+ * return false.
+ *
+ * @param p the point to add to this rectangle
+ * @throws NullPointerException if p is null
+ */
+ public void add(Point2D p)
+ {
+ add(p.getX(), p.getY());
+ }
+
+ /**
+ * Modifies this rectangle so that it represents the smallest rectangle
+ * that contains both the existing rectangle and the specified rectangle.
+ *
+ * @param r the rectangle to add to this rectangle
+ * @throws NullPointerException if r is null
+ * @see #union(Rectangle2D, Rectangle2D, Rectangle2D)
+ */
+ public void add(Rectangle2D r)
+ {
+ union(this, r, this);
+ }
+
+ /**
+ * Return an iterator along the shape boundary. If the optional transform
+ * is provided, the iterator is transformed accordingly. Each call returns
+ * a new object, independent from others in use. This iterator is thread
+ * safe; modifications to the rectangle do not affect the results of this
+ * path instance.
+ *
+ * @param at an optional transform to apply to the iterator
+ * @return a new iterator over the boundary
+ * @since 1.2
+ */
+ public PathIterator getPathIterator(final AffineTransform at)
+ {
+ final double minx = getX();
+ final double miny = getY();
+ final double maxx = minx + getWidth();
+ final double maxy = miny + getHeight();
+ return new PathIterator()
+ {
+ /** Current coordinate. */
+ private int current = (maxx <= minx && maxy <= miny) ? 6 : 0;
+
+ public int getWindingRule()
+ {
+ // A test program showed that Sun J2SE 1.3.1 and 1.4.1_01
+ // return WIND_NON_ZERO paths. While this does not really
+ // make any difference for rectangles (because they are not
+ // self-intersecting), it seems appropriate to behave
+ // identically.
+
+ return WIND_NON_ZERO;
+ }
+
+ public boolean isDone()
+ {
+ return current > 5;
+ }
+
+ public void next()
+ {
+ current++;
+ }
+
+ public int currentSegment(float[] coords)
+ {
+ switch (current)
+ {
+ case 1:
+ coords[0] = (float) maxx;
+ coords[1] = (float) miny;
+ break;
+ case 2:
+ coords[0] = (float) maxx;
+ coords[1] = (float) maxy;
+ break;
+ case 3:
+ coords[0] = (float) minx;
+ coords[1] = (float) maxy;
+ break;
+ case 0:
+ case 4:
+ coords[0] = (float) minx;
+ coords[1] = (float) miny;
+ break;
+ case 5:
+ return SEG_CLOSE;
+ default:
+ throw new NoSuchElementException("rect iterator out of bounds");
+ }
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 1);
+ return current == 0 ? SEG_MOVETO : SEG_LINETO;
+ }
+
+ public int currentSegment(double[] coords)
+ {
+ switch (current)
+ {
+ case 1:
+ coords[0] = maxx;
+ coords[1] = miny;
+ break;
+ case 2:
+ coords[0] = maxx;
+ coords[1] = maxy;
+ break;
+ case 3:
+ coords[0] = minx;
+ coords[1] = maxy;
+ break;
+ case 0:
+ case 4:
+ coords[0] = minx;
+ coords[1] = miny;
+ break;
+ case 5:
+ return SEG_CLOSE;
+ default:
+ throw new NoSuchElementException("rect iterator out of bounds");
+ }
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 1);
+ return current == 0 ? SEG_MOVETO : SEG_LINETO;
+ }
+ };
+ }
+
+ /**
+ * Return an iterator along the shape boundary. If the optional transform
+ * is provided, the iterator is transformed accordingly. Each call returns
+ * a new object, independent from others in use. This iterator is thread
+ * safe; modifications to the rectangle do not affect the results of this
+ * path instance. As the rectangle is already flat, the flatness parameter
+ * is ignored.
+ *
+ * @param at an optional transform to apply to the iterator
+ * @param flatness the maximum distance for deviation from the real boundary
+ * @return a new iterator over the boundary
+ * @since 1.2
+ */
+ public PathIterator getPathIterator(AffineTransform at, double flatness)
+ {
+ return getPathIterator(at);
+ }
+
+ /**
+ * Return the hashcode for this rectangle. The formula is not documented, but
+ * appears to be the same as:
+ * <pre>
+ * long l = Double.doubleToLongBits(getX())
+ * + 37 * Double.doubleToLongBits(getY())
+ * + 43 * Double.doubleToLongBits(getWidth())
+ * + 47 * Double.doubleToLongBits(getHeight());
+ * return (int) ((l &gt;&gt; 32) ^ l);
+ * </pre>
+ *
+ * @return the hashcode
+ */
+ public int hashCode()
+ {
+ // Talk about a fun time reverse engineering this one!
+ long l = java.lang.Double.doubleToLongBits(getX())
+ + 37 * java.lang.Double.doubleToLongBits(getY())
+ + 43 * java.lang.Double.doubleToLongBits(getWidth())
+ + 47 * java.lang.Double.doubleToLongBits(getHeight());
+ return (int) ((l >> 32) ^ l);
+ }
+
+ /**
+ * Tests this rectangle for equality against the specified object. This
+ * will be true if an only if the specified object is an instance of
+ * Rectangle2D with the same coordinates and dimensions.
+ *
+ * @param obj the object to test against for equality
+ * @return true if the specified object is equal to this one
+ */
+ public boolean equals(Object obj)
+ {
+ if (! (obj instanceof Rectangle2D))
+ return false;
+ Rectangle2D r = (Rectangle2D) obj;
+ return r.getX() == getX() && r.getY() == getY()
+ && r.getWidth() == getWidth() && r.getHeight() == getHeight();
+ }
+
+ /**
+ * This class defines a rectangle in <code>double</code> precision.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+ public static class Double extends Rectangle2D
+ {
+ /** The x coordinate of the lower left corner. */
+ public double x;
+
+ /** The y coordinate of the lower left corner. */
+ public double y;
+
+ /** The width of the rectangle. */
+ public double width;
+
+ /** The height of the rectangle. */
+ public double height;
+
+ /**
+ * Create a rectangle at (0,0) with width 0 and height 0.
+ */
+ public Double()
+ {
+ }
+
+ /**
+ * Create a rectangle with the given values.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param w the width
+ * @param h the height
+ */
+ public Double(double x, double y, double w, double h)
+ {
+ this.x = x;
+ this.y = y;
+ width = w;
+ height = h;
+ }
+
+ /**
+ * Return the X coordinate.
+ *
+ * @return the value of x
+ */
+ public double getX()
+ {
+ return x;
+ }
+
+ /**
+ * Return the Y coordinate.
+ *
+ * @return the value of y
+ */
+ public double getY()
+ {
+ return y;
+ }
+
+ /**
+ * Return the width.
+ *
+ * @return the value of width
+ */
+ public double getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Return the height.
+ *
+ * @return the value of height
+ */
+ public double getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * Test if the rectangle is empty.
+ *
+ * @return true if width or height is not positive
+ */
+ public boolean isEmpty()
+ {
+ return width <= 0 || height <= 0;
+ }
+
+ /**
+ * Set the contents of this rectangle to those specified.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param w the width
+ * @param h the height
+ */
+ public void setRect(double x, double y, double w, double h)
+ {
+ this.x = x;
+ this.y = y;
+ width = w;
+ height = h;
+ }
+
+ /**
+ * Set the contents of this rectangle to those specified.
+ *
+ * @param r the rectangle to copy
+ * @throws NullPointerException if r is null
+ */
+ public void setRect(Rectangle2D r)
+ {
+ x = r.getX();
+ y = r.getY();
+ width = r.getWidth();
+ height = r.getHeight();
+ }
+
+ /**
+ * Determine where the point lies with respect to this rectangle. The
+ * result will be the binary OR of the appropriate bit masks.
+ *
+ * @param x the x coordinate to check
+ * @param y the y coordinate to check
+ * @return the binary OR of the result
+ * @see #OUT_LEFT
+ * @see #OUT_TOP
+ * @see #OUT_RIGHT
+ * @see #OUT_BOTTOM
+ * @since 1.2
+ */
+ public int outcode(double x, double y)
+ {
+ int result = 0;
+ if (width <= 0)
+ result |= OUT_LEFT | OUT_RIGHT;
+ else if (x < this.x)
+ result |= OUT_LEFT;
+ else if (x > this.x + width)
+ result |= OUT_RIGHT;
+ if (height <= 0)
+ result |= OUT_BOTTOM | OUT_TOP;
+ else if (y < this.y) // Remember that +y heads top-to-bottom.
+ result |= OUT_TOP;
+ else if (y > this.y + height)
+ result |= OUT_BOTTOM;
+ return result;
+ }
+
+ /**
+ * Returns the bounds of this rectangle. A pretty useless method, as this
+ * is already a rectangle.
+ *
+ * @return a copy of this rectangle
+ */
+ public Rectangle2D getBounds2D()
+ {
+ return new Double(x, y, width, height);
+ }
+
+ /**
+ * Return a new rectangle which is the intersection of this and the given
+ * one. The result will be empty if there is no intersection.
+ *
+ * @param r the rectangle to be intersected
+ * @return the intersection
+ * @throws NullPointerException if r is null
+ */
+ public Rectangle2D createIntersection(Rectangle2D r)
+ {
+ Double res = new Double();
+ intersect(this, r, res);
+ return res;
+ }
+
+ /**
+ * Return a new rectangle which is the union of this and the given one.
+ *
+ * @param r the rectangle to be merged
+ * @return the union
+ * @throws NullPointerException if r is null
+ */
+ public Rectangle2D createUnion(Rectangle2D r)
+ {
+ Double res = new Double();
+ union(this, r, res);
+ return res;
+ }
+
+ /**
+ * Returns a string representation of this rectangle. This is in the form
+ * <code>getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width
+ * + ",h=" + height + ']'</code>.
+ *
+ * @return a string representation of this rectangle
+ */
+ public String toString()
+ {
+ return getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width
+ + ",h=" + height + ']';
+ }
+ }
+
+ /**
+ * This class defines a rectangle in <code>float</code> precision.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+ public static class Float extends Rectangle2D
+ {
+ /** The x coordinate of the lower left corner. */
+ public float x;
+
+ /** The y coordinate of the lower left corner. */
+ public float y;
+
+ /** The width of the rectangle. */
+ public float width;
+
+ /** The height of the rectangle. */
+ public float height;
+
+ /**
+ * Create a rectangle at (0,0) with width 0 and height 0.
+ */
+ public Float()
+ {
+ }
+
+ /**
+ * Create a rectangle with the given values.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param w the width
+ * @param h the height
+ */
+ public Float(float x, float y, float w, float h)
+ {
+ this.x = x;
+ this.y = y;
+ width = w;
+ height = h;
+ }
+
+ /**
+ * Create a rectangle with the given values.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param w the width
+ * @param h the height
+ */
+ Float(double x, double y, double w, double h)
+ {
+ this.x = (float) x;
+ this.y = (float) y;
+ width = (float) w;
+ height = (float) h;
+ }
+
+ /**
+ * Return the X coordinate.
+ *
+ * @return the value of x
+ */
+ public double getX()
+ {
+ return x;
+ }
+
+ /**
+ * Return the Y coordinate.
+ *
+ * @return the value of y
+ */
+ public double getY()
+ {
+ return y;
+ }
+
+ /**
+ * Return the width.
+ *
+ * @return the value of width
+ */
+ public double getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Return the height.
+ *
+ * @return the value of height
+ */
+ public double getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * Test if the rectangle is empty.
+ *
+ * @return true if width or height is not positive
+ */
+ public boolean isEmpty()
+ {
+ return width <= 0 || height <= 0;
+ }
+
+ /**
+ * Set the contents of this rectangle to those specified.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param w the width
+ * @param h the height
+ */
+ public void setRect(float x, float y, float w, float h)
+ {
+ this.x = x;
+ this.y = y;
+ width = w;
+ height = h;
+ }
+
+ /**
+ * Set the contents of this rectangle to those specified.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param w the width
+ * @param h the height
+ */
+ public void setRect(double x, double y, double w, double h)
+ {
+ this.x = (float) x;
+ this.y = (float) y;
+ width = (float) w;
+ height = (float) h;
+ }
+
+ /**
+ * Set the contents of this rectangle to those specified.
+ *
+ * @param r the rectangle to copy
+ * @throws NullPointerException if r is null
+ */
+ public void setRect(Rectangle2D r)
+ {
+ x = (float) r.getX();
+ y = (float) r.getY();
+ width = (float) r.getWidth();
+ height = (float) r.getHeight();
+ }
+
+ /**
+ * Determine where the point lies with respect to this rectangle. The
+ * result will be the binary OR of the appropriate bit masks.
+ *
+ * @param x the x coordinate to check
+ * @param y the y coordinate to check
+ * @return the binary OR of the result
+ * @see #OUT_LEFT
+ * @see #OUT_TOP
+ * @see #OUT_RIGHT
+ * @see #OUT_BOTTOM
+ * @since 1.2
+ */
+ public int outcode(double x, double y)
+ {
+ int result = 0;
+ if (width <= 0)
+ result |= OUT_LEFT | OUT_RIGHT;
+ else if (x < this.x)
+ result |= OUT_LEFT;
+ else if (x > this.x + width)
+ result |= OUT_RIGHT;
+ if (height <= 0)
+ result |= OUT_BOTTOM | OUT_TOP;
+ else if (y < this.y) // Remember that +y heads top-to-bottom.
+ result |= OUT_TOP;
+ else if (y > this.y + height)
+ result |= OUT_BOTTOM;
+ return result;
+ }
+
+ /**
+ * Returns the bounds of this rectangle. A pretty useless method, as this
+ * is already a rectangle.
+ *
+ * @return a copy of this rectangle
+ */
+ public Rectangle2D getBounds2D()
+ {
+ return new Float(x, y, width, height);
+ }
+
+ /**
+ * Return a new rectangle which is the intersection of this and the given
+ * one. The result will be empty if there is no intersection.
+ *
+ * @param r the rectangle to be intersected
+ * @return the intersection
+ * @throws NullPointerException if r is null
+ */
+ public Rectangle2D createIntersection(Rectangle2D r)
+ {
+ Float res = new Float();
+ intersect(this, r, res);
+ return res;
+ }
+
+ /**
+ * Return a new rectangle which is the union of this and the given one.
+ *
+ * @param r the rectangle to be merged
+ * @return the union
+ * @throws NullPointerException if r is null
+ */
+ public Rectangle2D createUnion(Rectangle2D r)
+ {
+ Float res = new Float();
+ union(this, r, res);
+ return res;
+ }
+
+ /**
+ * Returns a string representation of this rectangle. This is in the form
+ * <code>getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width
+ * + ",h=" + height + ']'</code>.
+ *
+ * @return a string representation of this rectangle
+ */
+ public String toString()
+ {
+ return getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width
+ + ",h=" + height + ']';
+ }
+ }
+}
diff --git a/libjava/classpath/java/awt/geom/RectangularShape.java b/libjava/classpath/java/awt/geom/RectangularShape.java
new file mode 100644
index 000000000..68bc451cc
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/RectangularShape.java
@@ -0,0 +1,382 @@
+/* RectangularShape.java -- a rectangular frame for several generic shapes
+ Copyright (C) 2000, 2002 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.geom;
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+
+/**
+ * This class provides a generic framework, and several helper methods, for
+ * subclasses which represent geometric objects inside a rectangular frame.
+ * This does not specify any geometry except for the bounding box.
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @see Arc2D
+ * @see Ellipse2D
+ * @see Rectangle2D
+ * @see RoundRectangle2D
+ * @status updated to 1.4
+ */
+public abstract class RectangularShape implements Shape, Cloneable
+{
+ /**
+ * Default constructor.
+ */
+ protected RectangularShape()
+ {
+ }
+
+ /**
+ * Get the x coordinate of the upper-left corner of the framing rectangle.
+ *
+ * @return the x coordinate
+ */
+ public abstract double getX();
+
+ /**
+ * Get the y coordinate of the upper-left corner of the framing rectangle.
+ *
+ * @return the y coordinate
+ */
+ public abstract double getY();
+
+ /**
+ * Get the width of the framing rectangle.
+ *
+ * @return the width
+ */
+ public abstract double getWidth();
+
+ /**
+ * Get the height of the framing rectangle.
+ *
+ * @return the height
+ */
+ public abstract double getHeight();
+
+ /**
+ * Get the minimum x coordinate in the frame. This is misnamed, or else
+ * Sun has a bug, because the implementation returns getX() even when
+ * getWidth() is negative.
+ *
+ * @return the minimum x coordinate
+ */
+ public double getMinX()
+ {
+ return getX();
+ }
+
+ /**
+ * Get the minimum y coordinate in the frame. This is misnamed, or else
+ * Sun has a bug, because the implementation returns getY() even when
+ * getHeight() is negative.
+ *
+ * @return the minimum y coordinate
+ */
+ public double getMinY()
+ {
+ return getY();
+ }
+
+ /**
+ * Get the maximum x coordinate in the frame. This is misnamed, or else
+ * Sun has a bug, because the implementation returns getX()+getWidth() even
+ * when getWidth() is negative.
+ *
+ * @return the maximum x coordinate
+ */
+ public double getMaxX()
+ {
+ return getX() + getWidth();
+ }
+
+ /**
+ * Get the maximum y coordinate in the frame. This is misnamed, or else
+ * Sun has a bug, because the implementation returns getY()+getHeight() even
+ * when getHeight() is negative.
+ *
+ * @return the maximum y coordinate
+ */
+ public double getMaxY()
+ {
+ return getY() + getHeight();
+ }
+
+ /**
+ * Return the x coordinate of the center point of the framing rectangle.
+ *
+ * @return the central x coordinate
+ */
+ public double getCenterX()
+ {
+ return getX() + getWidth() / 2;
+ }
+
+ /**
+ * Return the y coordinate of the center point of the framing rectangle.
+ *
+ * @return the central y coordinate
+ */
+ public double getCenterY()
+ {
+ return getY() + getHeight() / 2;
+ }
+
+ /**
+ * Return the frame around this object. Note that this may be a looser
+ * bounding box than getBounds2D.
+ *
+ * @return the frame, in double precision
+ * @see #setFrame(double, double, double, double)
+ */
+ public Rectangle2D getFrame()
+ {
+ return new Rectangle2D.Double(getX(), getY(), getWidth(), getHeight());
+ }
+
+ /**
+ * Test if the shape is empty, meaning that no points are inside it.
+ *
+ * @return true if the shape is empty
+ */
+ public abstract boolean isEmpty();
+
+ /**
+ * Set the framing rectangle of this shape to the given coordinate and size.
+ *
+ * @param x the new x coordinate
+ * @param y the new y coordinate
+ * @param w the new width
+ * @param h the new height
+ * @see #getFrame()
+ */
+ public abstract void setFrame(double x, double y, double w, double h);
+
+ /**
+ * Set the framing rectangle of this shape to the given coordinate and size.
+ *
+ * @param p the new point
+ * @param d the new dimension
+ * @throws NullPointerException if p or d is null
+ * @see #getFrame()
+ */
+ public void setFrame(Point2D p, Dimension2D d)
+ {
+ setFrame(p.getX(), p.getY(), d.getWidth(), d.getHeight());
+ }
+
+ /**
+ * Set the framing rectangle of this shape to the given rectangle.
+ *
+ * @param r the new framing rectangle
+ * @throws NullPointerException if r is null
+ * @see #getFrame()
+ */
+ public void setFrame(Rectangle2D r)
+ {
+ setFrame(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Set the framing rectangle of this shape using two points on a diagonal.
+ * The area will be positive.
+ *
+ * @param x1 the first x coordinate
+ * @param y1 the first y coordinate
+ * @param x2 the second x coordinate
+ * @param y2 the second y coordinate
+ */
+ public void setFrameFromDiagonal(double x1, double y1, double x2, double y2)
+ {
+ if (x1 > x2)
+ {
+ double t = x2;
+ x2 = x1;
+ x1 = t;
+ }
+ if (y1 > y2)
+ {
+ double t = y2;
+ y2 = y1;
+ y1 = t;
+ }
+ setFrame(x1, y1, x2 - x1, y2 - y1);
+ }
+
+ /**
+ * Set the framing rectangle of this shape using two points on a diagonal.
+ * The area will be positive.
+ *
+ * @param p1 the first point
+ * @param p2 the second point
+ * @throws NullPointerException if either point is null
+ */
+ public void setFrameFromDiagonal(Point2D p1, Point2D p2)
+ {
+ setFrameFromDiagonal(p1.getX(), p1.getY(), p2.getX(), p2.getY());
+ }
+
+ /**
+ * Set the framing rectangle of this shape using the center of the frame,
+ * and one of the four corners. The area will be positive.
+ *
+ * @param centerX the x coordinate at the center
+ * @param centerY the y coordinate at the center
+ * @param cornerX the x coordinate at a corner
+ * @param cornerY the y coordinate at a corner
+ */
+ public void setFrameFromCenter(double centerX, double centerY,
+ double cornerX, double cornerY)
+ {
+ double halfw = Math.abs(cornerX - centerX);
+ double halfh = Math.abs(cornerY - centerY);
+ setFrame(centerX - halfw, centerY - halfh, halfw + halfw, halfh + halfh);
+ }
+
+ /**
+ * Set the framing rectangle of this shape using the center of the frame,
+ * and one of the four corners. The area will be positive.
+ *
+ * @param center the center point
+ * @param corner a corner point
+ * @throws NullPointerException if either point is null
+ */
+ public void setFrameFromCenter(Point2D center, Point2D corner)
+ {
+ setFrameFromCenter(center.getX(), center.getY(),
+ corner.getX(), corner.getY());
+ }
+
+ /**
+ * Tests if a point is inside the boundary of the shape.
+ *
+ * @param p the point to test
+ * @return true if the point is inside the shape
+ * @throws NullPointerException if p is null
+ * @see #contains(double, double)
+ */
+ public boolean contains(Point2D p)
+ {
+ return contains(p.getX(), p.getY());
+ }
+
+ /**
+ * Tests if a rectangle and this shape share common internal points.
+ *
+ * @param r the rectangle to test
+ * @return true if the rectangle intersects this shpae
+ * @throws NullPointerException if r is null
+ * @see #intersects(double, double, double, double)
+ */
+ public boolean intersects(Rectangle2D r)
+ {
+ return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Tests if the shape completely contains the given rectangle.
+ *
+ * @param r the rectangle to test
+ * @return true if r is contained in this shape
+ * @throws NullPointerException if r is null
+ * @see #contains(double, double, double, double)
+ */
+ public boolean contains(Rectangle2D r)
+ {
+ return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Returns a bounding box for this shape, in integer format. Notice that you
+ * may get a tighter bound with getBounds2D.
+ *
+ * @return a bounding box
+ */
+ public Rectangle getBounds()
+ {
+ double x = getX();
+ double y = getY();
+ double maxx = Math.ceil(x + getWidth());
+ double maxy = Math.ceil(y + getHeight());
+ x = Math.floor(x);
+ y = Math.floor(y);
+ return new Rectangle((int) x, (int) y, (int) (maxx - x), (int) (maxy - y));
+ }
+
+ /**
+ * Return an iterator along the shape boundary. If the optional transform
+ * is provided, the iterator is transformed accordingly. The path is
+ * flattened until all segments differ from the curve by at most the value
+ * of the flatness parameter, within the limits of the default interpolation
+ * recursion limit of 1024 segments between actual points. Each call
+ * returns a new object, independent from others in use. The result is
+ * threadsafe if and only if the iterator returned by
+ * {@link #getPathIterator(AffineTransform)} is as well.
+ *
+ * @param at an optional transform to apply to the iterator
+ * @param flatness the desired flatness
+ * @return a new iterator over the boundary
+ * @throws IllegalArgumentException if flatness is invalid
+ * @since 1.2
+ */
+ public PathIterator getPathIterator(AffineTransform at, double flatness)
+ {
+ return new FlatteningPathIterator(getPathIterator(at), flatness);
+ }
+
+ /**
+ * Create a new shape of the same run-time type with the same contents as
+ * this one.
+ *
+ * @return the clone
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // Impossible
+ }
+ }
+} // class RectangularShape
diff --git a/libjava/classpath/java/awt/geom/RoundRectangle2D.java b/libjava/classpath/java/awt/geom/RoundRectangle2D.java
new file mode 100644
index 000000000..19a7b4237
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/RoundRectangle2D.java
@@ -0,0 +1,584 @@
+/* RoundRectangle2D.java -- represents a rectangle with rounded corners
+ Copyright (C) 2000, 2002, 2003, 2004, 2006, Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.geom;
+
+
+
+/** This class implements a rectangle with rounded corners.
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @date December 3, 2000
+ */
+public abstract class RoundRectangle2D extends RectangularShape
+{
+ /**
+ * Return the arc height of this round rectangle. The arc height and width
+ * control the roundness of the corners of the rectangle.
+ *
+ * @return The arc height.
+ *
+ * @see #getArcWidth()
+ */
+ public abstract double getArcHeight();
+
+ /**
+ * Return the arc width of this round rectangle. The arc width and height
+ * control the roundness of the corners of the rectangle.
+ *
+ * @return The arc width.
+ *
+ * @see #getArcHeight()
+ */
+ public abstract double getArcWidth();
+
+ /**
+ * Set the values of this round rectangle.
+ *
+ * @param x The x coordinate
+ * @param y The y coordinate
+ * @param w The width
+ * @param h The height
+ * @param arcWidth The arc width
+ * @param arcHeight The arc height
+ */
+ public abstract void setRoundRect(double x, double y, double w, double h,
+ double arcWidth, double arcHeight);
+
+ /**
+ * Create a RoundRectangle2D. This is protected because this class
+ * is abstract and cannot be instantiated.
+ */
+ protected RoundRectangle2D()
+ {
+ }
+
+ /**
+ * Return true if this object contains the specified point.
+ * @param x The x coordinate
+ * @param y The y coordinate
+ */
+ public boolean contains(double x, double y)
+ {
+ double mx = getX();
+ double mw = getWidth();
+ if (x < mx || x >= mx + mw)
+ return false;
+ double my = getY();
+ double mh = getHeight();
+ if (y < my || y >= my + mh)
+ return false;
+
+ // Now check to see if the point is in range of an arc.
+ double dy = Math.min(Math.abs(my - y), Math.abs(my + mh - y));
+ double dx = Math.min(Math.abs(mx - x), Math.abs(mx + mw - x));
+
+ // The arc dimensions are that of the corresponding ellipse
+ // thus a 90 degree segment is half of that.
+ double aw = getArcWidth() / 2.0;
+ double ah = getArcHeight() / 2.0;
+ if (dx > aw || dy > ah)
+ return true;
+
+ // At this point DX represents the distance from the nearest edge
+ // of the rectangle. But we want to transform it to represent the
+ // scaled distance from the center of the ellipse that forms the
+ // arc. Hence this code:
+ dy = (ah - dy) / ah;
+ dx = (aw - dx) / aw;
+
+ return dx * dx + dy * dy <= 1.0;
+ }
+
+ /**
+ * Return true if this object contains the specified rectangle
+ * @param x The x coordinate
+ * @param y The y coordinate
+ * @param w The width
+ * @param h The height
+ */
+ public boolean contains(double x, double y, double w, double h)
+ {
+ // We have to check all four points here (for ordinary rectangles
+ // we can just check opposing corners).
+ return (contains(x, y) && contains(x, y + h) && contains(x + w, y + h)
+ && contains(x + w, y));
+ }
+
+ /**
+ * Return a new path iterator which iterates over this rectangle.
+ *
+ * @param at An affine transform to apply to the object
+ */
+ public PathIterator getPathIterator(final AffineTransform at)
+ {
+ double arcW = Math.min(getArcWidth(), getWidth());
+ double arcH = Math.min(getArcHeight(), getHeight());
+
+ // check for special cases...
+ if (arcW <= 0 || arcH <= 0)
+ {
+ Rectangle2D r = new Rectangle2D.Double(getX(), getY(), getWidth(),
+ getHeight());
+ return r.getPathIterator(at);
+ }
+ else if (arcW >= getWidth() && arcH >= getHeight())
+ {
+ Ellipse2D e = new Ellipse2D.Double(getX(), getY(), getWidth(),
+ getHeight());
+ return e.getPathIterator(at);
+ }
+
+ // otherwise return the standard case...
+ return new PathIterator()
+ {
+ double x = getX();
+ double y = getY();
+ double w = getWidth();
+ double h = getHeight();
+ double arcW = Math.min(getArcWidth(), w);
+ double arcH = Math.min(getArcHeight(), h);
+ Arc2D.Double arc = new Arc2D.Double();
+ PathIterator corner;
+ int step = -1;
+
+ public int currentSegment(double[] coords)
+ {
+ if (corner != null) // steps 1, 3, 5 and 7
+ {
+ int r = corner.currentSegment(coords);
+ if (r == SEG_MOVETO)
+ r = SEG_LINETO;
+ return r;
+ }
+ if (step == -1)
+ {
+ // move to the start position
+ coords[0] = x + w - arcW / 2;
+ coords[1] = y;
+ }
+ else if (step == 0)
+ {
+ // top line
+ coords[0] = x + arcW / 2;
+ coords[1] = y;
+ }
+ else if (step == 2)
+ {
+ // left line
+ coords[0] = x;
+ coords[1] = y + h - arcH / 2;
+ }
+ else if (step == 4)
+ {
+ // bottom line
+ coords[0] = x + w - arcW / 2;
+ coords[1] = y + h;
+ }
+ else if (step == 6)
+ {
+ // right line
+ coords[0] = x + w;
+ coords[1] = y + arcH / 2;
+ }
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 1);
+ return step == -1 ? SEG_MOVETO : SEG_LINETO;
+ }
+
+ public int currentSegment(float[] coords) {
+ if (corner != null) // steps 1, 3, 5 and 7
+ {
+ int r = corner.currentSegment(coords);
+ if (r == SEG_MOVETO)
+ r = SEG_LINETO;
+ return r;
+ }
+ if (step == -1)
+ {
+ // move to the start position
+ coords[0] = (float) (x + w - arcW / 2);
+ coords[1] = (float) y;
+ }
+ else if (step == 0)
+ {
+ // top line
+ coords[0] = (float) (x + arcW / 2);
+ coords[1] = (float) y;
+ }
+ else if (step == 2)
+ {
+ // left line
+ coords[0] = (float) x;
+ coords[1] = (float) (y + h - arcH / 2);
+ }
+ else if (step == 4)
+ {
+ // bottom line
+ coords[0] = (float) (x + w - arcW / 2);
+ coords[1] = (float) (y + h);
+ }
+ else if (step == 6)
+ {
+ // right line
+ coords[0] = (float) (x + w);
+ coords[1] = (float) (y + arcH / 2);
+ }
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 1);
+ return step == -1 ? SEG_MOVETO : SEG_LINETO;
+ }
+
+ public int getWindingRule() {
+ return WIND_NON_ZERO;
+ }
+
+ public boolean isDone() {
+ return step >= 8;
+ }
+
+ public void next()
+ {
+ if (corner != null)
+ {
+ corner.next();
+ if (corner.isDone())
+ {
+ corner = null;
+ step++;
+ }
+ }
+ else
+ {
+ step++;
+ if (step == 1)
+ {
+ // create top left corner
+ arc.setArc(x, y, arcW, arcH, 90, 90, Arc2D.OPEN);
+ corner = arc.getPathIterator(at);
+ }
+ else if (step == 3)
+ {
+ // create bottom left corner
+ arc.setArc(x, y + h - arcH, arcW, arcH, 180, 90,
+ Arc2D.OPEN);
+ corner = arc.getPathIterator(at);
+ }
+ else if (step == 5)
+ {
+ // create bottom right corner
+ arc.setArc(x + w - arcW, y + h - arcH, arcW, arcH, 270, 90,
+ Arc2D.OPEN);
+ corner = arc.getPathIterator(at);
+ }
+ else if (step == 7)
+ {
+ // create top right corner
+ arc.setArc(x + w - arcW, y, arcW, arcH, 0, 90, Arc2D.OPEN);
+ corner = arc.getPathIterator(at);
+ }
+ }
+ }
+ };
+ }
+
+ /**
+ * Return true if the given rectangle intersects this shape.
+ * @param x The x coordinate
+ * @param y The y coordinate
+ * @param w The width
+ * @param h The height
+ */
+ public boolean intersects(double x, double y, double w, double h)
+ {
+ // Check if any corner is within the rectangle
+ return (contains(x, y) || contains(x, y + h) || contains(x + w, y + h)
+ || contains(x + w, y));
+ }
+
+ /**
+ * Set the boundary of this round rectangle.
+ * @param x The x coordinate
+ * @param y The y coordinate
+ * @param w The width
+ * @param h The height
+ */
+ public void setFrame(double x, double y, double w, double h)
+ {
+ // This is a bit lame.
+ setRoundRect(x, y, w, h, getArcWidth(), getArcHeight());
+ }
+
+ /**
+ * Set the values of this round rectangle to be the same as those
+ * of the argument.
+ * @param rr The round rectangle to copy
+ */
+ public void setRoundRect(RoundRectangle2D rr)
+ {
+ setRoundRect(rr.getX(), rr.getY(), rr.getWidth(), rr.getHeight(),
+ rr.getArcWidth(), rr.getArcHeight());
+ }
+
+ /**
+ * A subclass of RoundRectangle which keeps its parameters as
+ * doubles.
+ */
+ public static class Double extends RoundRectangle2D
+ {
+ /** The height of the corner arc. */
+ public double archeight;
+
+ /** The width of the corner arc. */
+ public double arcwidth;
+
+ /** The x coordinate of this object. */
+ public double x;
+
+ /** The y coordinate of this object. */
+ public double y;
+
+ /** The width of this object. */
+ public double width;
+
+ /** The height of this object. */
+ public double height;
+
+ /**
+ * Construct a new instance, with all parameters set to 0.
+ */
+ public Double()
+ {
+ }
+
+ /**
+ * Construct a new instance with the given arguments.
+ * @param x The x coordinate
+ * @param y The y coordinate
+ * @param w The width
+ * @param h The height
+ * @param arcWidth The arc width
+ * @param arcHeight The arc height
+ */
+ public Double(double x, double y, double w, double h, double arcWidth,
+ double arcHeight)
+ {
+ this.x = x;
+ this.y = y;
+ this.width = w;
+ this.height = h;
+ this.arcwidth = arcWidth;
+ this.archeight = arcHeight;
+ }
+
+ public double getArcHeight()
+ {
+ return archeight;
+ }
+
+ public double getArcWidth()
+ {
+ return arcwidth;
+ }
+
+ public Rectangle2D getBounds2D()
+ {
+ return new Rectangle2D.Double(x, y, width, height);
+ }
+
+ public double getX()
+ {
+ return x;
+ }
+
+ public double getY()
+ {
+ return y;
+ }
+
+ public double getWidth()
+ {
+ return width;
+ }
+
+ public double getHeight()
+ {
+ return height;
+ }
+
+ public boolean isEmpty()
+ {
+ return width <= 0 || height <= 0;
+ }
+
+ public void setRoundRect(double x, double y, double w, double h,
+ double arcWidth, double arcHeight)
+ {
+ this.x = x;
+ this.y = y;
+ this.width = w;
+ this.height = h;
+ this.arcwidth = arcWidth;
+ this.archeight = arcHeight;
+ }
+ } // class Double
+
+ /**
+ * A subclass of RoundRectangle which keeps its parameters as
+ * floats.
+ */
+ public static class Float extends RoundRectangle2D
+ {
+ /** The height of the corner arc. */
+ public float archeight;
+
+ /** The width of the corner arc. */
+ public float arcwidth;
+
+ /** The x coordinate of this object. */
+ public float x;
+
+ /** The y coordinate of this object. */
+ public float y;
+
+ /** The width of this object. */
+ public float width;
+
+ /** The height of this object. */
+ public float height;
+
+ /**
+ * Construct a new instance, with all parameters set to 0.
+ */
+ public Float()
+ {
+ }
+
+ /**
+ * Construct a new instance with the given arguments.
+ * @param x The x coordinate
+ * @param y The y coordinate
+ * @param w The width
+ * @param h The height
+ * @param arcWidth The arc width
+ * @param arcHeight The arc height
+ */
+ public Float(float x, float y, float w, float h, float arcWidth,
+ float arcHeight)
+ {
+ this.x = x;
+ this.y = y;
+ this.width = w;
+ this.height = h;
+ this.arcwidth = arcWidth;
+ this.archeight = arcHeight;
+ }
+
+ public double getArcHeight()
+ {
+ return archeight;
+ }
+
+ public double getArcWidth()
+ {
+ return arcwidth;
+ }
+
+ public Rectangle2D getBounds2D()
+ {
+ return new Rectangle2D.Float(x, y, width, height);
+ }
+
+ public double getX()
+ {
+ return x;
+ }
+
+ public double getY()
+ {
+ return y;
+ }
+
+ public double getWidth()
+ {
+ return width;
+ }
+
+ public double getHeight()
+ {
+ return height;
+ }
+
+ public boolean isEmpty()
+ {
+ return width <= 0 || height <= 0;
+ }
+
+ /**
+ * Sets the dimensions for this rounded rectangle.
+ *
+ * @param x the x-coordinate of the top left corner.
+ * @param y the y-coordinate of the top left corner.
+ * @param w the width of the rectangle.
+ * @param h the height of the rectangle.
+ * @param arcWidth the arc width.
+ * @param arcHeight the arc height.
+ *
+ * @see #setRoundRect(double, double, double, double, double, double)
+ */
+ public void setRoundRect(float x, float y, float w, float h,
+ float arcWidth, float arcHeight)
+ {
+ this.x = x;
+ this.y = y;
+ this.width = w;
+ this.height = h;
+ this.arcwidth = arcWidth;
+ this.archeight = arcHeight;
+ }
+
+ public void setRoundRect(double x, double y, double w, double h,
+ double arcWidth, double arcHeight)
+ {
+ this.x = (float) x;
+ this.y = (float) y;
+ this.width = (float) w;
+ this.height = (float) h;
+ this.arcwidth = (float) arcWidth;
+ this.archeight = (float) arcHeight;
+ }
+ } // class Float
+} // class RoundRectangle2D
diff --git a/libjava/classpath/java/awt/geom/doc-files/Area-1.png b/libjava/classpath/java/awt/geom/doc-files/Area-1.png
new file mode 100644
index 000000000..44650f2d8
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/Area-1.png
Binary files differ
diff --git a/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-1.png b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-1.png
new file mode 100644
index 000000000..1784509be
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-1.png
Binary files differ
diff --git a/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-2.png b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-2.png
new file mode 100644
index 000000000..1ddae9fc8
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-2.png
Binary files differ
diff --git a/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-3.png b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-3.png
new file mode 100644
index 000000000..b200dad37
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-3.png
Binary files differ
diff --git a/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-4.png b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-4.png
new file mode 100644
index 000000000..e57ffdc5c
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-4.png
Binary files differ
diff --git a/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-5.png b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-5.png
new file mode 100644
index 000000000..701ab138f
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-5.png
Binary files differ
diff --git a/libjava/classpath/java/awt/geom/doc-files/Ellipse-1.png b/libjava/classpath/java/awt/geom/doc-files/Ellipse-1.png
new file mode 100644
index 000000000..8317db661
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/Ellipse-1.png
Binary files differ
diff --git a/libjava/classpath/java/awt/geom/doc-files/FlatteningPathIterator-1.html b/libjava/classpath/java/awt/geom/doc-files/FlatteningPathIterator-1.html
new file mode 100644
index 000000000..5a52d693e
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/FlatteningPathIterator-1.html
@@ -0,0 +1,481 @@
+<?xml version="1.0" encoding="US-ASCII"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>The GNU Implementation of java.awt.geom.FlatteningPathIterator</title>
+ <meta name="author" content="Sascha Brawer" />
+ <style type="text/css"><!--
+ td { white-space: nowrap; }
+ li { margin: 2mm 0; }
+ --></style>
+</head>
+<body>
+
+<h1>The GNU Implementation of FlatteningPathIterator</h1>
+
+<p><i><a href="http://www.dandelis.ch/people/brawer/">Sascha
+Brawer</a>, November 2003</i></p>
+
+<p>This document describes the GNU implementation of the class
+<code>java.awt.geom.FlatteningPathIterator</code>. It does
+<em>not</em> describe how a programmer should use this class; please
+refer to the generated API documentation for this purpose. Instead, it
+is intended for maintenance programmers who want to understand the
+implementation, for example because they want to extend the class or
+fix a bug.</p>
+
+
+<h2>Data Structures</h2>
+
+<p>The algorithm uses a stack. Its allocation is delayed to the time
+when the source path iterator actually returns the first curved
+segment (either <code>SEG_QUADTO</code> or <code>SEG_CUBICTO</code>).
+If the input path does not contain any curved segments, the value of
+the <code>stack</code> variable stays <code>null</code>. In this quite
+common case, the memory consumption is minimal.</p>
+
+<dl><dt><code>stack</code></dt><dd>The variable <code>stack</code> is
+a <code>double</code> array that holds the start, control and end
+points of individual sub-segments.</dd>
+
+<dt><code>recLevel</code></dt><dd>The variable <code>recLevel</code>
+holds how many recursive sub-divisions were needed to calculate a
+segment. The original curve has recursion level 0. For each
+sub-division, the corresponding recursion level is increased by
+one.</dd>
+
+<dt><code>stackSize</code></dt><dd>Finally, the variable
+<code>stackSize</code> indicates how many sub-segments are stored on
+the stack.</dd></dl>
+
+<h2>Algorithm</h2>
+
+<p>The implementation separately processes each segment that the
+base iterator returns.</p>
+
+<p>In the case of <code>SEG_CLOSE</code>,
+<code>SEG_MOVETO</code> and <code>SEG_LINETO</code> segments, the
+implementation simply hands the segment to the consumer, without actually
+doing anything.</p>
+
+<p>Any <code>SEG_QUADTO</code> and <code>SEG_CUBICTO</code> segments
+need to be flattened. Flattening is performed with a fixed-sized
+stack, holding the coordinates of subdivided segments. When the base
+iterator returns a <code>SEG_QUADTO</code> and
+<code>SEG_CUBICTO</code> segments, it is recursively flattened as
+follows:</p>
+
+<ol><li>Intialization: Allocate memory for the stack (unless a
+sufficiently large stack has been allocated previously). Push the
+original quadratic or cubic curve onto the stack. Mark that segment as
+having a <code>recLevel</code> of zero.</li>
+
+<li>If the stack is empty, flattening the segment is complete,
+and the next segment is fetched from the base iterator.</li>
+
+<li>If the stack is not empty, pop a curve segment from the
+stack.
+
+ <ul><li>If its <code>recLevel</code> exceeds the recursion limit,
+ hand the current segment to the consumer.</li>
+
+ <li>Calculate the squared flatness of the segment. If it smaller
+ than <code>flatnessSq</code>, hand the current segment to the
+ consumer.</li>
+
+ <li>Otherwise, split the segment in two halves. Push the right
+ half onto the stack. Then, push the left half onto the stack.
+ Continue with step two.</li></ul></li>
+</ol>
+
+<p>The implementation is slightly complicated by the fact that
+consumers <em>pull</em> the flattened segments from the
+<code>FlatteningPathIterator</code>. This means that we actually
+cannot &#x201c;hand the curent segment over to the consumer.&#x201d;
+But the algorithm is easier to understand if one assumes a
+<em>push</em> paradigm.</p>
+
+
+<h2>Example</h2>
+
+<p>The following example shows how a
+<code>FlatteningPathIterator</code> processes a
+<code>SEG_QUADTO</code> segment. It is (arbitrarily) assumed that the
+recursion limit was set to 2.</p>
+
+<blockquote>
+<table border="1" cellspacing="0" cellpadding="8">
+ <tr align="center" valign="baseline">
+ <th></th><th>A</th><th>B</th><th>C</th>
+ <th>D</th><th>E</th><th>F</th><th>G</th><th>H</th>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[0]</code></th>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td><i>S<sub>ll</sub>.x</i></td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[1]</code></th>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td><i>S<sub>ll</sub>.y</i></td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[2]</code></th>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td><i>C<sub>ll</sub>.x</i></td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[3]</code></th>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td><i>C<sub>ll</sub>.y</i></td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[4]</code></th>
+ <td>&#x2014;</td>
+ <td><i>S<sub>l</sub>.x</i></td>
+ <td><i>E<sub>ll</sub>.x</i>
+ = <i>S<sub>lr</sub>.x</i></td>
+ <td><i>S<sub>lr</sub>.x</i></td>
+ <td>&#x2014;</td>
+ <td><i>S<sub>rl</sub>.x</i></td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[5]</code></th>
+ <td>&#x2014;</td>
+ <td><i>S<sub>l</sub>.y</i></td>
+ <td><i>E<sub>ll</sub>.x</i>
+ = <i>S<sub>lr</sub>.y</i></td>
+ <td><i>S<sub>lr</sub>.y</i></td>
+ <td>&#x2014;</td>
+ <td><i>S<sub>rl</sub>.y</i></td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[6]</code></th>
+ <td>&#x2014;</td>
+ <td><i>C<sub>l</sub>.x</i></td>
+ <td><i>C<sub>lr</sub>.x</i></td>
+ <td><i>C<sub>lr</sub>.x</i></td>
+ <td>&#x2014;</td>
+ <td><i>C<sub>rl</sub>.x</i></td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[7]</code></th>
+ <td>&#x2014;</td>
+ <td><i>C<sub>l</sub>.y</i></td>
+ <td><i>C<sub>lr</sub>.y</i></td>
+ <td><i>C<sub>lr</sub>.y</i></td>
+ <td>&#x2014;</td>
+ <td><i>C<sub>rl</sub>.y</i></td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[8]</code></th>
+ <td><i>S.x</i></td>
+ <td><i>E<sub>l</sub>.x</i>
+ = <i>S<sub>r</sub>.x</i></td>
+ <td><i>E<sub>lr</sub>.x</i>
+ = <i>S<sub>r</sub>.x</i></td>
+ <td><i>E<sub>lr</sub>.x</i>
+ = <i>S<sub>r</sub>.x</i></td>
+ <td><i>S<sub>r</sub>.x</i></td>
+ <td><i>E<sub>rl</sub>.x</i>
+ = <i>S<sub>rr</sub>.x</i></td>
+ <td><i>S<sub>rr</sub>.x</i></td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[9]</code></th>
+ <td><i>S.y</i></td>
+ <td><i>E<sub>l</sub>.y</i>
+ = <i>S<sub>r</sub>.y</i></td>
+ <td><i>E<sub>lr</sub>.y</i>
+ = <i>S<sub>r</sub>.y</i></td>
+ <td><i>E<sub>lr</sub>.y</i>
+ = <i>S<sub>r</sub>.y</i></td>
+ <td><i>S<sub>r</sub>.y</i></td>
+ <td><i>E<sub>rl</sub>.y</i>
+ = <i>S<sub>rr</sub>.y</i></td>
+ <td><i>S<sub>rr</sub>.y</i></td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[10]</code></th>
+ <td><i>C.x</i></td>
+ <td><i>C<sub>r</sub>.x</i></td>
+ <td><i>C<sub>r</sub>.x</i></td>
+ <td><i>C<sub>r</sub>.x</i></td>
+ <td><i>C<sub>r</sub>.x</i></td>
+ <td><i>C<sub>rr</sub>.x</i></td>
+ <td><i>C<sub>rr</sub>.x</i></td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[11]</code></th>
+ <td><i>C.y</i></td>
+ <td><i>C<sub>r</sub>.y</i></td>
+ <td><i>C<sub>r</sub>.y</i></td>
+ <td><i>C<sub>r</sub>.y</i></td>
+ <td><i>C<sub>r</sub>.y</i></td>
+ <td><i>C<sub>rr</sub>.y</i></td>
+ <td><i>C<sub>rr</sub>.y</i></td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[12]</code></th>
+ <td><i>E.x</i></td>
+ <td><i>E<sub>r</sub>.x</i></td>
+ <td><i>E<sub>r</sub>.x</i></td>
+ <td><i>E<sub>r</sub>.x</i></td>
+ <td><i>E<sub>r</sub>.x</i></td>
+ <td><i>E<sub>rr</sub>.x</i></td>
+ <td><i>E<sub>rr</sub>.x</i></td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stack[13]</code></th>
+ <td><i>E.y</i></td>
+ <td><i>E<sub>r</sub>.y</i></td>
+ <td><i>E<sub>r</sub>.y</i></td>
+ <td><i>E<sub>r</sub>.y</i></td>
+ <td><i>E<sub>r</sub>.y</i></td>
+ <td><i>E<sub>rr</sub>.y</i></td>
+ <td><i>E<sub>rr</sub>.x</i></td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>stackSize</code></th>
+ <td>1</td>
+ <td>2</td>
+ <td>3</td>
+ <td>2</td>
+ <td>1</td>
+ <td>2</td>
+ <td>1</td>
+ <td>0</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>recLevel[2]</code></th>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>2</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>recLevel[1]</code></th>
+ <td>&#x2014;</td>
+ <td>1</td>
+ <td>2</td>
+ <td>2</td>
+ <td>&#x2014;</td>
+ <td>2</td>
+ <td>&#x2014;</td>
+ <td>&#x2014;</td>
+ </tr>
+ <tr align="center" valign="baseline">
+ <th><code>recLevel[0]</code></th>
+ <td>0</td>
+ <td>1</td>
+ <td>1</td>
+ <td>1</td>
+ <td>1</td>
+ <td>2</td>
+ <td>2</td>
+ <td>&#x2014;</td>
+ </tr>
+ </table>
+</blockquote>
+
+<ol>
+
+<li>The data structures are initialized as follows.
+
+<ul><li>The segment&#x2019;s end point <i>E</i>, control point
+<i>C</i>, and start point <i>S</i> are pushed onto the stack.</li>
+
+ <li>Currently, the curve in the stack would be approximated by one
+ single straight line segment (<i>S</i> &#x2013; <i>E</i>).
+ Therefore, <code>stackSize</code> is set to 1.</li>
+
+ <li>This single straight line segment is approximating the original
+ curve, which can be seen as the result of zero recursive
+ splits. Therefore, <code>recLevel[0]</code> is set to
+ zero.</li></ul>
+
+Column A shows the state after the initialization step.</li>
+
+<li>The algorithm proceeds by taking the topmost curve segment
+(<i>S</i> &#x2013; <i>C</i> &#x2013; <i>E</i>) from the stack.
+
+ <ul><li>The recursion level of this segment (stored in
+ <code>recLevel[0]</code>) is zero, which is smaller than
+ the limit 2.</li>
+
+ <li>The method <code>java.awt.geom.QuadCurve2D.getFlatnessSq</code>
+ is called to calculate the squared flatness.</li>
+
+ <li>For the sake of argument, we assume that the squared flatness is
+ exceeding the threshold stored in <code>flatnessSq</code>. Thus, the
+ curve segment <i>S</i> &#x2013; <i>C</i> &#x2013; <i>E</i> gets
+ subdivided into a left and a right half, namely
+ <i>S<sub>l</sub></i> &#x2013; <i>C<sub>l</sub></i> &#x2013;
+ <i>E<sub>l</sub></i> and <i>S<sub>r</sub></i> &#x2013;
+ <i>C<sub>r</sub></i> &#x2013; <i>E<sub>r</sub></i>. Both halves are
+ pushed onto the stack, so the left half is now on top.
+
+ <br />&nbsp;<br />The left half starts at the same point
+ as the original curve, so <i>S<sub>l</sub></i> has the same
+ coordinates as <i>S</i>. Similarly, the end point of the right
+ half and of the original curve are identical
+ (<i>E<sub>r</sub></i> = <i>E</i>). More interestingly, the left
+ half ends where the right half starts. Because
+ <i>E<sub>l</sub></i> = <i>S<sub>r</sub></i>, their coordinates need
+ to be stored only once, which amounts to saving 16 bytes (two
+ <code>double</code> values) for each iteration.</li></ul>
+
+Column B shows the state after the first iteration.</li>
+
+<li>Again, the topmost curve segment (<i>S<sub>l</sub></i>
+&#x2013; <i>C<sub>l</sub></i> &#x2013; <i>E<sub>l</sub></i>) is
+taken from the stack.
+
+ <ul><li>The recursion level of this segment (stored in
+ <code>recLevel[1]</code>) is 1, which is smaller than
+ the limit 2.</li>
+
+ <li>The method <code>java.awt.geom.QuadCurve2D.getFlatnessSq</code>
+ is called to calculate the squared flatness.</li>
+
+ <li>Assuming that the segment is still not considered
+ flat enough, it gets subdivided into a left
+ (<i>S<sub>ll</sub></i> &#x2013; <i>C<sub>ll</sub></i> &#x2013;
+ <i>E<sub>ll</sub></i>) and a right (<i>S<sub>lr</sub></i>
+ &#x2013; <i>C<sub>lr</sub></i> &#x2013; <i>E<sub>lr</sub></i>)
+ half.</li></ul>
+
+Column C shows the state after the second iteration.</li>
+
+<li>The topmost curve segment (<i>S<sub>ll</sub></i> &#x2013;
+<i>C<sub>ll</sub></i> &#x2013; <i>E<sub>ll</sub></i>) is popped from
+the stack.
+
+ <ul><li>The recursion level of this segment (stored in
+ <code>recLevel[2]</code>) is 2, which is <em>not</em> smaller than
+ the limit 2. Therefore, a <code>SEG_LINETO</code> (from
+ <i>S<sub>ll</sub></i> to <i>E<sub>ll</sub></i>) is passed to the
+ consumer.</li></ul>
+
+ The new state is shown in column D.</li>
+
+
+<li>The topmost curve segment (<i>S<sub>lr</sub></i> &#x2013;
+<i>C<sub>lr</sub></i> &#x2013; <i>E<sub>lr</sub></i>) is popped from
+the stack.
+
+ <ul><li>The recursion level of this segment (stored in
+ <code>recLevel[1]</code>) is 2, which is <em>not</em> smaller than
+ the limit 2. Therefore, a <code>SEG_LINETO</code> (from
+ <i>S<sub>lr</sub></i> to <i>E<sub>lr</sub></i>) is passed to the
+ consumer.</li></ul>
+
+ The new state is shown in column E.</li>
+
+<li>The algorithm proceeds by taking the topmost curve segment
+(<i>S<sub>r</sub></i> &#x2013; <i>C<sub>r</sub></i> &#x2013;
+<i>E<sub>r</sub></i>) from the stack.
+
+ <ul><li>The recursion level of this segment (stored in
+ <code>recLevel[0]</code>) is 1, which is smaller than
+ the limit 2.</li>
+
+ <li>The method <code>java.awt.geom.QuadCurve2D.getFlatnessSq</code>
+ is called to calculate the squared flatness.</li>
+
+ <li>For the sake of argument, we again assume that the squared
+ flatness is exceeding the threshold stored in
+ <code>flatnessSq</code>. Thus, the curve segment
+ (<i>S<sub>r</sub></i> &#x2013; <i>C<sub>r</sub></i> &#x2013;
+ <i>E<sub>r</sub></i>) is subdivided into a left and a right half,
+ namely
+ <i>S<sub>rl</sub></i> &#x2013; <i>C<sub>rl</sub></i> &#x2013;
+ <i>E<sub>rl</sub></i> and <i>S<sub>rr</sub></i> &#x2013;
+ <i>C<sub>rr</sub></i> &#x2013; <i>E<sub>rr</sub></i>. Both halves
+ are pushed onto the stack.</li></ul>
+
+ The new state is shown in column F.</li>
+
+<li>The topmost curve segment (<i>S<sub>rl</sub></i> &#x2013;
+<i>C<sub>rl</sub></i> &#x2013; <i>E<sub>rl</sub></i>) is popped from
+the stack.
+
+ <ul><li>The recursion level of this segment (stored in
+ <code>recLevel[2]</code>) is 2, which is <em>not</em> smaller than
+ the limit 2. Therefore, a <code>SEG_LINETO</code> (from
+ <i>S<sub>rl</sub></i> to <i>E<sub>rl</sub></i>) is passed to the
+ consumer.</li></ul>
+
+ The new state is shown in column G.</li>
+
+<li>The topmost curve segment (<i>S<sub>rr</sub></i> &#x2013;
+<i>C<sub>rr</sub></i> &#x2013; <i>E<sub>rr</sub></i>) is popped from
+the stack.
+
+ <ul><li>The recursion level of this segment (stored in
+ <code>recLevel[2]</code>) is 2, which is <em>not</em> smaller than
+ the limit 2. Therefore, a <code>SEG_LINETO</code> (from
+ <i>S<sub>rr</sub></i> to <i>E<sub>rr</sub></i>) is passed to the
+ consumer.</li></ul>
+
+ The new state is shown in column H.</li>
+
+<li>The stack is now empty. The FlatteningPathIterator will fetch the
+next segment from the base iterator, and process it.</li>
+
+</ol>
+
+<p>In order to split the most recently pushed segment, the
+<code>subdivideQuadratic()</code> method passes <code>stack</code>
+directly to
+<code>QuadCurve2D.subdivide(double[],int,double[],int,double[],int)</code>.
+Because the stack grows towards the beginning of the array, no data
+needs to be copied around: <code>subdivide</code> will directly store
+the result into the stack, which will have the contents shown to the
+right.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/geom/doc-files/GeneralPath-1.png b/libjava/classpath/java/awt/geom/doc-files/GeneralPath-1.png
new file mode 100644
index 000000000..d1d75d575
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/GeneralPath-1.png
Binary files differ
diff --git a/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-1.png b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-1.png
new file mode 100644
index 000000000..7c2ec0ea9
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-1.png
Binary files differ
diff --git a/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-2.png b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-2.png
new file mode 100644
index 000000000..496180c44
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-2.png
Binary files differ
diff --git a/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-3.png b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-3.png
new file mode 100644
index 000000000..a7557ba7b
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-3.png
Binary files differ
diff --git a/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-4.png b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-4.png
new file mode 100644
index 000000000..835c0643b
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-4.png
Binary files differ
diff --git a/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-5.png b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-5.png
new file mode 100644
index 000000000..72110cd5a
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-5.png
Binary files differ
diff --git a/libjava/classpath/java/awt/geom/package.html b/libjava/classpath/java/awt/geom/package.html
new file mode 100644
index 000000000..c8ee8272f
--- /dev/null
+++ b/libjava/classpath/java/awt/geom/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt.geom package.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - java.awt.geom</title></head>
+
+<body>
+<p>Classes to represent 2D objects and different path transformations.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/im/InputContext.java b/libjava/classpath/java/awt/im/InputContext.java
new file mode 100644
index 000000000..8667272b8
--- /dev/null
+++ b/libjava/classpath/java/awt/im/InputContext.java
@@ -0,0 +1,438 @@
+/* InputContext.java -- provides the context for text input
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.im;
+
+import gnu.java.util.EmptyEnumeration;
+
+import java.awt.AWTEvent;
+import java.awt.AWTException;
+import java.awt.Component;
+import java.awt.im.spi.InputMethod;
+import java.awt.im.spi.InputMethodDescriptor;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.text.AttributedCharacterIterator.Attribute;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Locale;
+
+/**
+ * Provides a context for controlling input methods and keyboard layouts.
+ * This class provides the communication layer between the client component,
+ * and the various locale-dependent text entry input methods that can be used
+ * for the client. By default, there is one instance per Window, shared among
+ * all components, but this limits text entry to one component at a time.
+ * Thus, text components can create their own instance to allow text entry
+ * in multiple components at a time.
+ *
+ * <p>By using the interfaces of {@link java.awt.im.spi}, you can install
+ * extensions which allow additional input methods. Some of these may use
+ * platform native input methods, or keyboard layouts provided by the platform.
+ * Input methods are unavailable if none have been installed and the platform
+ * has no underlying native input methods. Extensions are installed as jar
+ * files, usually accessed in the default extension location or specified by
+ * the -extdir VM flag. The jar must contain a file named
+ * "META_INF/services/java.awt.im.spi.InputMethodDescriptor" which lists,
+ * one entry per line in UTF-8 encoding, each class in the jar that implements
+ * java.awt.im.spi.InputMethodDescriptor.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @see Component#getInputContext()
+ * @see Component#enableInputMethods(boolean)
+ * @since 1.2
+ * @status updated to 1.4, but unverified
+ */
+public class InputContext
+{
+ /**
+ * The list of installed input method descriptors.
+ */
+ private static final ArrayList<InputMethodDescriptor> descriptors
+ = new ArrayList<InputMethodDescriptor>();
+
+ static
+ {
+ Enumeration e;
+ try
+ {
+ e = ClassLoader.getSystemResources
+ ("META_INF/services/java.awt.im.spi.InputMethodDescriptor");
+ }
+ catch (IOException ex)
+ {
+ // XXX Should we do something else?
+ e = EmptyEnumeration.getInstance();
+ }
+ while (e.hasMoreElements())
+ {
+ URL url = (URL) e.nextElement();
+ BufferedReader in;
+ String line;
+ try
+ {
+ in = new BufferedReader
+ (new InputStreamReader(url.openConnection().getInputStream(),
+ "UTF-8"));
+ line = in.readLine().trim();
+ }
+ catch (IOException ignored)
+ {
+ continue;
+ }
+ outer:
+ while (line != null)
+ {
+ try
+ {
+ if (line.charAt(0) != '#')
+ {
+ Class<?> c = Class.forName(line);
+ descriptors.add((InputMethodDescriptor) c.newInstance());
+ }
+ line = in.readLine().trim();
+ }
+ catch (IOException ex)
+ {
+ continue outer;
+ }
+ catch (Exception ignored)
+ {
+ }
+ }
+ }
+ }
+
+ /** The current input method; null if no input methods are installed. */
+ private InputMethod im;
+
+ /** Map of locales to the most recently selected input method. */
+ private final HashMap<Locale,InputMethod> recent
+ = new HashMap<Locale,InputMethod>();
+
+ /** The list of acceptable character subsets. */
+ private Character.Subset[] subsets;
+
+ /**
+ * Construct an InputContext. This is protected, so clients must use
+ * {@link #getInstance()} instead.
+ */
+ protected InputContext()
+ {
+ }
+
+ /**
+ * Returns a new InputContext.
+ *
+ * @return a new instance, initialized to the default locale if available
+ */
+ public static InputContext getInstance()
+ {
+ InputContext ic = new InputContext();
+ ic.selectInputMethod(Locale.getDefault());
+ return ic;
+ }
+
+ /**
+ * Attempts to select an input method or keyboard layout which supports the
+ * given locale. This returns true if a locale is available and was selected.
+ * The following steps are taken in choosing an input method:<ul>
+ * <li>If the currently selected input method or keyboard layout supports
+ * the requested locale, it remains selected.</li>
+ * <li>If there is no input method or keyboard layout available that
+ * supports the requested locale, the current input method or keyboard
+ * layout remains selected.</li>
+ * <li>If the user has previously selected an input method or keyboard
+ * layout for the requested locale from the user interface, then the most
+ * recently selected such input method or keyboard layout is reselected.</li>
+ * <li>Otherwise, an input method or keyboard layout that supports the
+ * requested locale is selected in an implementation dependent way. This
+ * implementation chooses the first input method which supports the requested
+ * locale based on the InputMethodDescriptors loaded from the extensions
+ * installed on the CLASSPATH.</li>
+ * </ul>
+ *
+ * <p>Before switching away from an input method, any currently uncommitted
+ * text is committed. Not all host operating systems provide API to
+ * determine the locale of the currently selected native input method or
+ * keyboard layout, and to select a native input method or keyboard layout
+ * by locale. For host operating systems that don't provide such API,
+ * selectInputMethod assumes that native input methods or keyboard layouts
+ * provided by the host operating system support only the system's default
+ * locale.
+ *
+ * <p>An example of where this may be called is in a multi-language document,
+ * when moving the insertion point between sections of different locale, so
+ * that the user may use the input method appropriate to that section of the
+ * document.
+ *
+ * @param locale the desired new locale
+ * @return true if the new locale is active
+ * @throws NullPointerException if locale is null
+ */
+ public boolean selectInputMethod(Locale locale)
+ {
+ if (im != null && im.setLocale(locale))
+ {
+ recent.put(locale, im);
+ return true;
+ }
+ InputMethod next = recent.get(locale);
+ if (next != null)
+ for (int i = 0, limit = descriptors.size(); i < limit; i++)
+ {
+ InputMethodDescriptor d = descriptors.get(i);
+ Locale[] list;
+ try
+ {
+ list = d.getAvailableLocales();
+ }
+ catch (AWTException ignored)
+ {
+ continue;
+ }
+ for (int j = list.length; --j >= 0; )
+ if (locale.equals(list[j]))
+ {
+ try
+ {
+ next = d.createInputMethod();
+ recent.put(locale, next);
+ }
+ catch (Exception ignored)
+ {
+ continue;
+ }
+ }
+ }
+ if (next == null)
+ return false;
+ // XXX I'm not sure if this does all the necessary steps in the switch.
+ if (im != null)
+ {
+ try
+ {
+ next.setCompositionEnabled(im.isCompositionEnabled());
+ }
+ catch (UnsupportedOperationException ignored)
+ {
+ }
+ im.endComposition();
+ im.deactivate(false);
+ im.hideWindows();
+ }
+ im = next;
+ im.setLocale(locale);
+ im.setCharacterSubsets(subsets);
+ return true;
+ }
+
+ /**
+ * Returns the current locale of the current input method or keyboard
+ * layout. Returns null if the input context does not have a current input
+ * method or keyboard layout or if the current input method's
+ * {@link InputMethod#getLocale()} method returns null. Not all host
+ * operating systems provide API to determine the locale of the currently
+ * selected native input method or keyboard layout. For host operating
+ * systems that don't provide such API, getLocale assumes that the current
+ * locale of all native input methods or keyboard layouts provided by the
+ * host operating system is the system's default locale.
+ *
+ * @return the locale of the current input method, or null
+ * @since 1.3
+ */
+ public Locale getLocale()
+ {
+ return im == null ? null : im.getLocale();
+ }
+
+ /**
+ * Sets the subsets of Unicode characters allowed to be input by the current
+ * input method, as well as subsequent input methods. The value of null
+ * implies all characters are legal. Applications should not rely on this
+ * behavior, since native host input methods may not allow restrictions.
+ * If no current input method is available, this has no immediate effect.
+ *
+ * @param subsets the set of Unicode subsets to accept, or null
+ */
+ public void setCharacterSubsets(Character.Subset[] subsets)
+ {
+ this.subsets = subsets;
+ if (im != null)
+ im.setCharacterSubsets(subsets);
+ }
+
+ /**
+ * Changes the enabled status of the current input method. An input method
+ * that is enabled for composition interprets incoming events for both
+ * composition and control purposes, while a disabled input method only
+ * interprets control commands (including commands to enable itself).
+ *
+ * @param enable whether to enable the input method
+ * @throws UnsupportedOperationException if there is no current input method,
+ * or the input method does not support enabling
+ * @see #isCompositionEnabled()
+ * @since 1.3
+ */
+ public void setCompositionEnabled(boolean enable)
+ {
+ if (im == null)
+ throw new UnsupportedOperationException();
+ im.setCompositionEnabled(enable);
+ }
+
+ /**
+ * Find out if the current input method is enabled.
+ *
+ * @return true if the current input method is enabled
+ * @throws UnsupportedOperationException if there is no current input method,
+ * or the input method does not support enabling
+ * @see #setCompositionEnabled(boolean)
+ * @since 1.3
+ */
+ public boolean isCompositionEnabled()
+ {
+ if (im == null)
+ throw new UnsupportedOperationException();
+ return im.isCompositionEnabled();
+ }
+
+ /**
+ * Starts a reconversion operation in the current input method. The input
+ * method gets the text to reconvert from the client component, using
+ * {@link InputMethodRequests#getSelectedText(Attribute[])}. Then the
+ * composed and committed text produced by the operation is sent back to
+ * the client using a sequence of InputMethodRequests.
+ *
+ * @throws UnsupportedOperationException if there is no current input method,
+ * or the input method does not support reconversion
+ * @since 1.3
+ */
+ public void reconvert()
+ {
+ if (im == null)
+ throw new UnsupportedOperationException();
+ im.reconvert();
+ }
+
+ /**
+ * Dispatches an event to the current input method. This is called
+ * automatically by AWT. If no input method is available, then the event
+ * will never be consumed.
+ *
+ * @param event the event to dispatch
+ * @throws NullPointerException if event is null
+ */
+ public void dispatchEvent(AWTEvent event)
+ {
+ if (im != null)
+ im.dispatchEvent(event);
+ }
+
+ /**
+ * Notifies the input context that a client component has been removed from
+ * its containment hierarchy, or that input method support has been disabled
+ * for the component. This method is usually called from the client
+ * component's {@link Component#removeNotify()} method. Potentially pending
+ * input from input methods for this component is discarded. If no input
+ * methods are available, then this method has no effect.
+ *
+ * @param client the client component
+ * @throws NullPointerException if client is null
+ */
+ public void removeNotify(Component client)
+ {
+ // XXX What to do with client information?
+ if (im != null)
+ {
+ im.deactivate(false);
+ im.removeNotify();
+ }
+ }
+
+ /**
+ * Ends any input composition that may currently be going on in this
+ * context. Depending on the platform and possibly user preferences, this
+ * may commit or delete uncommitted text. Any changes to the text are
+ * communicated to the active component using an input method event. If no
+ * input methods are available, then this method has no effect. This may
+ * be called for a variety of reasons, such as when the user moves the
+ * insertion point in the client text outside the range of the composed text,
+ * or when text is saved to file.
+ */
+ public void endComposition()
+ {
+ if (im != null)
+ im.endComposition();
+ }
+
+ /**
+ * Disposes of the input context and release the resources used by it.
+ * Called automatically by AWT for the default input context of each
+ * Window. If no input methods are available, then this method has no
+ * effect.
+ */
+ public void dispose()
+ {
+ if (im != null)
+ {
+ im.deactivate(false);
+ im.dispose();
+ }
+ }
+
+ /**
+ * Returns a control object from the current input method, or null. A
+ * control object provides implementation-dependent methods that control
+ * the behavior of the input method or obtain information from the input
+ * method. Clients have to compare the result against known input method
+ * control object types. If no input methods are available or the current
+ * input method does not provide an input method control object, then null
+ * is returned.
+ *
+ * @return the control object, or null
+ */
+ public Object getInputMethodControlObject()
+ {
+ return im == null ? null : im.getControlObject();
+ }
+} // class InputContext
diff --git a/libjava/classpath/java/awt/im/InputMethodHighlight.java b/libjava/classpath/java/awt/im/InputMethodHighlight.java
new file mode 100644
index 000000000..a2ee86d44
--- /dev/null
+++ b/libjava/classpath/java/awt/im/InputMethodHighlight.java
@@ -0,0 +1,189 @@
+/* InputMethodHighlight.java -- highlights the current text selection
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.im;
+
+import java.awt.Toolkit;
+import java.text.Annotation;
+import java.text.AttributedCharacterIterator;
+import java.util.Map;
+import java.awt.font.TextAttribute;
+
+/**
+ * This describes the highlight attributes of text composed in an input method.
+ * The description includes an abstract level (whether text has been converted
+ * yet, and whether it is selected), and a concrete level (which style
+ * attributes are used in rendering). If no concrete level is defined, the
+ * renderer should use
+ * {@link Toolkit#mapInputMethodHighlight(InputMethodHighlight)}. An example
+ * of conversion state is kana -&gt; kanji.
+ *
+ * <p>Instances of this class are typically used in
+ * AttributedCharacterIterators, and may be wrapped in Annotations to separate
+ * text segments.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see AttributedCharacterIterator
+ * @see Annotation
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class InputMethodHighlight
+{
+ /** Raw text state (before conversion). */
+ public static final int RAW_TEXT = 0;
+
+ /** Converted text state (after conversion). */
+ public static final int CONVERTED_TEXT = 1;
+
+ /** Default do-nothing highlighting for unselected raw text. */
+ public static final InputMethodHighlight UNSELECTED_RAW_TEXT_HIGHLIGHT
+ = new InputMethodHighlight(false, RAW_TEXT);
+
+ /** Default do-nothing highlighting for selected raw text. */
+ public static final InputMethodHighlight SELECTED_RAW_TEXT_HIGHLIGHT
+ = new InputMethodHighlight(true, RAW_TEXT);
+
+ /** Default do-nothing highlighting for unselected converted text. */
+ public static final InputMethodHighlight UNSELECTED_CONVERTED_TEXT_HIGHLIGHT
+ = new InputMethodHighlight(false, CONVERTED_TEXT);
+
+ /** Default do-nothing highlighting for selected converted text. */
+ public static final InputMethodHighlight SELECTED_CONVERTED_TEXT_HIGHLIGHT
+ = new InputMethodHighlight(true, CONVERTED_TEXT);
+
+ /** Whether the highlighting applies to selected text. */
+ private final boolean selected;
+
+ /** The state of highlighted text. */
+ private final int state;
+
+ /** Any variation on the highlighting style. */
+ private final int variation;
+
+ /** The unmodifiable map of rendering styles. */
+ private final Map<TextAttribute, ?> style;
+
+ /**
+ * Create an input method highlight style, with variation 0 and null style
+ * mapping.
+ *
+ * @param selected whether the text range is selected
+ * @param state either {@link #RAW_TEXT} or {@link #CONVERTED_TEXT}
+ * @throws IllegalArgumentException if state is invalid
+ */
+ public InputMethodHighlight(boolean selected, int state)
+ {
+ this(selected, state, 0, null);
+ }
+
+ /**
+ * Create an input method highlight style, with null style mapping.
+ *
+ * @param selected whether the text range is selected
+ * @param state either {@link #RAW_TEXT} or {@link #CONVERTED_TEXT}
+ * @param variation the style variation
+ * @throws IllegalArgumentException if state is invalid
+ */
+ public InputMethodHighlight(boolean selected, int state, int variation)
+ {
+ this(selected, state, variation, null);
+ }
+
+ /**
+ * Create an input method highlight style.
+ *
+ * @param selected whether the text range is selected
+ * @param state either {@link #RAW_TEXT} or {@link #CONVERTED_TEXT}
+ * @param variation the style variation
+ * @param style an unmodifiable map of rendering styles, or null
+ * @throws IllegalArgumentException if state is invalid
+ * @since 1.3
+ */
+ public InputMethodHighlight(boolean selected, int state, int variation,
+ Map<TextAttribute, ?> style)
+ {
+ if (state != RAW_TEXT && state != CONVERTED_TEXT)
+ throw new IllegalArgumentException();
+ this.selected = selected;
+ this.state = state;
+ this.variation = variation;
+ this.style = style;
+ }
+
+ /**
+ * Return whether the highlighting applies to selected text.
+ *
+ * @return the selection status
+ */
+ public boolean isSelected()
+ {
+ return selected;
+ }
+
+ /**
+ * Return the conversion state of the highlighted text.
+ *
+ * @return one of {@link #RAW_TEXT} or {@link #CONVERTED_TEXT}
+ */
+ public int getState()
+ {
+ return state;
+ }
+
+ /**
+ * Return the highlighting style variation.
+ *
+ * @return the variation
+ */
+ public int getVariation()
+ {
+ return variation;
+ }
+
+ /**
+ * Return the rendering style attributes map, or null if it should be the
+ * default mapping.
+ *
+ * @return the style map
+ * @since 1.3
+ */
+ public Map<TextAttribute, ?> getStyle()
+ {
+ return style;
+ }
+} // class InputMethodHighlight
diff --git a/libjava/classpath/java/awt/im/InputMethodRequests.java b/libjava/classpath/java/awt/im/InputMethodRequests.java
new file mode 100644
index 000000000..0423358cc
--- /dev/null
+++ b/libjava/classpath/java/awt/im/InputMethodRequests.java
@@ -0,0 +1,155 @@
+/* InputMethodRequests.java -- handles text insertion via input methods
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.im;
+
+import java.awt.Component;
+import java.awt.Rectangle;
+import java.awt.font.TextHitInfo;
+import java.awt.event.InputMethodListener;
+import java.text.AttributedCharacterIterator;
+import java.text.AttributedCharacterIterator.Attribute;
+
+/**
+ * This interface handles requests made by input methods on text editing
+ * components. A component must specify a handler for input methods that
+ * implements this interface, and which supports one of two user interfaces:
+ * <ul><li><em>on-the-spot</em>: composed text is shown in place</li>
+ * <li><em>below-the-spot</em>: composed text is in a separate window,
+ * usually below the main text window, until it is committed into place at
+ * the insertion point, overwriting any selected text</li></ul>
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Component#getInputMethodRequests()
+ * @see InputMethodListener
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface InputMethodRequests
+{
+ /**
+ * Gets the location of a given offset of the text. This can be used to
+ * position a composition window near the location of where the composed
+ * text will be inserted.
+ *
+ * <p>If the component has composed text (from the most recent
+ * InputMethodEvent), then offset 0 indicates the location of the first
+ * character of this composed text. Otherwise, the offset is ignored, and
+ * the location should be the beginning of the final line of selected
+ * text (in horizontal left-to-right text, like English, this would be the
+ * lower left corner of the selction; in vertical top-to-bottom text, like
+ * Chinese, this would be the top right corner of the selection).
+ *
+ * <p>The location returned is a 0-thickness caret (either horizontal or
+ * vertical, depending on text flow), mapped to absolute screen coordinates.
+ *
+ * @param offset offset within composed text, or null
+ * @return the screen location of the caret at the offset
+ */
+ Rectangle getTextLocation(TextHitInfo offset);
+
+ /**
+ * Get the text offset for the given screen coordinate. The offset is
+ * relative to the composed text, and the return is null if it is outside
+ * the range of composed text. For example, this can be used to find
+ * where a mouse click should pop up a text composition window.
+ *
+ * @param x the x screen coordinate
+ * @param y the y screen coordinate
+ * @return a text hit info describing the composed text offset
+ */
+ TextHitInfo getLocationOffset(int x, int y);
+
+ /**
+ * Gets the offset where the committed text exists in the text editing
+ * component. This can be used to examine the text surrounding the insert
+ * position.
+ *
+ * @return the offset of the insert position
+ */
+ int getInsertPositionOffset();
+
+ /**
+ * Gets an interator which provides access to the text and its attributes,
+ * except for the uncommitted text. The input method may provide a list of
+ * attributes it is interested in; and the iterator need not provide
+ * information on the remaining attributes. If the attribute list is null,
+ * the iterator must list all attributes.
+ *
+ * @param beginIndex the index of the first character in the iteration
+ * @param endIndex the index of the last character in the iteration
+ * @param attributes a list of attributes interested in, or null
+ * @return an iterator over the region of text with its attributes
+ */
+ AttributedCharacterIterator getCommittedText(int beginIndex, int endIndex,
+ Attribute[] attributes);
+
+ /**
+ * Gets the length of committed text.
+ *
+ * @return the number of committed characters
+ */
+ int getCommittedTextLength();
+
+ /**
+ * Gets the latest committed text, and removes it from the component's text
+ * body. This allows an input method to provide an "Undo" command. In
+ * general, this should only be supported immediately after a commit, and
+ * not when other actions intervene; if not supported, simply return null.
+ * The input method may provide a list of attributes it is interested in;
+ * and the iterator need not provide information on the remaining attributes.
+ * If the attribute list is null, the iterator must list all attributes.
+ *
+ * @param attributes a list of attributes interested in, or null
+ * @return the latest committed text, or null
+ */
+ AttributedCharacterIterator cancelLatestCommittedText
+ (Attribute[] attributes);
+
+ /**
+ * Gets the currently selected text. One use of this is to implement a
+ * "Reconvert" feature in an input method, which modifies the selection
+ * based on the text in the composition window. The input method may
+ * provide a list of attributes it is interested in; and the iterator need
+ * not provide information on the remaining attributes. If the attribute
+ * list is null, the iterator must list all attributes.
+ *
+ * @param attributes a list of attributes interested in, or null
+ * @return the current selection
+ */
+ AttributedCharacterIterator getSelectedText(Attribute[] attributes);
+} // interface InputMethodRequests
diff --git a/libjava/classpath/java/awt/im/InputSubset.java b/libjava/classpath/java/awt/im/InputSubset.java
new file mode 100644
index 000000000..5e7d58e7f
--- /dev/null
+++ b/libjava/classpath/java/awt/im/InputSubset.java
@@ -0,0 +1,129 @@
+/* InputSubset.java -- subsets of Unicode important in text input
+ Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.im;
+
+/**
+ * Defines additional Unicode character blocks for use by input methods.
+ * These constants encompass several Unicode blocks, or portions thereof, for
+ * simplification over {@link Character.UnicodeBlock}.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public final class InputSubset extends Character.Subset
+{
+ /**
+ * Constant for all Latin characters, including the characters in the
+ * BASIC_LATIN, LATIN_1_SUPPLEMENT, LATIN_EXTENDED_A, LATIN_EXTENDED_B
+ * Unicode character blocks.
+ */
+ public static final InputSubset LATIN = new InputSubset("LATIN");
+
+ /**
+ * Constant for the digits included in the BASIC_LATIN Unicode character
+ * block.
+ */
+ public static final InputSubset LATIN_DIGITS
+ = new InputSubset("LATIN_DIGITS");
+
+ /**
+ * Constant for all Han characters used in writing Traditional Chinese,
+ * including a subset of the CJK unified ideographs as well as Traditional
+ * Chinese Han characters that may be defined as surrogate characters.
+ */
+ public static final InputSubset TRADITIONAL_HANZI
+ = new InputSubset("TRADITIONAL_HANZI");
+
+ /**
+ * Constant for all Han characters used in writing Simplified Chinese,
+ * including a subset of the CJK unified ideographs as well as Simplified
+ * Chinese Han characters that may be defined as surrogate characters.
+ */
+ public static final InputSubset SIMPLIFIED_HANZI
+ = new InputSubset("SIMPLIFIED_HANZI");
+
+ /**
+ * Constant for all Han characters used in writing Japanese, including a
+ * subset of the CJK unified ideographs as well as Japanese Han characters
+ * that may be defined as surrogate characters.
+ */
+ public static final InputSubset KANJI = new InputSubset("KANJI");
+
+ /**
+ * Constant for all Han characters used in writing Korean, including a
+ * subset of the CJK unified ideographs as well as Korean Han characters
+ * that may be defined as surrogate characters.
+ */
+ public static final InputSubset HANJA = new InputSubset("HANJA");
+
+ /**
+ * Constant for the halfwidth katakana subset of the Unicode halfwidth and
+ * fullwidth forms character block.
+ */
+ public static final InputSubset HALFWIDTH_KATAKANA
+ = new InputSubset("HALFWIDTH_KATAKANA");
+
+ /**
+ * Constant for the fullwidth ASCII variants subset of the Unicode
+ * halfwidth and fullwidth forms character block.
+ *
+ * @since 1.3
+ */
+ public static final InputSubset FULLWIDTH_LATIN
+ = new InputSubset("FULLWIDTH_LATIN");
+
+ /**
+ * Constant for the fullwidth digits included in the Unicode halfwidth and
+ * fullwidth forms character block.
+ *
+ * @since 1.3
+ */
+ public static final InputSubset FULLWIDTH_DIGITS
+ = new InputSubset("FULLWIDTH_DIGITS");
+
+ /**
+ * Construct a subset.
+ *
+ * @param name the subset name
+ */
+ private InputSubset(String name)
+ {
+ super(name);
+ }
+} // class InputSubset
diff --git a/libjava/classpath/java/awt/im/package.html b/libjava/classpath/java/awt/im/package.html
new file mode 100644
index 000000000..895da66d5
--- /dev/null
+++ b/libjava/classpath/java/awt/im/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt.im package.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - java.awt.im</title></head>
+
+<body>
+<p>Support for text input methods.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/im/spi/InputMethod.java b/libjava/classpath/java/awt/im/spi/InputMethod.java
new file mode 100644
index 000000000..ebe450841
--- /dev/null
+++ b/libjava/classpath/java/awt/im/spi/InputMethod.java
@@ -0,0 +1,244 @@
+/* InputMethod.java -- defines an interface for complex text input
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.im.spi;
+
+import java.awt.AWTEvent;
+import java.awt.Component;
+import java.awt.Rectangle;
+import java.awt.im.InputContext;
+import java.awt.im.InputMethodRequests;
+import java.text.AttributedCharacterIterator.Attribute;
+import java.util.Locale;
+
+/**
+ * This interface supports complex text input, often for situations where
+ * the text is more complex than a keyboard will accomodate. For example,
+ * this can be used for Chinese, Japanese, and Korean, where multiple
+ * keystrokes are necessary to compose text. This could also support things
+ * like phonetic English, or reordering Thai.
+ *
+ * <p>These contexts can be loaded by the input method framework, using
+ * {@link InputContext#selectInputMethod(Locale)}.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.3
+ * @status updated to 1.4
+ */
+public interface InputMethod
+{
+ /**
+ * Set the input method context, which ties the input method to a client
+ * component. This is called once automatically when creating the input
+ * method.
+ *
+ * @param context the context for this input method
+ * @throws NullPointerException if context is null
+ */
+ void setInputMethodContext(InputMethodContext context);
+
+ /**
+ * Sets the input locale. If the input method supports that locale, it
+ * changes its behavior to be consistent with the locale and returns true.
+ * Otherwise, it returns false. This is called by
+ * {@link InputContext#selectInputMethod(Locale)} when the user specifies
+ * a locale, or when the previously selected input method had a locale.
+ *
+ * @param locale the locale to use for input
+ * @return true if the change is successful
+ * @throws NullPointerException if locale is null
+ */
+ boolean setLocale(Locale locale);
+
+ /**
+ * Returns the current input locale, or null if none is defined. This is
+ * called by {@link InputContext#getLocale()}, or before switching input
+ * methods.
+ *
+ * @return the current input locale, or null
+ */
+ Locale getLocale();
+
+ /**
+ * Sets the allowed Unicode subsets that this input method can use. Null
+ * indicates that all characters are allowed. This is called after creation,
+ * or when switching to this input method, by
+ * {@link InputContext#setCharacterSubsets(Character.Subset[])}.
+ *
+ * @param subsets the accepted subsets for this input method, or null for all
+ */
+ void setCharacterSubsets(Character.Subset[] subsets);
+
+ /**
+ * Changes the enabled status of this input method. An enabled input method
+ * accepts incoming events for composition and control purposes, while a
+ * disabled input method ignores events (except for control purposes). This
+ * is called by {@link InputContext#setCompositionEnabled(boolean)} or when
+ * switching from an input method if the previous input method returned
+ * without exception on {@link #isCompositionEnabled()}.
+ *
+ * @param enable whether to enable this input method
+ * @throws UnsupportedOperationException if enabling/disabling is unsupported
+ * @see #isCompositionEnabled()
+ */
+ void setCompositionEnabled(boolean enable);
+
+ /**
+ * Find out if this input method is enabled. This is called by
+ * {@link InputContext#isCompositionEnabled()}, or when switching input
+ * methods via {@link InputContext#selectInputMethod(Locale)}.
+ *
+ * @return true if this input method is enabled
+ * @throws UnsupportedOperationException if enabling/disabling is unsupported
+ * @see #setCompositionEnabled(boolean)
+ */
+ boolean isCompositionEnabled();
+
+ /**
+ * Starts a reconversion operation. The input method gets its text from the
+ * client, using {@link InputMethodRequests#getSelectedText(Attribute[])}.
+ * Then the composed and committed text produced by the operation is sent
+ * back to the client using a sequence of InputMethodEvents. This is called
+ * by {@link InputContext#reconvert()}.
+ *
+ * @throws UnsupportedOperationException if reconversion is unsupported
+ */
+ void reconvert();
+
+ /**
+ * Dispatch an event to the input method. If input method support is enabled,
+ * certain events are dispatched to the input method before the client
+ * component or event listeners. The input method must either consume the
+ * event or pass it on to the component. Instances of InputEvent, including
+ * KeyEvent and MouseEvent, are given to this input method. This method is
+ * called by {@link InputContext#dispatchEvent(AWTEvent)}.
+ *
+ * @param event the event to dispatch
+ * @throws NullPointerException if event is null
+ */
+ void dispatchEvent(AWTEvent event);
+
+ /**
+ * Notify this input method of changes in the client window. This is called
+ * when notifications are enabled (see {@link
+ * InputMethodContext#enableClientWindowNotification(InputMethod, boolean)},
+ * if {@link InputContext#removeNotify(Component)} has not been called.
+ * The following situations trigger a notification:<ul>
+ * <li>The client window changes in location, size, visibility,
+ * iconification, or is closed.</li>
+ * <li>When enabling client notification (or on the first activation after
+ * enabling if no client existed at the time).</li>
+ * <li>When activating a new client after <code>removeNotify</code> was
+ * called on a previous client.</li>
+ * </ul>
+ *
+ * @param bounds the client window's current bounds, or null
+ */
+ void notifyClientWindowChange(Rectangle bounds);
+
+ /**
+ * Activate this input method for input processing. If the input method
+ * provides its own windows, it should make them open and visible at this
+ * time. This method is called when a client component receives a
+ * FOCUS_GAINED event, or when switching to this input method from another
+ * one. It is only called when the input method is inactive, assuming that
+ * new instances begin in an inactive state.
+ */
+ void activate();
+
+ /**
+ * Deactivate this input method, either temporarily or permanently for the
+ * given client. If the input method provides its own windows, it should
+ * only close those related to the current composition (such as a lookup
+ * choice panel), while leaving more persistant windows (like a control
+ * panel) open to avoid screen flicker. Before control is given to another
+ * input method, {@link #hideWindows()} will be called on this instance.
+ * This method is called when a client component receives a
+ * FOCUS_LOST event, when switching to another input method, or before
+ * {@link #removeNotify()} when the client is removed.
+ *
+ * @param isTemporary true if the focus change is temporary
+ */
+ void deactivate(boolean isTemporary);
+
+ /**
+ * Close or hide all windows opened by this input method. This is called
+ * before activating a different input method, and before calling
+ * {@link #dispose()} on this instance. It is only called when the input
+ * method is inactive.
+ */
+ void hideWindows();
+
+ /**
+ * Notify the input method that a client component has been removed from its
+ * hierarchy, or that input method support has been disabled. This is
+ * called by {@link InputContext#removeNotify(Component)}, and only when the input
+ * method is inactive.
+ */
+ void removeNotify();
+
+ /**
+ * End any input composition currently taking place. Depending on the
+ * platform and user preferences, this may commit or delete uncommitted text,
+ * using input method events. This may be called for a variety of reasons,
+ * such as when the user moves the insertion point in the client text outside
+ * the range of the composed text, or when text is saved to file. This is
+ * called by {@link InputContext#endComposition()}, when switching to a
+ * new input method, or by {@link InputContext#selectInputMethod(Locale)}.
+ */
+ void endComposition();
+
+ /**
+ * Disposes the input method and release any resources it is using. In
+ * particular, the input method should dispose windows and close files. This
+ * is called by {@link InputContext#dispose()}, when the input method is
+ * inactive; and nothing will be called on this instance afterwards.
+ */
+ void dispose();
+
+ /**
+ * Returns a control object from this input method, or null. A control object
+ * provides method to control the behavior of this input method, as well as
+ * query information about it. The object is implementation dependent, so
+ * clients must compare the result against known input method control
+ * object types. This is called by
+ * {@link InputContext#getInputMethodControlObject()}.
+ *
+ * @return the control object, or null
+ */
+ Object getControlObject();
+} // interface InputMethod
diff --git a/libjava/classpath/java/awt/im/spi/InputMethodContext.java b/libjava/classpath/java/awt/im/spi/InputMethodContext.java
new file mode 100644
index 000000000..aed21e8d3
--- /dev/null
+++ b/libjava/classpath/java/awt/im/spi/InputMethodContext.java
@@ -0,0 +1,126 @@
+/* InputMethodContext.java -- communication between an input method and client
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.im.spi;
+
+import java.awt.HeadlessException;
+import java.awt.Rectangle;
+import java.awt.Window;
+import java.awt.font.TextHitInfo;
+import java.awt.im.InputMethodRequests;
+import java.text.AttributedCharacterIterator;
+
+import javax.swing.JFrame;
+
+/**
+ * Provides methods for the communication context between an input method
+ * and the client component. This should be passed to
+ * {@link InputMethod#setInputMethodContext(InputMethodContext)}.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.3
+ * @status updated to 1.4
+ */
+public interface InputMethodContext extends InputMethodRequests
+{
+ /**
+ * Create an input method event and dispatch it to the client.
+ *
+ * @param id the event type
+ * @param text an iterator over the text to be committed
+ * @param count the count of characters to be committed
+ * @param caret the insertion point of the commit, or null
+ * @param visiblePosition the best location to make visible, or null
+ */
+ void dispatchInputMethodEvent(int id, AttributedCharacterIterator text,
+ int count, TextHitInfo caret,
+ TextHitInfo visiblePosition);
+
+ /**
+ * Creates a top-level window for use by the input method. This window should
+ * float above all document windows and dialogs, not receive focus, and have
+ * lightweight decorations (such as no title, reduced drag regions). But
+ * this behavior may be modified to meet the platform style. The title may
+ * or may not be displayed, depending on the platform.
+ *
+ * <p>If attachToInputContext is true, the new window will share the input
+ * context of the input method, so that events in the new window are
+ * dispatched to the input method. Also, this supresses deactivate and
+ * activate calls to the input method caused by setVisible.
+ *
+ * @param title the window title, if one is displayed; null becomes ""
+ * @param attachToInputContext true for the window to share context with
+ * the input method
+ * @return the new window for use by the input method
+ * @throws HeadlessException if GraphicsEnvironment.isHeadless is true
+ */
+ Window createInputMethodWindow(String title, boolean attachToInputContext);
+
+ /**
+ * Creates a top-level Swing JFrame for use by the input method. This frame
+ * should float above all document windows and dialogs, not receive focus,
+ * and have lightweight decorations (such as no title, reduced drag
+ * regions). But this behavior may be modified to meet the platform style.
+ * The title may or may not be displayed, depending on the platform.
+ *
+ * <p>If attachToInputContext is true, the new window will share the input
+ * context of the input method, so that events in the new window are
+ * dispatched to the input method. Also, this supresses deactivate and
+ * activate calls to the input method caused by setVisible.
+ *
+ * @param title the window title, if one is displayed; null becomes ""
+ * @param attachToInputContext true for the window to share context with
+ * the input method
+ * @return the new window for use by the input method
+ * @throws HeadlessException if GraphicsEnvironment.isHeadless is true
+ * @since 1.4
+ */
+ JFrame createInputMethodJFrame(String title, boolean attachToInputContext);
+
+ /**
+ * Sets whether notification of the client window's location and state should
+ * be enabled for the input method. When enabled, the input method's
+ * {@link InputMethod#notifyClientWindowChange(Rectangle)} method is called.
+ * Notification is automatically disabled when the input method is disposed.
+ *
+ * @param inputMethod the method to change status of
+ * @param enable true to enable notification
+ */
+ void enableClientWindowNotification(InputMethod inputMethod, boolean enable);
+} // interface InputMethodContext
diff --git a/libjava/classpath/java/awt/im/spi/InputMethodDescriptor.java b/libjava/classpath/java/awt/im/spi/InputMethodDescriptor.java
new file mode 100644
index 000000000..ce40ab2b6
--- /dev/null
+++ b/libjava/classpath/java/awt/im/spi/InputMethodDescriptor.java
@@ -0,0 +1,113 @@
+/* InputMethodDescriptor.java -- enables loading and use of an input method
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.im.spi;
+
+import java.awt.AWTException;
+import java.awt.Image;
+import java.awt.im.InputContext;
+import java.util.Locale;
+
+/**
+ * This interface provides information about an InputMethod before it is
+ * loaded.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.3
+ * @status updated to 1.4
+ */
+public interface InputMethodDescriptor
+{
+ /**
+ * Returns the locales supported by the input method this describes. This
+ * allows the selection of input methods by locale (by language only, or
+ * also by country and variant), via
+ * {@link InputContext#selectInputMethod(Locale)}. The returned list should
+ * ignore pass-through locales, so it is usually a subset of locales for
+ * which {@link InputMethod#setLocale(Locale)} returns true. If
+ * {@link #hasDynamicLocaleList()} returns true, this is called each time
+ * information is needed, allowing dynamic addition or removal of supported
+ * locales.
+ *
+ * @return the list of supported locales
+ * @throws AWTException if the input method is not available
+ */
+ Locale[] getAvailableLocales() throws AWTException;
+
+ /**
+ * Test whether the input method this describes has a static or dynamic
+ * locale list. For example, this would return true if the list of supported
+ * locales depends on adapters currently loaded over a network.
+ *
+ * @return true if the locale list is dynamic
+ */
+ boolean hasDynamicLocaleList();
+
+ /**
+ * Returns a user visible name of the input locale, displayed in the
+ * specified locale. The inputLocale parameter must be one obtained from
+ * the list in {@link #getAvailableLocales()}, or null for a
+ * locale-independent description of the input method. If a translation to
+ * the desired display language is not available, another language may be
+ * used.
+ *
+ * @param inputLocale the locale of the input method, or null
+ * @param displayLanguage the language of the result
+ * @return the name of the input method when using the given inputLocale
+ */
+ String getInputMethodDisplayName(Locale inputLocale,
+ Locale displayLanguage);
+
+ /**
+ * Returns a 16x16 icon for the input locale. The inputLocale parameter
+ * must be one obtained from the list in {@link #getAvailableLocales()}, or
+ * null for a locale-independent icon for the input method.
+ *
+ * @param inputLocale the locale of the input method, or null
+ * @return a 16x16 icon for the input method when using the given inputLocale
+ */
+ Image getInputMethodIcon(Locale inputLocale);
+
+ /**
+ * Creates a new instance of the input method.
+ *
+ * @return the newly created input method
+ * @throws Exception if anything goes wrong
+ */
+ InputMethod createInputMethod() throws Exception;
+
+} // interface InputMethodDescriptor
diff --git a/libjava/classpath/java/awt/im/spi/package.html b/libjava/classpath/java/awt/im/spi/package.html
new file mode 100644
index 000000000..c526ee159
--- /dev/null
+++ b/libjava/classpath/java/awt/im/spi/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt.im.spi package.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - java.awt.im.spi</title></head>
+
+<body>
+<p>Interfaces for implementation of text input methods.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/image/AffineTransformOp.java b/libjava/classpath/java/awt/image/AffineTransformOp.java
new file mode 100644
index 000000000..460804f90
--- /dev/null
+++ b/libjava/classpath/java/awt/image/AffineTransformOp.java
@@ -0,0 +1,608 @@
+/* AffineTransformOp.java -- This class performs affine
+ transformation between two images or rasters in 2 dimensions.
+ Copyright (C) 2004, 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.Arrays;
+
+/**
+ * AffineTransformOp performs matrix-based transformations (translations,
+ * scales, flips, rotations, and shears).
+ *
+ * If interpolation is required, nearest neighbour, bilinear, and bicubic
+ * methods are available.
+ *
+ * @author Olga Rodimina (rodimina@redhat.com)
+ * @author Francis Kung (fkung@redhat.com)
+ */
+public class AffineTransformOp implements BufferedImageOp, RasterOp
+{
+ public static final int TYPE_NEAREST_NEIGHBOR = 1;
+
+ public static final int TYPE_BILINEAR = 2;
+
+ /**
+ * @since 1.5.0
+ */
+ public static final int TYPE_BICUBIC = 3;
+
+ private AffineTransform transform;
+ private RenderingHints hints;
+
+ /**
+ * Construct AffineTransformOp with the given xform and interpolationType.
+ * Interpolation type can be TYPE_BILINEAR, TYPE_BICUBIC or
+ * TYPE_NEAREST_NEIGHBOR.
+ *
+ * @param xform AffineTransform that will applied to the source image
+ * @param interpolationType type of interpolation used
+ * @throws ImagingOpException if the transform matrix is noninvertible
+ */
+ public AffineTransformOp (AffineTransform xform, int interpolationType)
+ {
+ this.transform = xform;
+ if (xform.getDeterminant() == 0)
+ throw new ImagingOpException(null);
+
+ switch (interpolationType)
+ {
+ case TYPE_BILINEAR:
+ hints = new RenderingHints (RenderingHints.KEY_INTERPOLATION,
+ RenderingHints.VALUE_INTERPOLATION_BILINEAR);
+ break;
+ case TYPE_BICUBIC:
+ hints = new RenderingHints (RenderingHints.KEY_INTERPOLATION,
+ RenderingHints.VALUE_INTERPOLATION_BICUBIC);
+ break;
+ default:
+ hints = new RenderingHints (RenderingHints.KEY_INTERPOLATION,
+ RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
+ }
+ }
+
+ /**
+ * Construct AffineTransformOp with the given xform and rendering hints.
+ *
+ * @param xform AffineTransform that will applied to the source image
+ * @param hints rendering hints that will be used during transformation
+ * @throws ImagingOpException if the transform matrix is noninvertible
+ */
+ public AffineTransformOp (AffineTransform xform, RenderingHints hints)
+ {
+ this.transform = xform;
+ this.hints = hints;
+ if (xform.getDeterminant() == 0)
+ throw new ImagingOpException(null);
+ }
+
+ /**
+ * Creates a new BufferedImage with the size equal to that of the
+ * transformed image and the correct number of bands. The newly created
+ * image is created with the specified ColorModel.
+ * If a ColorModel is not specified, an appropriate ColorModel is used.
+ *
+ * @param src the source image.
+ * @param destCM color model for the destination image (can be null).
+ * @return a new compatible destination image.
+ */
+ public BufferedImage createCompatibleDestImage (BufferedImage src,
+ ColorModel destCM)
+ {
+ if (destCM != null)
+ return new BufferedImage(destCM,
+ createCompatibleDestRaster(src.getRaster()),
+ src.isAlphaPremultiplied(), null);
+
+ // This behaviour was determined by Mauve testcases, and is compatible
+ // with the reference implementation
+ if (src.getType() == BufferedImage.TYPE_INT_ARGB_PRE
+ || src.getType() == BufferedImage.TYPE_4BYTE_ABGR
+ || src.getType() == BufferedImage.TYPE_4BYTE_ABGR_PRE)
+ return new BufferedImage(src.getWidth(), src.getHeight(), src.getType());
+
+ else
+ return new BufferedImage(src.getWidth(), src.getHeight(),
+ BufferedImage.TYPE_INT_ARGB);
+ }
+
+ /**
+ * Creates a new WritableRaster with the size equal to the transformed
+ * source raster and correct number of bands .
+ *
+ * @param src the source raster.
+ * @throws RasterFormatException if resulting width or height of raster is 0.
+ * @return a new compatible raster.
+ */
+ public WritableRaster createCompatibleDestRaster (Raster src)
+ {
+ Rectangle2D rect = getBounds2D(src);
+
+ if (rect.getWidth() == 0 || rect.getHeight() == 0)
+ throw new RasterFormatException("width or height is 0");
+
+ return src.createCompatibleWritableRaster((int) rect.getWidth(),
+ (int) rect.getHeight());
+ }
+
+ /**
+ * Transforms source image using transform specified at the constructor.
+ * The resulting transformed image is stored in the destination image if one
+ * is provided; otherwise a new BufferedImage is created and returned.
+ *
+ * @param src source image
+ * @param dst destination image
+ * @throws IllegalArgumentException if the source and destination image are
+ * the same
+ * @return transformed source image.
+ */
+ public final BufferedImage filter (BufferedImage src, BufferedImage dst)
+ {
+ if (dst == src)
+ throw new IllegalArgumentException("src image cannot be the same as "
+ + "the dst image");
+
+ // If the destination image is null, then use a compatible BufferedImage
+ if (dst == null)
+ dst = createCompatibleDestImage(src, null);
+
+ Graphics2D gr = dst.createGraphics();
+ gr.setRenderingHints(hints);
+ gr.drawImage(src, transform, null);
+ return dst;
+ }
+
+ /**
+ * Transforms source raster using transform specified at the constructor.
+ * The resulting raster is stored in the destination raster if it is not
+ * null, otherwise a new raster is created and returned.
+ *
+ * @param src source raster
+ * @param dst destination raster
+ * @throws IllegalArgumentException if the source and destination are not
+ * compatible
+ * @return transformed raster.
+ */
+ public final WritableRaster filter(Raster src, WritableRaster dst)
+ {
+ // Initial checks
+ if (dst == src)
+ throw new IllegalArgumentException("src image cannot be the same as"
+ + " the dst image");
+
+ if (dst == null)
+ dst = createCompatibleDestRaster(src);
+
+ if (src.getNumBands() != dst.getNumBands())
+ throw new IllegalArgumentException("src and dst must have same number"
+ + " of bands");
+
+ // Optimization for rasters that can be represented in the RGB colormodel:
+ // wrap the rasters in images, and let Cairo do the transformation
+ if (ColorModel.getRGBdefault().isCompatibleSampleModel(src.getSampleModel())
+ && ColorModel.getRGBdefault().isCompatibleSampleModel(dst.getSampleModel()))
+ {
+ WritableRaster src2 = Raster.createWritableRaster(src.getSampleModel(),
+ src.getDataBuffer(),
+ new Point(src.getMinX(),
+ src.getMinY()));
+ BufferedImage iSrc = new BufferedImage(ColorModel.getRGBdefault(),
+ src2, false, null);
+ BufferedImage iDst = new BufferedImage(ColorModel.getRGBdefault(), dst,
+ false, null);
+
+ return filter(iSrc, iDst).getRaster();
+ }
+
+ // Otherwise, we need to do the transformation in java code...
+ // Create arrays to hold all the points
+ double[] dstPts = new double[dst.getHeight() * dst.getWidth() * 2];
+ double[] srcPts = new double[dst.getHeight() * dst.getWidth() * 2];
+
+ // Populate array with all points in the *destination* raster
+ int i = 0;
+ for (int x = 0; x < dst.getWidth(); x++)
+ {
+ for (int y = 0; y < dst.getHeight(); y++)
+ {
+ dstPts[i++] = x;
+ dstPts[i++] = y;
+ }
+ }
+ Rectangle srcbounds = src.getBounds();
+
+ // Use an inverse transform to map each point in the destination to
+ // a point in the source. Note that, while all points in the destination
+ // matrix are integers, this is not necessarily true for points in the
+ // source (hence why interpolation is required)
+ try
+ {
+ AffineTransform inverseTx = transform.createInverse();
+ inverseTx.transform(dstPts, 0, srcPts, 0, dstPts.length / 2);
+ }
+ catch (NoninvertibleTransformException e)
+ {
+ // Shouldn't happen since the constructor traps this
+ throw new ImagingOpException(e.getMessage());
+ }
+
+ // Different interpolation methods...
+ if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR))
+ filterNearest(src, dst, dstPts, srcPts);
+
+ else if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_BILINEAR))
+ filterBilinear(src, dst, dstPts, srcPts);
+
+ else // bicubic
+ filterBicubic(src, dst, dstPts, srcPts);
+
+ return dst;
+ }
+
+ /**
+ * Transforms source image using transform specified at the constructor and
+ * returns bounds of the transformed image.
+ *
+ * @param src image to be transformed
+ * @return bounds of the transformed image.
+ */
+ public final Rectangle2D getBounds2D (BufferedImage src)
+ {
+ return getBounds2D (src.getRaster());
+ }
+
+ /**
+ * Returns bounds of the transformed raster.
+ *
+ * @param src raster to be transformed
+ * @return bounds of the transformed raster.
+ */
+ public final Rectangle2D getBounds2D (Raster src)
+ {
+ return transform.createTransformedShape(src.getBounds()).getBounds2D();
+ }
+
+ /**
+ * Returns interpolation type used during transformations.
+ *
+ * @return interpolation type
+ */
+ public final int getInterpolationType ()
+ {
+ if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_BILINEAR))
+ return TYPE_BILINEAR;
+
+ else if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_BICUBIC))
+ return TYPE_BICUBIC;
+
+ else
+ return TYPE_NEAREST_NEIGHBOR;
+ }
+
+ /**
+ * Returns location of the transformed source point. The resulting point
+ * is stored in the dstPt if one is specified.
+ *
+ * @param srcPt point to be transformed
+ * @param dstPt destination point
+ * @return the location of the transformed source point.
+ */
+ public final Point2D getPoint2D (Point2D srcPt, Point2D dstPt)
+ {
+ return transform.transform (srcPt, dstPt);
+ }
+
+ /**
+ * Returns rendering hints that are used during transformation.
+ *
+ * @return the rendering hints used in this Op.
+ */
+ public final RenderingHints getRenderingHints ()
+ {
+ return hints;
+ }
+
+ /**
+ * Returns transform used in transformation between source and destination
+ * image.
+ *
+ * @return the transform used in this Op.
+ */
+ public final AffineTransform getTransform ()
+ {
+ return transform;
+ }
+
+ /**
+ * Perform nearest-neighbour filtering
+ *
+ * @param src the source raster
+ * @param dst the destination raster
+ * @param dpts array of points on the destination raster
+ * @param pts array of corresponding points on the source raster
+ */
+ private void filterNearest(Raster src, WritableRaster dst, double[] dpts,
+ double[] pts)
+ {
+ Rectangle srcbounds = src.getBounds();
+
+ // For all points on the destination raster, copy the value from the
+ // corrosponding (rounded) source point
+ for (int i = 0; i < dpts.length; i += 2)
+ {
+ int srcX = (int) Math.round(pts[i]) + src.getMinX();
+ int srcY = (int) Math.round(pts[i + 1]) + src.getMinY();
+
+ if (srcbounds.contains(srcX, srcY))
+ dst.setDataElements((int) dpts[i] + dst.getMinX(),
+ (int) dpts[i + 1] + dst.getMinY(),
+ src.getDataElements(srcX, srcY, null));
+ }
+ }
+
+ /**
+ * Perform bilinear filtering
+ *
+ * @param src the source raster
+ * @param dst the destination raster
+ * @param dpts array of points on the destination raster
+ * @param pts array of corresponding points on the source raster
+ */
+ private void filterBilinear(Raster src, WritableRaster dst, double[] dpts,
+ double[] pts)
+ {
+ Rectangle srcbounds = src.getBounds();
+
+ Object xyarr = null;
+ Object xp1arr = null;
+ Object yp1arr = null;
+ Object xyp1arr = null;
+
+ double xy;
+ double xp1;
+ double yp1;
+ double xyp1;
+
+ double[] result = new double[src.getNumBands()];
+
+ // For all points in the destination raster, use bilinear interpolation
+ // to find the value from the corrosponding source points
+ for (int i = 0; i < dpts.length; i += 2)
+ {
+ int srcX = (int) Math.round(pts[i]) + src.getMinX();
+ int srcY = (int) Math.round(pts[i + 1]) + src.getMinY();
+
+ if (srcbounds.contains(srcX, srcY))
+ {
+ // Corner case at the bottom or right edge; use nearest neighbour
+ if (pts[i] >= src.getWidth() - 1
+ || pts[i + 1] >= src.getHeight() - 1)
+ dst.setDataElements((int) dpts[i] + dst.getMinX(),
+ (int) dpts[i + 1] + dst.getMinY(),
+ src.getDataElements(srcX, srcY, null));
+
+ // Standard case, apply the bilinear formula
+ else
+ {
+ int x = (int) Math.floor(pts[i] + src.getMinX());
+ int y = (int) Math.floor(pts[i + 1] + src.getMinY());
+ double xdiff = pts[i] + src.getMinX() - x;
+ double ydiff = pts[i + 1] + src.getMinY() - y;
+
+ // Get surrounding pixels used in interpolation... optimized
+ // to use the smallest datatype possible.
+ if (src.getTransferType() == DataBuffer.TYPE_DOUBLE
+ || src.getTransferType() == DataBuffer.TYPE_FLOAT)
+ {
+ xyarr = src.getPixel(x, y, (double[])xyarr);
+ xp1arr = src.getPixel(x+1, y, (double[])xp1arr);
+ yp1arr = src.getPixel(x, y+1, (double[])yp1arr);
+ xyp1arr = src.getPixel(x+1, y+1, (double[])xyp1arr);
+ }
+ else
+ {
+ xyarr = src.getPixel(x, y, (int[])xyarr);
+ xp1arr = src.getPixel(x+1, y, (int[])xp1arr);
+ yp1arr = src.getPixel(x, y+1, (int[])yp1arr);
+ xyp1arr = src.getPixel(x+1, y+1, (int[])xyp1arr);
+ }
+ // using
+ // array[] pixels = src.getPixels(x, y, 2, 2, pixels);
+ // instead of doing four individual src.getPixel() calls
+ // should be faster, but benchmarking shows that it's not...
+
+ // Run interpolation for each band
+ for (int j = 0; j < src.getNumBands(); j++)
+ {
+ // Pull individual sample values out of array
+ if (src.getTransferType() == DataBuffer.TYPE_DOUBLE
+ || src.getTransferType() == DataBuffer.TYPE_FLOAT)
+ {
+ xy = ((double[])xyarr)[j];
+ xp1 = ((double[])xp1arr)[j];
+ yp1 = ((double[])yp1arr)[j];
+ xyp1 = ((double[])xyp1arr)[j];
+ }
+ else
+ {
+ xy = ((int[])xyarr)[j];
+ xp1 = ((int[])xp1arr)[j];
+ yp1 = ((int[])yp1arr)[j];
+ xyp1 = ((int[])xyp1arr)[j];
+ }
+
+ // If all four samples are identical, there's no need to
+ // calculate anything
+ if (xy == xp1 && xy == yp1 && xy == xyp1)
+ result[j] = xy;
+
+ // Run bilinear interpolation formula
+ else
+ result[j] = (xy * (1-xdiff) + xp1 * xdiff)
+ * (1-ydiff)
+ + (yp1 * (1-xdiff) + xyp1 * xdiff)
+ * ydiff;
+ }
+
+ dst.setPixel((int)dpts[i] + dst.getMinX(),
+ (int)dpts[i+1] + dst.getMinY(),
+ result);
+ }
+ }
+ }
+ }
+
+ /**
+ * Perform bicubic filtering
+ * based on http://local.wasp.uwa.edu.au/~pbourke/colour/bicubic/
+ *
+ * @param src the source raster
+ * @param dst the destination raster
+ * @param dpts array of points on the destination raster
+ * @param pts array of corresponding points on the source raster
+ */
+ private void filterBicubic(Raster src, WritableRaster dst, double[] dpts,
+ double[] pts)
+ {
+ Rectangle srcbounds = src.getBounds();
+ double[] result = new double[src.getNumBands()];
+ Object pixels = null;
+
+ // For all points on the destination raster, perform bicubic interpolation
+ // from corrosponding source points
+ for (int i = 0; i < dpts.length; i += 2)
+ {
+ if (srcbounds.contains((int) Math.round(pts[i]) + src.getMinX(),
+ (int) Math.round(pts[i + 1]) + src.getMinY()))
+ {
+ int x = (int) Math.floor(pts[i] + src.getMinX());
+ int y = (int) Math.floor(pts[i + 1] + src.getMinY());
+ double dx = pts[i] + src.getMinX() - x;
+ double dy = pts[i + 1] + src.getMinY() - y;
+ Arrays.fill(result, 0);
+
+ for (int m = - 1; m < 3; m++)
+ for (int n = - 1; n < 3; n++)
+ {
+ // R(x) = ( P(x+2)^3 - 4 P(x+1)^3 + 6 P(x)^3 - 4 P(x-1)^3 ) / 6
+ double r1 = 0;
+ double r2 = 0;
+
+ // Calculate R(m - dx)
+ double rx = m - dx + 2;
+ r1 += rx * rx * rx;
+
+ rx = m - dx + 1;
+ if (rx > 0)
+ r1 -= 4 * rx * rx * rx;
+
+ rx = m - dx;
+ if (rx > 0)
+ r1 += 6 * rx * rx * rx;
+
+ rx = m - dx - 1;
+ if (rx > 0)
+ r1 -= 4 * rx * rx * rx;
+
+ r1 /= 6;
+
+ // Calculate R(dy - n);
+ rx = dy - n + 2;
+ if (rx > 0)
+ r2 += rx * rx * rx;
+
+ rx = dy - n + 1;
+ if (rx > 0)
+ r2 -= 4 * rx * rx * rx;
+
+ rx = dy - n;
+ if (rx > 0)
+ r2 += 6 * rx * rx * rx;
+
+ rx = dy - n - 1;
+ if (rx > 0)
+ r2 -= 4 * rx * rx * rx;
+
+ r2 /= 6;
+
+ // Calculate F(i+m, j+n) R(m - dx) R(dy - n)
+ // Check corner cases
+ int srcX = x + m;
+ if (srcX >= src.getMinX() + src.getWidth())
+ srcX = src.getMinX() + src.getWidth() - 1;
+ else if (srcX < src.getMinX())
+ srcX = src.getMinX();
+
+ int srcY = y + n;
+ if (srcY >= src.getMinY() + src.getHeight())
+ srcY = src.getMinY() + src.getHeight() - 1;
+ else if (srcY < src.getMinY())
+ srcY = src.getMinY();
+
+ // Calculate once for each band, using the smallest
+ // datatype possible
+ if (src.getTransferType() == DataBuffer.TYPE_DOUBLE
+ || src.getTransferType() == DataBuffer.TYPE_FLOAT)
+ {
+ pixels = src.getPixel(srcX, srcY, (double[])pixels);
+ for (int j = 0; j < result.length; j++)
+ result[j] += ((double[])pixels)[j] * r1 * r2;
+ }
+ else
+ {
+ pixels = src.getPixel(srcX, srcY, (int[])pixels);
+ for (int j = 0; j < result.length; j++)
+ result[j] += ((int[])pixels)[j] * r1 * r2;
+ }
+ }
+
+ // Put it all together
+ dst.setPixel((int)dpts[i] + dst.getMinX(),
+ (int)dpts[i+1] + dst.getMinY(),
+ result);
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/java/awt/image/AreaAveragingScaleFilter.java b/libjava/classpath/java/awt/image/AreaAveragingScaleFilter.java
new file mode 100644
index 000000000..db2335f1c
--- /dev/null
+++ b/libjava/classpath/java/awt/image/AreaAveragingScaleFilter.java
@@ -0,0 +1,268 @@
+/* AreaAveragingScaleFilter.java -- Java class for filtering images
+ Copyright (C) 1999,2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+/**
+ * This filter should produce images which do not have image artifacts
+ * like broken lines which were originally unbroken. The cost is of
+ * course speed. Using bi-linear interpolation here against 4 pixel
+ * points should give the desired results although Sun does not
+ * specify what the exact algorithm should be.
+ * <br>
+ *
+ * @author C. Brian Jones (cbj@gnu.org)
+ */
+public class AreaAveragingScaleFilter extends ReplicateScaleFilter
+{
+ /**
+ * Construct an instance of <code>AreaAveragingScaleFilter</code> which
+ * should be used in conjunction with a <code>FilteredImageSource</code>
+ * object.
+ *
+ * @param width the width of the destination image
+ * @param height the height of the destination image
+ */
+ public AreaAveragingScaleFilter(int width, int height) {
+ super(width, height);
+ }
+
+ /**
+ * The <code>ImageProducer</code> should call this method with a
+ * bit mask of hints from any of <code>RANDOMPIXELORDER</code>,
+ * <code>TOPDOWNLEFTRIGHT</code>, <code>COMPLETESCANLINES</code>,
+ * <code>SINGLEPASS</code>, <code>SINGLEFRAME</code> from the
+ * <code>ImageConsumer</code> interface.
+ * <br>
+ * FIXME - more than likely Sun's implementation desires
+ * <code>TOPDOWNLEFTRIGHT</code> order and this method is overloaded here
+ * in order to assure that mask is part of the hints added to
+ * the consumer.
+ *
+ * @param flags a bit mask of hints
+ * @see ImageConsumer
+ */
+ public void setHints(int flags)
+ {
+ if (consumer != null)
+ consumer.setHints(flags);
+ }
+
+ /**
+ * This function delivers a rectangle of pixels where any
+ * pixel(m,n) is stored in the array as a <code>byte</code> at
+ * index (n * scansize + m + offset).
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param model the <code>ColorModel</code> used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the <code>pixels</code> array
+ * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
+ */
+ public void setPixels(int x, int y, int w, int h,
+ ColorModel model, byte[] pixels, int offset, int scansize)
+ {
+ double rx = ((double) srcWidth) / destWidth;
+ double ry = ((double) srcHeight) / destHeight;
+
+ int destScansize = (int) Math.round(scansize / rx);
+
+ byte[] destPixels = averagePixels(x, y, w, h,
+ model, pixels, offset, scansize,
+ rx, ry, destScansize);
+
+ if (consumer != null)
+ consumer.setPixels((int) Math.floor(x/rx), (int) Math.floor(y/ry),
+ (int) Math.ceil(w/rx), (int) Math.ceil(h/ry),
+ model, destPixels, 0, destScansize);
+ }
+
+ /**
+ * This function delivers a rectangle of pixels where any
+ * pixel(m,n) is stored in the array as an <code>int</code> at
+ * index (n * scansize + m + offset).
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param model the <code>ColorModel</code> used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the <code>pixels</code> array
+ * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
+ */
+ public void setPixels(int x, int y, int w, int h,
+ ColorModel model, int[] pixels, int offset, int scansize)
+ {
+ double rx = ((double) srcWidth) / destWidth;
+ double ry = ((double) srcHeight) / destHeight;
+
+ int destScansize = (int) Math.round(scansize / rx);
+
+ int[] destPixels = averagePixels(x, y, w, h,
+ model, pixels, offset, scansize,
+ rx, ry, destScansize);
+
+ if (consumer != null)
+ consumer.setPixels((int) Math.floor(x/rx), (int) Math.floor(y/ry),
+ (int) Math.ceil(w/rx), (int) Math.ceil(h/ry),
+ model, destPixels, 0, destScansize);
+ }
+
+ /**
+ * This is a really terrible implementation,
+ * since it uses the nearest-neighbor method. This filter is rarely used though.
+ *
+ * @param srcx, srcy - Source rectangle upper-left corner
+ * @param srcw, srch - Source rectangle width and height
+ * @param model - Pixel color model
+ * @param srcPixels - Source pixel data.
+ * @param srcOffset - Starting offset into the source pixel data array.
+ * @param srcScansize - Source array scanline size.
+ * @param rx,ry - Scaling factor.
+ * @param destScansize - Destination array scanline size.
+ */
+ private byte[] averagePixels(int srcx, int srcy, int srcw, int srch,
+ ColorModel model, byte[] srcPixels,
+ int srcOffset, int srcScansize,
+ double rx, double ry, int destScansize)
+ {
+ int destW = (int) Math.ceil(srcw/rx);
+ int destH = (int) Math.ceil(srch/ry);
+ byte[] destPixels = new byte[ destW * destH ];
+ int sx, sy;
+
+ int w = (int)Math.ceil(rx);
+ int h = (int)Math.ceil(ry);
+
+ for(int x = 0; x < destW; x++)
+ for(int y = 0; y < destH; y++)
+ {
+ sx = (int) (x * rx);
+ sy = (int) (y * ry);
+
+ int r,g,b,a;
+ r = g = b = a = 0;
+
+ for(int i = 0; i < w; i++)
+ {
+ for(int j = 0; j < h; j++)
+ {
+ int idx = srcx + sx + i + (srcy + sy + j)*srcScansize;
+ r += model.getRed(srcPixels[ idx ]);
+ g += model.getGreen(srcPixels[ idx ]);
+ b += model.getBlue(srcPixels[ idx ]);
+ a += model.getAlpha(srcPixels[ idx ]);
+ }
+ }
+
+ r = r / (w * h);
+ g = g / (w * h);
+ b = b / (w * h);
+ a = a / (w * h);
+
+ // Does this really work?
+ destPixels[x + destScansize*y] = (byte)model.getDataElement
+ (new int[]{r, g, b, a}, 0);
+ }
+
+ return destPixels;
+ }
+
+ /**
+ * This is a really terrible implementation,
+ * since it uses the nearest-neighbor method. This filter is rarely used though.
+ *
+ * @param srcx, srcy - Source rectangle upper-left corner
+ * @param srcw, srch - Source rectangle width and height
+ * @param model - Pixel color model
+ * @param srcPixels - Source pixel data.
+ * @param srcOffset - Starting offset into the source pixel data array.
+ * @param srcScansize - Source array scanline size.
+ * @param rx,ry - Scaling factor.
+ * @param destScansize - Destination array scanline size.
+ */
+ private int[] averagePixels(int srcx, int srcy, int srcw, int srch,
+ ColorModel model, int[] srcPixels,
+ int srcOffset, int srcScansize,
+ double rx, double ry, int destScansize)
+ {
+ int destW = (int) Math.ceil(srcw/rx);
+ int destH = (int) Math.ceil(srch/ry);
+ int[] destPixels = new int[ destW * destH ];
+ int sx, sy;
+
+ int w = (int)Math.ceil(rx);
+ int h = (int)Math.ceil(ry);
+
+ for(int x = 0; x < destW; x++)
+ for(int y = 0; y < destH; y++)
+ {
+ sx = (int) (x * rx);
+ sy = (int) (y * ry);
+
+ int r,g,b,a;
+ r = g = b = a = 0;
+
+ for(int i = 0; i < w; i++)
+ {
+ for(int j = 0; j < h; j++)
+ {
+ int idx = srcx + sx + i + (srcy + sy + j)*srcScansize;
+ r += model.getRed(srcPixels[ idx ]);
+ g += model.getGreen(srcPixels[ idx ]);
+ b += model.getBlue(srcPixels[ idx ]);
+ a += model.getAlpha(srcPixels[ idx ]);
+ }
+ }
+
+ r = r / (w * h);
+ g = g / (w * h);
+ b = b / (w * h);
+ a = a / (w * h);
+
+ destPixels[x + destScansize*y] = model.getDataElement
+ (new int[]{r, g, b, a}, 0);
+ }
+
+ return destPixels;
+ }
+}
diff --git a/libjava/classpath/java/awt/image/BandCombineOp.java b/libjava/classpath/java/awt/image/BandCombineOp.java
new file mode 100644
index 000000000..f3a6c5756
--- /dev/null
+++ b/libjava/classpath/java/awt/image/BandCombineOp.java
@@ -0,0 +1,218 @@
+/* BandCombineOp.java - perform a combination on the bands of a raster
+ Copyright (C) 2004, 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+import java.awt.RenderingHints;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.Arrays;
+
+/**
+ * Filter Raster pixels by applying a matrix.
+ *
+ * BandCombineOp applies a matrix to each pixel to produce new pixel values.
+ * The width of the matrix must be the same or one more than the number of
+ * bands in the source Raster. If one more, the pixels in the source are
+ * assumed to contain an implicit 1.0 at the end.
+ *
+ * The rows of the matrix are multiplied by the pixel to produce the values
+ * for the destination. Therefore the destination Raster must contain the
+ * same number of bands as the number of rows in the filter matrix.
+ *
+ * This Op assumes that samples are integers; floating point sample types will
+ * be rounded to their nearest integer value during filtering.
+ *
+ * @author Jerry Quinn (jlquinn@optonline.net)
+ */
+public class BandCombineOp implements RasterOp
+{
+ private RenderingHints hints;
+ private float[][] matrix;
+
+ /**
+ * Construct a BandCombineOp.
+ *
+ * @param matrix The matrix to filter pixels with.
+ * @param hints Rendering hints to apply. Ignored.
+ * @throws ArrayIndexOutOfBoundsException if the matrix is invalid
+ */
+ public BandCombineOp(float[][] matrix, RenderingHints hints)
+ {
+ this.matrix = new float[matrix.length][];
+ int width = matrix[0].length;
+ for (int i = 0; i < matrix.length; i++)
+ {
+ this.matrix[i] = new float[width + 1];
+ for (int j = 0; j < width; j++)
+ this.matrix[i][j] = matrix[i][j];
+
+ // The reference implementation pads the array with a trailing zero...
+ this.matrix[i][width] = 0;
+ }
+
+ this.hints = hints;
+ }
+
+ /**
+ * Filter Raster pixels through a matrix. Applies the Op matrix to source
+ * pixes to produce dest pixels. Each row of the matrix is multiplied by the
+ * src pixel components to produce the dest pixel. If matrix is one more than
+ * the number of bands in the src, the last element is implicitly multiplied
+ * by 1, i.e. added to the sum for that dest component. If dest is null, a
+ * suitable Raster is created. This implementation uses
+ * createCompatibleDestRaster.
+ *
+ * @param src The source Raster.
+ * @param dest The destination Raster, or null.
+ * @throws IllegalArgumentException if the destination raster is incompatible
+ * with the source raster.
+ * @return The filtered Raster.
+ * @see java.awt.image.RasterOp#filter(java.awt.image.Raster,
+ * java.awt.image.WritableRaster)
+ */
+ public WritableRaster filter(Raster src, WritableRaster dest) {
+ if (dest == null)
+ dest = createCompatibleDestRaster(src);
+ else if (dest.getNumBands() != src.getNumBands()
+ || dest.getTransferType() != src.getTransferType())
+ throw new IllegalArgumentException("Destination raster is incompatible with source raster");
+
+ // Filter the pixels
+ int[] spix = new int[matrix[0].length - 1];
+ int[] spix2 = new int[matrix[0].length - 1];
+ int[] dpix = new int[matrix.length];
+ for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
+ for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
+ {
+ // In case matrix rows have implicit translation
+ spix[spix.length - 1] = 1;
+ src.getPixel(x, y, spix);
+
+ // Do not re-calculate if pixel is identical to the last one
+ // (ie, blocks of the same colour)
+ if (!Arrays.equals(spix, spix2))
+ {
+ System.arraycopy(spix, 0, spix2, 0, spix.length);
+ for (int i = 0; i < matrix.length; i++)
+ {
+ dpix[i] = 0;
+ for (int j = 0; j < matrix[0].length - 1; j++)
+ dpix[i] += spix[j] * (int)matrix[i][j];
+ }
+ }
+ dest.setPixel(x, y, dpix);
+ }
+
+ return dest;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#getBounds2D(java.awt.image.Raster)
+ */
+ public final Rectangle2D getBounds2D(Raster src)
+ {
+ return src.getBounds();
+ }
+
+ /**
+ * Creates a new WritableRaster that can be used as the destination for this
+ * Op. The number of bands in the source raster must equal the number of rows
+ * in the op matrix, which must also be equal to either the number of columns
+ * or (columns - 1) in the matrix.
+ *
+ * @param src The source raster.
+ * @return A compatible raster.
+ * @see java.awt.image.RasterOp#createCompatibleDestRaster(java.awt.image.Raster)
+ * @throws IllegalArgumentException if the raster is incompatible with the
+ * matrix.
+ */
+ public WritableRaster createCompatibleDestRaster(Raster src)
+ {
+ // Destination raster must have same number of bands as source
+ if (src.getNumBands() != matrix.length)
+ throw new IllegalArgumentException("Number of rows in matrix specifies an "
+ + "incompatible number of bands");
+
+ // We use -1 and -2 because we previously padded the rows with a trailing 0
+ if (src.getNumBands() != matrix[0].length - 1
+ && src.getNumBands() != matrix[0].length - 2)
+ throw new IllegalArgumentException("Incompatible number of bands: "
+ + "the number of bands in the raster must equal the number of "
+ + "columns in the matrix, optionally minus one");
+
+ return src.createCompatibleWritableRaster();
+ }
+
+ /**
+ * Return corresponding destination point for source point. Because this is
+ * not a geometric operation, it simply returns a copy of the source.
+ *
+ * @param src The source point.
+ * @param dst The destination point.
+ * @return dst The destination point.
+ * @see java.awt.image.RasterOp#getPoint2D(java.awt.geom.Point2D,
+ *java.awt.geom.Point2D)
+ */
+ public final Point2D getPoint2D(Point2D src, Point2D dst)
+ {
+ if (dst == null)
+ return (Point2D)src.clone();
+
+ dst.setLocation(src);
+ return dst;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#getRenderingHints()
+ */
+ public final RenderingHints getRenderingHints()
+ {
+ return hints;
+ }
+
+ /**
+ * Return the matrix used in this operation.
+ *
+ * @return The matrix used in this operation.
+ */
+ public final float[][] getMatrix()
+ {
+ return matrix;
+ }
+
+}
diff --git a/libjava/classpath/java/awt/image/BandedSampleModel.java b/libjava/classpath/java/awt/image/BandedSampleModel.java
new file mode 100644
index 000000000..7df6c8548
--- /dev/null
+++ b/libjava/classpath/java/awt/image/BandedSampleModel.java
@@ -0,0 +1,759 @@
+/* Copyright (C) 2004, 2005, 2006, Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+import gnu.java.awt.Buffers;
+import gnu.java.lang.CPStringBuilder;
+
+/**
+ * A sample model that reads each sample value from a separate band in the
+ * {@link DataBuffer}.
+ *
+ * @author Jerry Quinn (jlquinn@optonline.net)
+ */
+public final class BandedSampleModel extends ComponentSampleModel
+{
+ private int[] bitMasks;
+ private int[] bitOffsets;
+ private int[] sampleSize;
+ private int dataBitOffset;
+ private int elemBits;
+ private int numberOfBits;
+ private int numElems;
+
+ private static int[] createBankArray(int size)
+ {
+ int[] result = new int[size];
+ for (int i = 0; i < size; i++)
+ result[i] = i;
+ return result;
+ }
+
+ /**
+ * Creates a new <code>BandedSampleModel</code>.
+ *
+ * @param dataType the data buffer type.
+ * @param w the width (in pixels).
+ * @param h the height (in pixels).
+ * @param numBands the number of bands.
+ */
+ public BandedSampleModel(int dataType, int w, int h, int numBands)
+ {
+ this(dataType, w, h, w, createBankArray(numBands), new int[numBands]);
+ }
+
+ /**
+ * Creates a new <code>BandedSampleModel</code>.
+ *
+ * @param dataType the data buffer type.
+ * @param w the width (in pixels).
+ * @param h the height (in pixels).
+ * @param scanlineStride the number of data elements from a pixel in one
+ * row to the corresponding pixel in the next row.
+ * @param bankIndices the bank indices.
+ * @param bandOffsets the band offsets.
+ */
+ public BandedSampleModel(int dataType, int w, int h, int scanlineStride,
+ int[] bankIndices, int[] bandOffsets)
+ {
+ super(dataType, w, h, 1, scanlineStride, bankIndices, bandOffsets);
+ }
+
+ /**
+ * Creates a new data buffer that is compatible with this sample model.
+ *
+ * @return The new data buffer.
+ */
+ public DataBuffer createDataBuffer()
+ {
+ int size = scanlineStride * height;
+ return Buffers.createBuffer(getDataType(), size, numBanks);
+ }
+
+ /**
+ * Creates a new <code>SampleModel</code> that is compatible with this
+ * model and has the specified width and height.
+ *
+ * @param w the width (in pixels, must be greater than zero).
+ * @param h the height (in pixels, must be greater than zero).
+ *
+ * @return The new sample model.
+ *
+ * @throws IllegalArgumentException if <code>w</code> or <code>h</code> is
+ * not greater than zero.
+ * @throws IllegalArgumentException if <code>w * h</code> exceeds
+ * <code>Integer.MAX_VALUE</code>.
+ */
+ public SampleModel createCompatibleSampleModel(int w, int h)
+ {
+ // NOTE: blackdown 1.4.1 sets all offsets to 0. Sun's 1.4.2 docs
+ // disagree.
+
+ // Compress offsets so minimum is 0, others w*scanlineStride
+ int[] newoffsets = new int[bandOffsets.length];
+ int[] order = new int[bandOffsets.length];
+ for (int i = 0; i < bandOffsets.length; i++)
+ order[i] = i;
+ // FIXME: This is N^2, but not a big issue, unless there's a lot of
+ // bands...
+ for (int i = 0; i < bandOffsets.length; i++)
+ for (int j = i + 1; j < bandOffsets.length; j++)
+ if (bankIndices[order[i]] > bankIndices[order[j]]
+ || (bankIndices[order[i]] == bankIndices[order[j]]
+ && bandOffsets[order[i]] > bandOffsets[order[j]]))
+ {
+ int t = order[i]; order[i] = order[j]; order[j] = t;
+ }
+ int bank = 0;
+ int offset = 0;
+ for (int i = 0; i < bandOffsets.length; i++)
+ {
+ if (bankIndices[order[i]] != bank)
+ {
+ bank = bankIndices[order[i]];
+ offset = 0;
+ }
+ newoffsets[order[i]] = offset;
+ offset += w * scanlineStride;
+ }
+
+ return new BandedSampleModel(dataType, w, h, w, bankIndices, newoffsets);
+ }
+
+
+ public SampleModel createSubsetSampleModel(int[] bands)
+ {
+ if (bands.length > bankIndices.length)
+ throw new
+ RasterFormatException("BandedSampleModel createSubsetSampleModel too"
+ +" many bands");
+ int[] newoff = new int[bands.length];
+ int[] newbanks = new int[bands.length];
+ for (int i = 0; i < bands.length; i++)
+ {
+ int b = bands[i];
+ newoff[i] = bandOffsets[b];
+ newbanks[i] = bankIndices[b];
+ }
+
+ return new BandedSampleModel(dataType, width, height, scanlineStride,
+ newbanks, newoff);
+ }
+
+ /**
+ * Extract all samples of one pixel and return in an array of transfer type.
+ *
+ * Extracts the pixel at x, y from data and stores samples into the array
+ * obj. If obj is null, a new array of getTransferType() is created.
+ *
+ * @param x The x-coordinate of the pixel rectangle to store in
+ * <code>obj</code>.
+ * @param y The y-coordinate of the pixel rectangle to store in
+ * <code>obj</code>.
+ * @param obj The primitive array to store the pixels into or null to force
+ * creation.
+ * @param data The DataBuffer that is the source of the pixel data.
+ * @return The primitive array containing the pixel data.
+ * @see java.awt.image.SampleModel#getDataElements(int, int,
+ * java.lang.Object, java.awt.image.DataBuffer)
+ */
+ public Object getDataElements(int x, int y, Object obj, DataBuffer data)
+ {
+ if (x < 0 || y < 0)
+ throw new ArrayIndexOutOfBoundsException(
+ "x and y must not be less than 0.");
+ int pixel = getSample(x, y, 0, data);
+ switch (getTransferType())
+ {
+ case DataBuffer.TYPE_BYTE:
+ {
+ byte[] b = (byte[]) obj;
+ if (b == null) b = new byte[numBands];
+ for (int i = 0; i < numBands; i++)
+ b[i] = (byte)getSample(x, y, i, data);
+ return b;
+ }
+ case DataBuffer.TYPE_SHORT:
+ case DataBuffer.TYPE_USHORT:
+ {
+ short[] b = (short[]) obj;
+ if (b == null) b = new short[numBands];
+ for (int i = 0; i < numBands; i++)
+ b[i] = (short)getSample(x, y, i, data);
+ return b;
+ }
+ case DataBuffer.TYPE_INT:
+ {
+ int[] b = (int[]) obj;
+ if (b == null) b = new int[numBands];
+ for (int i = 0; i < numBands; i++)
+ b[i] = getSample(x, y, i, data);
+ return b;
+ }
+ case DataBuffer.TYPE_FLOAT:
+ {
+ float[] b = (float[]) obj;
+ if (b == null) b = new float[numBands];
+ for (int i = 0; i < numBands; i++)
+ b[i] = getSampleFloat(x, y, i, data);
+ return b;
+ }
+ case DataBuffer.TYPE_DOUBLE:
+ {
+ double[] b = (double[]) obj;
+ if (b == null)
+ b = new double[numBands];
+ for (int i = 0; i < numBands; i++)
+ b[i] = getSample(x, y, i, data);
+ return b;
+ }
+
+ default:
+ // Seems like the only sensible thing to do.
+ throw new ClassCastException();
+ }
+ }
+
+ /**
+ * Returns all the samples for the pixel at location <code>(x, y)</code>
+ * stored in the specified data buffer.
+ *
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ * @param iArray an array that will be populated with the sample values and
+ * returned as the result. The size of this array should be equal to the
+ * number of bands in the model. If the array is <code>null</code>, a new
+ * array is created.
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The samples for the specified pixel.
+ *
+ * @see #setPixel(int, int, int[], DataBuffer)
+ */
+ public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
+ {
+ if (iArray == null)
+ iArray = new int[numBands];
+ for (int i = 0; i < numBands; i++)
+ iArray[i] = getSample(x, y, i, data);
+
+ return iArray;
+ }
+
+ /**
+ * Copy pixels from a region into an array.
+ *
+ * Copies the samples of the pixels in the rectangle starting at x, y that
+ * is w pixels wide and h scanlines high. When there is more than one band,
+ * the samples stored in order before the next pixel. This ordering isn't
+ * well specified in Sun's docs as of 1.4.2.
+ *
+ * If iArray is null, a new array is allocated, filled, and returned.
+ *
+ * @param x The x-coordinate of the pixel rectangle to store in
+ * <code>iArray</code>.
+ * @param y The y-coordinate of the pixel rectangle to store in
+ * <code>iArray</code>.
+ * @param w The width in pixels of the rectangle.
+ * @param h The height in pixels of the rectangle.
+ * @param iArray The int array to store the pixels into or null to force
+ * creation.
+ * @param data The DataBuffer that is the source of the pixel data.
+ * @return The primitive array containing the pixel data.
+ */
+ public int[] getPixels(int x, int y, int w, int h, int[] iArray,
+ DataBuffer data)
+ {
+ if (x < 0 || y < 0)
+ throw new ArrayIndexOutOfBoundsException(
+ "x and y must not be less than 0.");
+ if (iArray == null)
+ iArray = new int[w * h * numBands];
+ int outOffset = 0;
+ int maxX = x + w;
+ int maxY = y + h;
+ for (int yy = x; yy < maxY; yy++)
+ {
+ for (int xx = x; xx < maxX; xx++)
+ {
+ for (int b = 0; b < numBands; b++)
+ {
+ int offset = bandOffsets[b] + yy * scanlineStride + xx;
+ iArray[outOffset++] =
+ data.getElem(bankIndices[b], offset);
+ }
+ }
+ }
+ return iArray;
+ }
+
+ /**
+ * Returns a sample value for the pixel at (x, y) in the specified data
+ * buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The sample value.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
+ public int getSample(int x, int y, int b, DataBuffer data)
+ {
+ int offset = bandOffsets[b] + y * scanlineStride + x;
+ return data.getElem(bankIndices[b], offset);
+ }
+
+ /**
+ * Returns a sample value for the pixel at (x, y) in the specified data
+ * buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The sample value.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ *
+ * @see #getSample(int, int, int, DataBuffer)
+ */
+ public float getSampleFloat(int x, int y, int b, DataBuffer data)
+ {
+ int offset = bandOffsets[b] + y * scanlineStride + x;
+ return data.getElemFloat(bankIndices[b], offset);
+ }
+
+ /**
+ * Returns the sample value for the pixel at (x, y) in the specified data
+ * buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The sample value.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ *
+ * @see #getSample(int, int, int, DataBuffer)
+ */
+ public double getSampleDouble(int x, int y, int b, DataBuffer data)
+ {
+ int offset = bandOffsets[b] + y * scanlineStride + x;
+ return data.getElemDouble(bankIndices[b], offset);
+ }
+
+ /**
+ * Copy one band's samples from a region into an array.
+ *
+ * Copies from one band the samples of the pixels in the rectangle starting
+ * at x, y that is w pixels wide and h scanlines high.
+ *
+ * If iArray is null, a new array is allocated, filled, and returned.
+ *
+ * @param x The x-coordinate of the pixel rectangle to store in
+ * <code>iArray</code>.
+ * @param y The y-coordinate of the pixel rectangle to store in
+ * <code>iArray</code>.
+ * @param w The width in pixels of the rectangle.
+ * @param h The height in pixels of the rectangle.
+ * @param b The band to retrieve.
+ * @param iArray The int array to store the pixels into or null to force
+ * creation.
+ * @param data The DataBuffer that is the source of the pixel data.
+ * @return The primitive array containing the pixel data.
+ */
+ public int[] getSamples(int x, int y, int w, int h, int b, int[] iArray,
+ DataBuffer data)
+ {
+ if (x < 0 || y < 0)
+ throw new ArrayIndexOutOfBoundsException(
+ "x and y must not be less than 0.");
+ if (iArray == null)
+ iArray = new int[w * h];
+ int outOffset = 0;
+ int maxX = x + w;
+ int maxY = y + h;
+ for (int yy = y; yy < maxY; yy++)
+ {
+ for (int xx = x; xx < maxX; xx++)
+ {
+ int offset = bandOffsets[b] + yy * scanlineStride + xx;
+ iArray[outOffset++] =
+ data.getElem(bankIndices[b], offset);
+ }
+ }
+ return iArray;
+ }
+
+ /**
+ * Set the pixel at x, y to the value in the first element of the primitive
+ * array obj.
+ *
+ * @param x The x-coordinate of the data elements in <code>obj</code>.
+ * @param y The y-coordinate of the data elements in <code>obj</code>.
+ * @param obj The primitive array containing the data elements to set.
+ * @param data The DataBuffer to store the data elements into.
+ * @see java.awt.image.SampleModel#setDataElements(int, int, int, int, java.lang.Object, java.awt.image.DataBuffer)
+ */
+ public void setDataElements(int x, int y, Object obj, DataBuffer data)
+ {
+ int transferType = getTransferType();
+ if (getTransferType() != data.getDataType())
+ {
+ throw new IllegalArgumentException("transfer type ("+
+ getTransferType()+"), "+
+ "does not match data "+
+ "buffer type (" +
+ data.getDataType() +
+ ").");
+ }
+
+ int offset = y * scanlineStride + x;
+
+ try
+ {
+ switch (transferType)
+ {
+ case DataBuffer.TYPE_BYTE:
+ {
+ DataBufferByte out = (DataBufferByte) data;
+ byte[] in = (byte[]) obj;
+ for (int i = 0; i < numBands; i++)
+ out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
+ return;
+ }
+ case DataBuffer.TYPE_SHORT:
+ {
+ DataBufferShort out = (DataBufferShort) data;
+ short[] in = (short[]) obj;
+ for (int i = 0; i < numBands; i++)
+ out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
+ return;
+ }
+ case DataBuffer.TYPE_USHORT:
+ {
+ DataBufferUShort out = (DataBufferUShort) data;
+ short[] in = (short[]) obj;
+ for (int i = 0; i < numBands; i++)
+ out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
+ return;
+ }
+ case DataBuffer.TYPE_INT:
+ {
+ DataBufferInt out = (DataBufferInt) data;
+ int[] in = (int[]) obj;
+ for (int i = 0; i < numBands; i++)
+ out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
+ return;
+ }
+ case DataBuffer.TYPE_FLOAT:
+ {
+ DataBufferFloat out = (DataBufferFloat) data;
+ float[] in = (float[]) obj;
+ for (int i = 0; i < numBands; i++)
+ out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
+ return;
+ }
+ case DataBuffer.TYPE_DOUBLE:
+ {
+ DataBufferDouble out = (DataBufferDouble) data;
+ double[] in = (double[]) obj;
+ for (int i = 0; i < numBands; i++)
+ out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
+ return;
+ }
+ default:
+ throw new ClassCastException("Unsupported data type");
+ }
+ }
+ catch (ArrayIndexOutOfBoundsException aioobe)
+ {
+ String msg = "While writing data elements"
+ + ", x=" + x + ", y=" + y
+ + ", width=" + width + ", height=" + height
+ + ", scanlineStride=" + scanlineStride
+ + ", offset=" + offset
+ + ", data.getSize()=" + data.getSize()
+ + ", data.getOffset()=" + data.getOffset()
+ + ": " + aioobe;
+ throw new ArrayIndexOutOfBoundsException(msg);
+ }
+ }
+
+ /**
+ * Sets the samples for the pixel at (x, y) in the specified data buffer to
+ * the specified values.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param iArray the sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>iArray</code> or
+ * <code>data</code> is <code>null</code>.
+ */
+ public void setPixel(int x, int y, int[] iArray, DataBuffer data)
+ {
+ for (int b = 0; b < numBands; b++)
+ data.setElem(bankIndices[b], bandOffsets[b] + y * scanlineStride + x,
+ iArray[b]);
+ }
+
+ /**
+ * Sets the sample values for the pixels in the region specified by
+ * (x, y, w, h) in the specified data buffer. The array is
+ * ordered by pixels (that is, all the samples for the first pixel are
+ * grouped together, followed by all the samples for the second pixel, and so
+ * on).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param iArray the pixel sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>iArray</code> or
+ * <code>data</code> is <code>null</code>.
+ */
+ public void setPixels(int x, int y, int w, int h, int[] iArray,
+ DataBuffer data)
+ {
+ int inOffset = 0;
+ for (int hh = 0; hh < h; hh++)
+ {
+ for (int ww = 0; ww < w; ww++)
+ {
+ int offset = y * scanlineStride + (x + ww);
+ for (int b = 0; b < numBands; b++)
+ data.setElem(bankIndices[b], bandOffsets[b] + offset,
+ iArray[inOffset++]);
+ }
+ y++;
+ }
+ }
+
+ /**
+ * Sets the sample value for band <code>b</code> of the pixel at location
+ * <code>(x, y)</code> in the specified data buffer.
+ *
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ * @param b the band index.
+ * @param s the sample value.
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @see #getSample(int, int, int, DataBuffer)
+ */
+ public void setSample(int x, int y, int b, int s, DataBuffer data)
+ {
+ data.setElem(bankIndices[b], bandOffsets[b] + y * scanlineStride + x, s);
+ }
+
+ /**
+ * Sets the sample value for a band for the pixel at (x, y) in the
+ * specified data buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param s the sample value.
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
+ public void setSample(int x, int y, int b, float s, DataBuffer data)
+ {
+ data.setElemFloat(bankIndices[b], bandOffsets[b] + y * scanlineStride + x,
+ s);
+ }
+
+ /**
+ * Sets the sample value for a band for the pixel at (x, y) in the
+ * specified data buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param s the sample value.
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
+ public void setSample(int x, int y, int b, double s, DataBuffer data)
+ {
+ data.setElemDouble(bankIndices[b], bandOffsets[b] + y * scanlineStride + x,
+ s);
+ }
+
+ /**
+ * Sets the sample values for one band for the pixels in the region
+ * specified by (x, y, w, h) in the specified data buffer.
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param b the band (in the range <code>0</code> to
+ * </code>getNumBands() - 1</code>).
+ * @param iArray the sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>iArray</code> or
+ * <code>data</code> is <code>null</code>.
+ */
+ public void setSamples(int x, int y, int w, int h, int b, int[] iArray,
+ DataBuffer data)
+ {
+ if (x < 0 || y < 0)
+ throw new ArrayIndexOutOfBoundsException(
+ "x and y must not be less than 0.");
+ int inOffset = 0;
+
+ switch (getTransferType())
+ {
+ case DataBuffer.TYPE_BYTE:
+ {
+ DataBufferByte out = (DataBufferByte) data;
+ byte[] bank = out.getData(bankIndices[b]);
+ for (int hh = 0; hh < h; hh++)
+ {
+ for (int ww = 0; ww < w; ww++)
+ {
+ int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
+ bank[offset] = (byte)iArray[inOffset++];
+ }
+ y++;
+ }
+ return;
+ }
+ case DataBuffer.TYPE_SHORT:
+ {
+ DataBufferShort out = (DataBufferShort) data;
+ short[] bank = out.getData(bankIndices[b]);
+ for (int hh = 0; hh < h; hh++)
+ {
+ for (int ww = 0; ww < w; ww++)
+ {
+ int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
+ bank[offset] = (short)iArray[inOffset++];
+ }
+ y++;
+ }
+ return;
+ }
+ case DataBuffer.TYPE_USHORT:
+ {
+ DataBufferShort out = (DataBufferShort) data;
+ short[] bank = out.getData(bankIndices[b]);
+ for (int hh = 0; hh < h; hh++)
+ {
+ for (int ww = 0; ww < w; ww++)
+ {
+ int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
+ bank[offset] = (short)iArray[inOffset++];
+ }
+ y++;
+ }
+ return;
+ }
+ case DataBuffer.TYPE_INT:
+ {
+ DataBufferInt out = (DataBufferInt) data;
+ int[] bank = out.getData(bankIndices[b]);
+ for (int hh = 0; hh < h; hh++)
+ {
+ for (int ww = 0; ww < w; ww++)
+ {
+ int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
+ bank[offset] = iArray[inOffset++];
+ }
+ y++;
+ }
+ return;
+ }
+ case DataBuffer.TYPE_FLOAT:
+ case DataBuffer.TYPE_DOUBLE:
+ break;
+ default:
+ throw new ClassCastException("Unsupported data type");
+ }
+
+ // Default implementation probably slower for float and double
+ for (int hh = 0; hh < h; hh++)
+ {
+ for (int ww = 0; ww < w; ww++)
+ {
+ int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
+ data.setElem(bankIndices[b], offset, iArray[inOffset++]);
+ }
+ y++;
+ }
+ }
+
+ /**
+ * Creates a String with some information about this SampleModel.
+ * @return A String describing this SampleModel.
+ * @see java.lang.Object#toString()
+ */
+ public String toString()
+ {
+ CPStringBuilder result = new CPStringBuilder();
+ result.append(getClass().getName());
+ result.append("[");
+ result.append("scanlineStride=").append(scanlineStride);
+ for(int i = 0; i < bitMasks.length; i+=1)
+ {
+ result.append(", mask[").append(i).append("]=0x").append(
+ Integer.toHexString(bitMasks[i]));
+ }
+
+ result.append("]");
+ return result.toString();
+ }
+}
diff --git a/libjava/classpath/java/awt/image/BufferStrategy.java b/libjava/classpath/java/awt/image/BufferStrategy.java
new file mode 100644
index 000000000..e86aad60f
--- /dev/null
+++ b/libjava/classpath/java/awt/image/BufferStrategy.java
@@ -0,0 +1,124 @@
+/* BufferStrategy.java -- describes image buffering resources
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.BufferCapabilities;
+import java.awt.Graphics;
+
+/**
+ * This class describes a strategy for managing image buffering
+ * resources on a Canvas or Window. A given buffer strategy may make
+ * use of hardware acceleration or take advantage of features of the
+ * native graphics system. Examples of buffering strategies are
+ * double or triple buffering using either flipping or blitting. For
+ * the details of these algorithms see BufferCapabilities.
+ *
+ * To use a buffer strategy, you retrieve it from either the current
+ * GraphicsConfiguration or from the Component on which you'd like to
+ * draw. Then you can query the strategy's capabilities to make sure
+ * they're suitable.
+ *
+ * If the strategy's capabilities are suitable, you can obtain a
+ * graphics object and use it to draw with this strategy. Drawing
+ * with a buffer strategy requires extra care, however. You'll need
+ * to manually cause the next buffer to be shown on the output device.
+ * And since buffer strategies are usually implemented with a
+ * VolatileImage, you must frequently check that the contents of the
+ * buffer are valid and that the buffer still exists.
+ *
+ * A buffer strategy is usually implemented using a VolatileImage.
+ *
+ * @see VolatileImage
+ * @since 1.4
+ */
+public abstract class BufferStrategy
+{
+ /**
+ * Creates a new buffer strategy.
+ */
+ public BufferStrategy()
+ {
+ }
+
+ /**
+ * Retrieves the capabilities of this buffer strategy.
+ *
+ * @return this buffer strategy's capabilities
+ */
+ public abstract BufferCapabilities getCapabilities();
+
+ /**
+ * Retrieves a graphics object that can be used to draw using this
+ * buffer strategy. This method may not be synchronized so be
+ * careful when calling it from multiple threads. You also must
+ * manually dispose of this graphics object.
+ *
+ * @return a graphics object that can be used to draw using this
+ * buffer strategy
+ */
+ public abstract Graphics getDrawGraphics();
+
+ /**
+ * Returns whether or not the buffer's resources have been reclaimed
+ * by the native graphics system. If the buffer resources have been
+ * lost then you'll need to obtain new resources before drawing
+ * again. For details, see the documentation for VolatileImage.
+ *
+ * @return true if the contents were lost, false otherwise
+ */
+ public abstract boolean contentsLost();
+
+ /**
+ * Returns whether or not the buffer's resources were re-created and
+ * cleared to the default background color. If the buffer's
+ * resources have recently been re-created and initialized then the
+ * buffer's image may need to be re-rendered. For details, see the
+ * documentation for VolatileImage.
+ *
+ * @return true if the contents were restored, false otherwise
+ */
+ public abstract boolean contentsRestored();
+
+ /**
+ * Applies this buffer strategy. In other words, this method brings
+ * the contents of the back or intermediate buffers to the front
+ * buffer.
+ */
+ public abstract void show();
+}
diff --git a/libjava/classpath/java/awt/image/BufferedImage.java b/libjava/classpath/java/awt/image/BufferedImage.java
new file mode 100644
index 000000000..094c71dd1
--- /dev/null
+++ b/libjava/classpath/java/awt/image/BufferedImage.java
@@ -0,0 +1,839 @@
+/* BufferedImage.java --
+ Copyright (C) 2000, 2002, 2003, 2004, 2005, 2006, Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import gnu.java.awt.Buffers;
+import gnu.java.awt.ClasspathGraphicsEnvironment;
+import gnu.java.awt.ComponentDataBlitOp;
+import gnu.java.lang.CPStringBuilder;
+
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
+import java.util.Hashtable;
+import java.util.Vector;
+
+/**
+ * A buffered image always starts at coordinates (0, 0).
+ *
+ * The buffered image is not subdivided into multiple tiles. Instead,
+ * the image consists of one large tile (0,0) with the width and
+ * height of the image. This tile is always considered to be checked
+ * out.
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public class BufferedImage extends Image
+ implements WritableRenderedImage, Transparency
+{
+ public static final int TYPE_CUSTOM = 0,
+ TYPE_INT_RGB = 1,
+ TYPE_INT_ARGB = 2,
+ TYPE_INT_ARGB_PRE = 3,
+ TYPE_INT_BGR = 4,
+ TYPE_3BYTE_BGR = 5,
+ TYPE_4BYTE_ABGR = 6,
+ TYPE_4BYTE_ABGR_PRE = 7,
+ TYPE_USHORT_565_RGB = 8,
+ TYPE_USHORT_555_RGB = 9,
+ TYPE_BYTE_GRAY = 10,
+ TYPE_USHORT_GRAY = 11,
+ TYPE_BYTE_BINARY = 12,
+ TYPE_BYTE_INDEXED = 13;
+
+ /**
+ * Vector of TileObservers (or null)
+ */
+ Vector<TileObserver> tileObservers;
+
+ /**
+ * The image's WritableRaster
+ */
+ WritableRaster raster;
+
+ /**
+ * The associated ColorModel
+ */
+ ColorModel colorModel;
+
+ /**
+ * The image's properties (or null)
+ */
+ Hashtable properties;
+
+ /**
+ * Whether alpha is premultiplied
+ */
+ boolean isPremultiplied;
+
+ /**
+ * The predefined type, if any.
+ */
+ int type;
+
+ /**
+ * Creates a new <code>BufferedImage</code> with the specified width, height
+ * and type. Valid <code>type</code> values are:
+ *
+ * <ul>
+ * <li>{@link #TYPE_INT_RGB}</li>
+ * <li>{@link #TYPE_INT_ARGB}</li>
+ * <li>{@link #TYPE_INT_ARGB_PRE}</li>
+ * <li>{@link #TYPE_INT_BGR}</li>
+ * <li>{@link #TYPE_3BYTE_BGR}</li>
+ * <li>{@link #TYPE_4BYTE_ABGR}</li>
+ * <li>{@link #TYPE_4BYTE_ABGR_PRE}</li>
+ * <li>{@link #TYPE_USHORT_565_RGB}</li>
+ * <li>{@link #TYPE_USHORT_555_RGB}</li>
+ * <li>{@link #TYPE_BYTE_GRAY}</li>
+ * <li>{@link #TYPE_USHORT_GRAY}</li>
+ * <li>{@link #TYPE_BYTE_BINARY}</li>
+ * <li>{@link #TYPE_BYTE_INDEXED}</li>
+ * </ul>
+ *
+ * @param width the width (must be > 0).
+ * @param height the height (must be > 0).
+ * @param type the image type (see the list of valid types above).
+ *
+ * @throws IllegalArgumentException if <code>width</code> or
+ * <code>height</code> is less than or equal to zero.
+ * @throws IllegalArgumentException if <code>type</code> is not one of the
+ * specified values.
+ */
+ public BufferedImage(int width, int height, int type)
+ {
+ SampleModel sm = null;
+ ColorModel cm = null;
+ boolean premultiplied = (type == BufferedImage.TYPE_INT_ARGB_PRE
+ || type == BufferedImage.TYPE_4BYTE_ABGR_PRE);
+
+ switch( type )
+ {
+ case BufferedImage.TYPE_INT_RGB:
+ sm = new SinglePixelPackedSampleModel( DataBuffer.TYPE_INT,
+ width, height,
+ new int[]{ 0x00FF0000,
+ 0x0000FF00,
+ 0x000000FF } ) ;
+ cm = new DirectColorModel( 24, 0xff0000, 0xff00, 0xff );
+ break;
+
+ case BufferedImage.TYPE_3BYTE_BGR:
+ sm = new PixelInterleavedSampleModel( DataBuffer.TYPE_BYTE,
+ width, height,
+ 3, width * 3,
+ new int[]{ 2, 1, 0 } );
+ cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ false, false,
+ BufferedImage.OPAQUE,
+ DataBuffer.TYPE_BYTE);
+ break;
+
+ case BufferedImage.TYPE_INT_ARGB:
+ case BufferedImage.TYPE_INT_ARGB_PRE:
+ sm = new SinglePixelPackedSampleModel( DataBuffer.TYPE_INT,
+ width, height,
+ new int[]{ 0x00FF0000,
+ 0x0000FF00,
+ 0x000000FF,
+ 0xFF000000 } );
+ if (premultiplied)
+ cm = new DirectColorModel( ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ 32, 0xff0000, 0xff00, 0xff, 0xff000000,
+ true,
+ Buffers.smallestAppropriateTransferType(32));
+ else
+ cm = new DirectColorModel( 32, 0xff0000, 0xff00, 0xff, 0xff000000 );
+
+ break;
+
+ case BufferedImage.TYPE_4BYTE_ABGR:
+ case BufferedImage.TYPE_4BYTE_ABGR_PRE:
+ sm = new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE,
+ width, height,
+ 4, 4*width,
+ new int[]{3, 2, 1, 0});
+ cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ true, premultiplied,
+ BufferedImage.TRANSLUCENT,
+ DataBuffer.TYPE_BYTE);
+ break;
+
+ case BufferedImage.TYPE_INT_BGR:
+ sm = new SinglePixelPackedSampleModel( DataBuffer.TYPE_INT,
+ width, height,
+ new int[]{ 0x000000FF,
+ 0x0000FF00,
+ 0x00FF0000 } ) ;
+ cm = new DirectColorModel( 24, 0xff, 0xff00, 0xff0000 );
+ break;
+
+ case BufferedImage.TYPE_USHORT_565_RGB:
+ sm = new SinglePixelPackedSampleModel( DataBuffer.TYPE_USHORT,
+ width, height,
+ new int[]{ 0xF800,
+ 0x7E0,
+ 0x1F } ) ;
+ cm = new DirectColorModel( 16, 0xF800, 0x7E0, 0x1F );
+ break;
+
+ case BufferedImage.TYPE_USHORT_555_RGB:
+ sm = new SinglePixelPackedSampleModel( DataBuffer.TYPE_USHORT,
+ width, height,
+ new int[]{ 0x7C00,
+ 0x3E0,
+ 0x1F } ) ;
+ cm = new DirectColorModel( 15, 0x7C00, 0x3E0, 0x1F );
+ break;
+
+ case BufferedImage.TYPE_BYTE_INDEXED:
+ cm = createDefaultIndexedColorModel( false );
+
+ case BufferedImage.TYPE_BYTE_GRAY:
+ sm = new PixelInterleavedSampleModel( DataBuffer.TYPE_BYTE,
+ width, height,
+ 1, width, new int[]{ 0 } );
+ break;
+
+ case BufferedImage.TYPE_USHORT_GRAY:
+ sm = new PixelInterleavedSampleModel( DataBuffer.TYPE_USHORT,
+ width, height,
+ 1, width, new int[]{ 0 } );
+ break;
+
+ case BufferedImage.TYPE_BYTE_BINARY:
+ cm = createDefaultIndexedColorModel( true );
+ sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE,
+ width, height, 1);
+ break;
+
+ default:
+ sm = null;
+ }
+
+ if( sm == null )
+ throw new IllegalArgumentException("Unknown predefined image type.");
+
+ if( cm == null ) // only for the grayscale types
+ {
+ int buftype;
+ int[] bits = new int[1];
+ if( type == BufferedImage.TYPE_BYTE_GRAY )
+ {
+ buftype = DataBuffer.TYPE_BYTE;
+ bits[0] = 8;
+ }
+ else
+ {
+ buftype = DataBuffer.TYPE_USHORT;
+ bits[0] = 16;
+ }
+ ColorSpace graySpace = ColorSpace.getInstance( ColorSpace.CS_GRAY );
+
+ cm = new ComponentColorModel( graySpace, bits, false, false,
+ Transparency.OPAQUE, buftype );
+ }
+
+ WritableRaster rst = null;
+
+ // Attempt to create an accelerated backend for this image
+ GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ if (env instanceof ClasspathGraphicsEnvironment)
+ rst = ((ClasspathGraphicsEnvironment)env).createRaster(cm, sm);
+
+ // Default to a standard Java raster & databuffer if needed
+ if (rst == null)
+ rst = Raster.createWritableRaster(sm, new Point( 0, 0 ) );
+
+ init(cm, rst, premultiplied,
+ null, // no properties
+ type );
+ }
+
+ public BufferedImage(int w, int h, int type, IndexColorModel indexcolormodel)
+ {
+ if ((type != TYPE_BYTE_BINARY) && (type != TYPE_BYTE_INDEXED))
+ throw new IllegalArgumentException("Type must be TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED");
+ if( indexcolormodel.getMapSize() > 16 && type == TYPE_BYTE_BINARY )
+ throw new IllegalArgumentException("Type TYPE_BYTE_BINARY cannot have a larger than 16-color palette.");
+ if( indexcolormodel.getMapSize() > 256 )
+ throw new IllegalArgumentException("Byte type cannot have a larger than 256-color palette.");
+
+ init( indexcolormodel,
+ indexcolormodel.createCompatibleWritableRaster(w, h),
+ indexcolormodel.isAlphaPremultiplied(),
+ null, // no properties
+ type );
+ }
+
+ public BufferedImage(ColorModel colormodel, WritableRaster writableraster,
+ boolean premultiplied, Hashtable<?,?> properties)
+ {
+ init(colormodel, writableraster, premultiplied, properties, TYPE_CUSTOM);
+ }
+
+
+ private void init(ColorModel cm, WritableRaster writableraster,
+ boolean premultiplied, Hashtable properties, int type)
+ {
+ raster = writableraster;
+ colorModel = cm;
+ this.properties = properties;
+ isPremultiplied = premultiplied;
+ this.type = type;
+ }
+
+ /**
+ * Creates the default palettes for the predefined indexed color types
+ * (256-color or black-and-white)
+ *
+ * @param binary - If <code>true</code>, a black and white palette,
+ * otherwise a default 256-color palette is returned.
+ */
+ private IndexColorModel createDefaultIndexedColorModel( boolean binary )
+ {
+ if( binary )
+ {
+ byte[] t = new byte[]{ 0, (byte)255 };
+ return new IndexColorModel( 1, 2, t, t, t );
+ }
+
+ byte[] r = new byte[256];
+ byte[] g = new byte[256];
+ byte[] b = new byte[256];
+
+ int index = 0;
+ for( int i = 0; i < 6; i++ )
+ for( int j = 0; j < 6; j++ )
+ for( int k = 0; k < 6; k++ )
+ {
+ r[ index ] = (byte)(i * 51);
+ g[ index ] = (byte)(j * 51);
+ b[ index ] = (byte)(k * 51);
+ index++;
+ }
+
+ while( index < 256 )
+ {
+ r[ index ] = g[ index ] = b[ index ] =
+ (byte)(18 + (index - 216) * 6);
+ index++;
+ }
+
+ return new IndexColorModel( 8, 256, r, g, b );
+ }
+
+ public void coerceData(boolean premultiplied)
+ {
+ colorModel = colorModel.coerceData(raster, premultiplied);
+ isPremultiplied = premultiplied;
+ }
+
+ public WritableRaster copyData(WritableRaster dest)
+ {
+ if (dest == null)
+ dest = raster.createCompatibleWritableRaster(getMinX(), getMinY(),
+ getWidth(),getHeight());
+
+ int x = dest.getMinX();
+ int y = dest.getMinY();
+ int w = dest.getWidth();
+ int h = dest.getHeight();
+
+ // create a src child that has the right bounds...
+ WritableRaster src =
+ raster.createWritableChild(x, y, w, h, x, y,
+ null); // same bands
+
+ if (src.getSampleModel () instanceof ComponentSampleModel
+ && dest.getSampleModel () instanceof ComponentSampleModel)
+ // Refer to ComponentDataBlitOp for optimized data blitting:
+ ComponentDataBlitOp.INSTANCE.filter(src, dest);
+
+ else
+ {
+ // slower path
+ int samples[] = src.getPixels (x, y, w, h, (int [])null);
+ dest.setPixels (x, y, w, h, samples);
+ }
+ return dest;
+ }
+
+ public Graphics2D createGraphics()
+ {
+ GraphicsEnvironment env;
+ env = GraphicsEnvironment.getLocalGraphicsEnvironment ();
+ return env.createGraphics (this);
+ }
+
+ public void flush()
+ {
+ }
+
+ public WritableRaster getAlphaRaster()
+ {
+ return colorModel.getAlphaRaster(raster);
+ }
+
+ public ColorModel getColorModel()
+ {
+ return colorModel;
+ }
+
+ public Raster getData()
+ {
+ return copyData(null);
+ /* TODO: this might be optimized by returning the same
+ raster (not writable) as long as image data doesn't change. */
+ }
+
+ public Raster getData(Rectangle rectangle)
+ {
+ WritableRaster dest =
+ raster.createCompatibleWritableRaster(rectangle);
+ return copyData(dest);
+ }
+
+ public Graphics getGraphics()
+ {
+ return createGraphics();
+ }
+
+ public int getHeight()
+ {
+ return raster.getHeight();
+ }
+
+ public int getHeight(ImageObserver imageobserver)
+ {
+ return getHeight();
+ }
+
+ public int getMinTileX()
+ {
+ return 0;
+ }
+
+ public int getMinTileY()
+ {
+ return 0;
+ }
+
+ public int getMinX()
+ {
+ return 0;
+ }
+
+ public int getMinY()
+ {
+ return 0;
+ }
+
+ public int getNumXTiles()
+ {
+ return 1;
+ }
+
+ public int getNumYTiles()
+ {
+ return 1;
+ }
+
+ /**
+ * Returns the value of the specified property, or
+ * {@link Image#UndefinedProperty} if the property is not defined.
+ *
+ * @param string the property key (<code>null</code> not permitted).
+ *
+ * @return The property value.
+ *
+ * @throws NullPointerException if <code>string</code> is <code>null</code>.
+ */
+ public Object getProperty(String string)
+ {
+ if (string == null)
+ throw new NullPointerException("The property name cannot be null.");
+ Object result = Image.UndefinedProperty;
+ if (properties != null)
+ {
+ Object v = properties.get(string);
+ if (v != null)
+ result = v;
+ }
+ return result;
+ }
+
+ public Object getProperty(String string, ImageObserver imageobserver)
+ {
+ return getProperty(string);
+ }
+
+ /**
+ * Returns <code>null</code> always.
+ *
+ * @return <code>null</code> always.
+ */
+ public String[] getPropertyNames()
+ {
+ // This method should always return null, see:
+ // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4640609
+ return null;
+ }
+
+ public int getRGB(int x, int y)
+ {
+ Object rgbElem = raster.getDataElements(x, y, null);
+ return colorModel.getRGB(rgbElem);
+ }
+
+ public int[] getRGB(int startX, int startY, int w, int h, int[] rgbArray,
+ int offset, int scanlineStride)
+ {
+ if (rgbArray == null)
+ {
+ /*
+ 000000000000000000
+ 00000[#######----- [ = start
+ -----########----- ] = end
+ -----#######]00000
+ 000000000000000000
+ */
+ int size = (h-1)*scanlineStride + w;
+ rgbArray = new int[size];
+ }
+
+ int endX = startX + w;
+ int endY = startY + h;
+
+ /* *TODO*:
+ Opportunity for optimization by examining color models...
+
+ Perhaps wrap the rgbArray up in a WritableRaster with packed
+ sRGB color model and perform optimized rendering into the
+ array. */
+
+ Object rgbElem = null;
+ for (int y=startY; y<endY; y++)
+ {
+ int xoffset = offset;
+ for (int x=startX; x<endX; x++)
+ {
+ int rgb;
+ rgbElem = raster.getDataElements(x, y, rgbElem);
+ rgb = colorModel.getRGB(rgbElem);
+ rgbArray[xoffset++] = rgb;
+ }
+ offset += scanlineStride;
+ }
+ return rgbArray;
+ }
+
+ public WritableRaster getRaster()
+ {
+ return raster;
+ }
+
+ public SampleModel getSampleModel()
+ {
+ return raster.getSampleModel();
+ }
+
+ public ImageProducer getSource()
+ {
+ return new ImageProducer()
+ {
+ Vector<ImageConsumer> consumers = new Vector<ImageConsumer>();
+
+ public void addConsumer(ImageConsumer ic)
+ {
+ if(!consumers.contains(ic))
+ consumers.add(ic);
+ }
+
+ public boolean isConsumer(ImageConsumer ic)
+ {
+ return consumers.contains(ic);
+ }
+
+ public void removeConsumer(ImageConsumer ic)
+ {
+ consumers.remove(ic);
+ }
+
+ public void startProduction(ImageConsumer ic)
+ {
+ int x = 0;
+ int y = 0;
+ int width = getWidth();
+ int height = getHeight();
+ int stride = width;
+ int offset = 0;
+ int[] pixels = getRGB(x, y,
+ width, height,
+ (int[])null, offset, stride);
+ // We already convert the color to RGB in the getRGB call, so
+ // we pass a simple RGB color model to the consumers.
+ ColorModel model = new DirectColorModel(32, 0xff0000, 0xff00, 0xff,
+ 0xff000000);
+
+ consumers.add(ic);
+
+ for(int i = 0; i < consumers.size(); i++)
+ {
+ ImageConsumer c = consumers.elementAt(i);
+ c.setHints(ImageConsumer.SINGLEPASS);
+ c.setDimensions(getWidth(), getHeight());
+ c.setPixels(x, y, width, height, model, pixels, offset, stride);
+ c.imageComplete(ImageConsumer.STATICIMAGEDONE);
+ }
+ }
+
+ public void requestTopDownLeftRightResend(ImageConsumer ic)
+ {
+ startProduction(ic);
+ }
+
+ };
+ }
+
+ public Vector<RenderedImage> getSources()
+ {
+ return null;
+ }
+
+ public BufferedImage getSubimage(int x, int y, int w, int h)
+ {
+ WritableRaster subRaster =
+ getRaster().createWritableChild(x, y, w, h, 0, 0, null);
+
+ return new BufferedImage(getColorModel(), subRaster, isPremultiplied,
+ properties);
+ }
+
+ public Raster getTile(int tileX, int tileY)
+ {
+ return getWritableTile(tileX, tileY);
+ }
+
+ public int getTileGridXOffset()
+ {
+ return 0; // according to javadocs
+ }
+
+ public int getTileGridYOffset()
+ {
+ return 0; // according to javadocs
+ }
+
+ public int getTileHeight()
+ {
+ return getHeight(); // image is one big tile
+ }
+
+ public int getTileWidth()
+ {
+ return getWidth(); // image is one big tile
+ }
+
+ public int getType()
+ {
+ return type;
+ }
+
+ public int getWidth()
+ {
+ return raster.getWidth();
+ }
+
+ public int getWidth(ImageObserver imageobserver)
+ {
+ return getWidth();
+ }
+
+ public WritableRaster getWritableTile(int tileX, int tileY)
+ {
+ isTileWritable(tileX, tileY); // for exception
+ return raster;
+ }
+
+ private static final Point[] tileIndices = { new Point() };
+
+ public Point[] getWritableTileIndices()
+ {
+ return tileIndices;
+ }
+
+ public boolean hasTileWriters()
+ {
+ return true;
+ }
+
+ public boolean isAlphaPremultiplied()
+ {
+ return isPremultiplied;
+ }
+
+ public boolean isTileWritable(int tileX, int tileY)
+ {
+ if ((tileX != 0) || (tileY != 0))
+ throw new ArrayIndexOutOfBoundsException("only tile is (0,0)");
+ return true;
+ }
+
+ public void releaseWritableTile(int tileX, int tileY)
+ {
+ isTileWritable(tileX, tileY); // for exception
+ }
+
+ //public void removeTileObserver(TileObserver tileobserver) {}
+
+ public void setData(Raster src)
+ {
+ int x = src.getMinX();
+ int y = src.getMinY();
+ int w = src.getWidth();
+ int h = src.getHeight();
+
+ // create a dest child that has the right bounds...
+ WritableRaster dest =
+ raster.createWritableChild(x, y, w, h, x, y, null);
+
+ if (src.getSampleModel () instanceof ComponentSampleModel
+ && dest.getSampleModel () instanceof ComponentSampleModel)
+
+ // Refer to ComponentDataBlitOp for optimized data blitting:
+ ComponentDataBlitOp.INSTANCE.filter(src, dest);
+ else
+ {
+ // slower path
+ int samples[] = src.getPixels (x, y, w, h, (int [])null);
+ dest.setPixels (x, y, w, h, samples);
+ }
+ }
+
+ public void setRGB(int x, int y, int argb)
+ {
+ Object rgbElem = colorModel.getDataElements(argb, null);
+ raster.setDataElements(x, y, rgbElem);
+ }
+
+ public void setRGB(int startX, int startY, int w, int h,
+ int[] argbArray, int offset, int scanlineStride)
+ {
+ int endX = startX + w;
+ int endY = startY + h;
+
+ Object rgbElem = null;
+ for (int y=startY; y<endY; y++)
+ {
+ int xoffset = offset;
+ for (int x=startX; x<endX; x++)
+ {
+ int argb = argbArray[xoffset++];
+ rgbElem = colorModel.getDataElements(argb, rgbElem);
+ raster.setDataElements(x, y, rgbElem);
+ }
+ offset += scanlineStride;
+ }
+ }
+
+ public String toString()
+ {
+ CPStringBuilder buf;
+
+ buf = new CPStringBuilder(/* estimated length */ 120);
+ buf.append("BufferedImage@");
+ buf.append(Integer.toHexString(hashCode()));
+ buf.append(": type=");
+ buf.append(type);
+ buf.append(' ');
+ buf.append(colorModel);
+ buf.append(' ');
+ buf.append(raster);
+
+ return buf.toString();
+ }
+
+
+ /**
+ * Adds a tile observer. If the observer is already present, it receives
+ * multiple notifications.
+ *
+ * @param to The TileObserver to add.
+ */
+ public void addTileObserver (TileObserver to)
+ {
+ if (tileObservers == null)
+ tileObservers = new Vector<TileObserver>();
+
+ tileObservers.add (to);
+ }
+
+ /**
+ * Removes a tile observer. If the observer was not registered,
+ * nothing happens. If the observer was registered for multiple
+ * notifications, it is now registered for one fewer notification.
+ *
+ * @param to The TileObserver to remove.
+ */
+ public void removeTileObserver (TileObserver to)
+ {
+ if (tileObservers == null)
+ return;
+
+ tileObservers.remove (to);
+ }
+
+ /**
+ * Return the transparency type.
+ *
+ * @return One of {@link #OPAQUE}, {@link #BITMASK}, or {@link #TRANSLUCENT}.
+ * @see Transparency#getTransparency()
+ * @since 1.5
+ */
+ public int getTransparency()
+ {
+ return colorModel.getTransparency();
+ }
+}
diff --git a/libjava/classpath/java/awt/image/BufferedImageFilter.java b/libjava/classpath/java/awt/image/BufferedImageFilter.java
new file mode 100644
index 000000000..04b6672c6
--- /dev/null
+++ b/libjava/classpath/java/awt/image/BufferedImageFilter.java
@@ -0,0 +1,110 @@
+/* Copyright (C) 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+import java.awt.Point;
+
+/**
+ * The BufferedImageFilter class wraps BufferedImageOp objects in a Filter.
+ *
+ * When pixels are pushed through the filter, we create a BufferedImage,
+ * apply the BufferedImageOp, and pass the filtered pixels to the base class.
+ *
+ * @author jlquinn@optonline.net
+ */
+public class BufferedImageFilter extends ImageFilter implements Cloneable
+{
+ private BufferedImageOp op;
+
+ /**
+ *
+ */
+ public BufferedImageFilter(BufferedImageOp op)
+ {
+ super();
+ if (op == null)
+ throw new NullPointerException("BufferedImageFilter null"
+ + " op in constructor");
+ this.op = op;
+ }
+
+ /**
+ * @return Returns the contained BufferedImageOp.
+ */
+ public BufferedImageOp getBufferedImageOp()
+ {
+ return op;
+ }
+
+ // FIXME: Definitely not sure this is the right thing. I'm not sure how to
+ // create a compatible sample model that incorporates scansize != w. I
+ // asume off is handled by the db itself.
+ public void setPixels(int x, int y, int w, int h, ColorModel model,
+ byte[] pixels, int off, int scansize)
+ {
+ // Create an input BufferedImage
+ DataBufferByte db = new DataBufferByte(pixels, scansize * h + off, off);
+ SampleModel sm = model.createCompatibleSampleModel(scansize, h);
+ WritableRaster wr = new WritableRaster(sm, db, new Point(0, 0));
+ BufferedImage in =
+ new BufferedImage(model, wr, model.isAlphaPremultiplied(), null);
+ BufferedImage out = op.createCompatibleDestImage(in, model);
+ op.filter(in, out);
+ DataBuffer dbout = out.getRaster().getDataBuffer();
+ super.setPixels(0, 0, w, h, model, ((DataBufferByte)dbout).getData(), 0,
+ scansize);
+ }
+
+ // FIXME: Definitely not sure this is the right thing. I'm not sure how
+ // to create a compatible sample model that incorporates
+ // scansize != w. I asume off is handled by the db itself.
+ public void setPixels(int x, int y, int w, int h, ColorModel model,
+ int[] pixels, int off, int scansize)
+ {
+ // Create an input BufferedImage
+ DataBufferInt db = new DataBufferInt(pixels, scansize * h + off, off);
+ SampleModel sm = model.createCompatibleSampleModel(scansize, h);
+ WritableRaster wr = new WritableRaster(sm, db, new Point(0, 0));
+ BufferedImage in =
+ new BufferedImage(model, wr, model.isAlphaPremultiplied(), null);
+ BufferedImage out = op.createCompatibleDestImage(in, model);
+ op.filter(in, out);
+ DataBuffer dbout = out.getRaster().getDataBuffer();
+ super.setPixels(0, 0, w, h, model, ((DataBufferInt)dbout).getData(), 0,
+ scansize);
+ }
+}
diff --git a/libjava/classpath/java/awt/image/BufferedImageOp.java b/libjava/classpath/java/awt/image/BufferedImageOp.java
new file mode 100644
index 000000000..1aba4bb09
--- /dev/null
+++ b/libjava/classpath/java/awt/image/BufferedImageOp.java
@@ -0,0 +1,107 @@
+/* BufferedImageOp.java --
+ Copyright (C) 2002, 2006, Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.RenderingHints;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * An operation that is performed on one <code>BufferedImage</code> (the
+ * source) producing a new <code>BufferedImage</code> (the destination).
+ */
+public interface BufferedImageOp
+{
+ /**
+ * Performs an operation on the source image, returning the result in a
+ * <code>BufferedImage</code>. If <code>dest</code> is <code>null</code>, a
+ * new <code>BufferedImage</code> will be created by calling the
+ * {@link #createCompatibleDestImage} method. If <code>dest</code>
+ * is not <code>null</code>, the result is written to <code>dest</code> then
+ * returned (this avoids creating a new <code>BufferedImage</code> each
+ * time this method is called).
+ *
+ * @param src the source image.
+ * @param dst the destination image (<code>null</code> permitted).
+ *
+ * @return The filterd image.
+ */
+ BufferedImage filter(BufferedImage src, BufferedImage dst);
+
+ /**
+ * Returns the bounds of the destination image on the basis of this
+ * <code>BufferedImageOp</code> being applied to the specified source image.
+ *
+ * @param src the source image.
+ *
+ * @return The destination bounds.
+ */
+ Rectangle2D getBounds2D(BufferedImage src);
+
+ /**
+ * Returns a new <code>BufferedImage</code> that can be used by this
+ * <code>BufferedImageOp</code> as the destination image when filtering
+ * the specified source image.
+ *
+ * @param src the source image.
+ * @param dstCM the color model for the destination image.
+ *
+ * @return A new image that can be used as the destination image.
+ */
+ BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM);
+
+ /**
+ * Returns the point on the destination image that corresponds to the given
+ * point on the source image.
+ *
+ * @param src the source point.
+ * @param dst the destination point (<code>null</code> permitted).
+ *
+ * @return The destination point.
+ */
+ Point2D getPoint2D(Point2D src, Point2D dst);
+
+ /**
+ * Returns the rendering hints for this operation.
+ *
+ * @return The rendering hints.
+ */
+ RenderingHints getRenderingHints();
+
+}
diff --git a/libjava/classpath/java/awt/image/ByteLookupTable.java b/libjava/classpath/java/awt/image/ByteLookupTable.java
new file mode 100644
index 000000000..89804c55b
--- /dev/null
+++ b/libjava/classpath/java/awt/image/ByteLookupTable.java
@@ -0,0 +1,175 @@
+/* ByteLookupTable.java -- Java class for a pixel translation table.
+ Copyright (C) 2004, 2005, 2006, Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+/**
+ * ByteLookupTable represents translation arrays for pixel values. It wraps
+ * one or more data arrays for each layer (or component) in an image, such as
+ * Alpha, R, G, and B. When doing translation, the offset is subtracted from
+ * the pixel values to allow a subset of an array to be used.
+ *
+ * @author Jerry Quinn (jlquinn@optonline.net)
+ * @version 1.0
+ */
+public class ByteLookupTable extends LookupTable
+{
+ // Array of translation tables.
+ private byte data[][];
+
+ /**
+ * Creates a new <code>ByteLookupTable</code> instance.
+ *
+ * Offset is subtracted from pixel values when looking up in the translation
+ * tables. If data.length is one, the same table is applied to all pixel
+ * components.
+ *
+ * @param offset Offset to be subtracted.
+ * @param data Array of lookup tables (<code>null</code> not permitted).
+ * @exception IllegalArgumentException if offset &lt; 0 or data.length &lt; 1.
+ */
+ public ByteLookupTable(int offset, byte[][] data)
+ throws IllegalArgumentException
+ {
+ super(offset, data.length);
+
+ // tests show that Sun's implementation creates a new array to store the
+ // references from the incoming 'data' array - not sure why, but we'll
+ // match that behaviour just in case it matters...
+ this.data = new byte[data.length][];
+ for (int i = 0; i < data.length; i++)
+ this.data[i] = data[i];
+ }
+
+ /**
+ * Creates a new <code>ByteLookupTable</code> instance.
+ *
+ * Offset is subtracted from pixel values when looking up in the translation
+ * table. The same table is applied to all pixel components.
+ *
+ * @param offset Offset to be subtracted.
+ * @param data Lookup table for all components (<code>null</code> not
+ * permitted).
+ * @exception IllegalArgumentException if offset &lt; 0.
+ */
+ public ByteLookupTable(int offset, byte[] data)
+ throws IllegalArgumentException
+ {
+ super(offset, 1);
+ if (data == null)
+ throw new NullPointerException("Null 'data' argument.");
+ this.data = new byte[][] {data};
+ }
+
+ /**
+ * Return the lookup tables.
+ *
+ * @return the tables
+ */
+ public final byte[][] getTable()
+ {
+ return data;
+ }
+
+ /**
+ * Return translated values for a pixel.
+ *
+ * For each value in the pixel src, use the value minus offset as an index
+ * in the component array and copy the value there to the output for the
+ * component. If dest is null, the output is a new array, otherwise the
+ * translated values are written to dest. Dest can be the same array as
+ * src.
+ *
+ * For example, if the pixel src is [2, 4, 3], and offset is 1, the output
+ * is [comp1[1], comp2[3], comp3[2]], where comp1, comp2, and comp3 are the
+ * translation arrays.
+ *
+ * @param src Component values of a pixel.
+ * @param dst Destination array for values, or null.
+ * @return Translated values for the pixel.
+ */
+ public int[] lookupPixel(int[] src, int[] dst)
+ throws ArrayIndexOutOfBoundsException
+ {
+ if (dst == null)
+ dst = new int[src.length];
+
+ if (data.length == 1)
+ for (int i=0; i < src.length; i++)
+ dst[i] = data[0][src[i] - offset];
+ else
+ for (int i=0; i < src.length; i++)
+ dst[i] = data[i][src[i] - offset];
+
+ return dst;
+ }
+
+ /**
+ * Return translated values for a pixel.
+ *
+ * For each value in the pixel src, use the value minus offset as an index
+ * in the component array and copy the value there to the output for the
+ * component. If dest is null, the output is a new array, otherwise the
+ * translated values are written to dest. Dest can be the same array as
+ * src.
+ *
+ * For example, if the pixel src is [2, 4, 3], and offset is 1, the output
+ * is [comp1[1], comp2[3], comp3[2]], where comp1, comp2, and comp3 are the
+ * translation arrays.
+ *
+ * @param src Component values of a pixel.
+ * @param dst Destination array for values, or null.
+ * @return Translated values for the pixel.
+ */
+ public byte[] lookupPixel(byte[] src, byte[] dst)
+ throws ArrayIndexOutOfBoundsException
+ {
+ if (dst == null)
+ dst = new byte[src.length];
+
+ if (data.length == 1)
+ for (int i=0; i < src.length; i++)
+ dst[i] = data[0][((int)src[i]) - offset];
+ else
+ for (int i=0; i < src.length; i++)
+ dst[i] = data[i][((int)src[i]) - offset];
+
+ return dst;
+
+ }
+}
diff --git a/libjava/classpath/java/awt/image/ColorConvertOp.java b/libjava/classpath/java/awt/image/ColorConvertOp.java
new file mode 100644
index 000000000..b1d6f857d
--- /dev/null
+++ b/libjava/classpath/java/awt/image/ColorConvertOp.java
@@ -0,0 +1,537 @@
+/* ColorConvertOp.java --
+ Copyright (C) 2004, 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import gnu.java.awt.Buffers;
+
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.RenderingHints;
+import java.awt.color.ColorSpace;
+import java.awt.color.ICC_ColorSpace;
+import java.awt.color.ICC_Profile;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * ColorConvertOp is a filter for converting images or rasters between
+ * colorspaces, either through a sequence of colorspaces or just from source to
+ * destination.
+ *
+ * Color conversion is done on the color components without alpha. Thus
+ * if a BufferedImage has alpha premultiplied, this is divided out before
+ * color conversion, and premultiplication applied if the destination
+ * requires it.
+ *
+ * Color rendering and dithering hints may be applied if specified. This is
+ * likely platform-dependent.
+ *
+ * @author jlquinn@optonline.net
+ */
+public class ColorConvertOp implements BufferedImageOp, RasterOp
+{
+ private RenderingHints hints;
+ private ICC_Profile[] profiles = null;
+ private ColorSpace[] spaces;
+
+
+ /**
+ * Convert a BufferedImage through a ColorSpace.
+ *
+ * Objects created with this constructor can be used to convert
+ * BufferedImage's to a destination ColorSpace. Attempts to convert Rasters
+ * with this constructor will result in an IllegalArgumentException when the
+ * filter(Raster, WritableRaster) method is called.
+ *
+ * @param cspace The target color space.
+ * @param hints Rendering hints to use in conversion, if any (may be null)
+ * @throws NullPointerException if the ColorSpace is null.
+ */
+ public ColorConvertOp(ColorSpace cspace, RenderingHints hints)
+ {
+ if (cspace == null)
+ throw new NullPointerException();
+ spaces = new ColorSpace[]{cspace};
+ this.hints = hints;
+ }
+
+ /**
+ * Convert from a source colorspace to a destination colorspace.
+ *
+ * This constructor takes two ColorSpace arguments as the source and
+ * destination color spaces. It is usually used with the
+ * filter(Raster, WritableRaster) method, in which case the source colorspace
+ * is assumed to correspond to the source Raster, and the destination
+ * colorspace with the destination Raster.
+ *
+ * If used with BufferedImages that do not match the source or destination
+ * colorspaces specified here, there is an implicit conversion from the
+ * source image to the source ColorSpace, or the destination ColorSpace to
+ * the destination image.
+ *
+ * @param srcCspace The source ColorSpace.
+ * @param dstCspace The destination ColorSpace.
+ * @param hints Rendering hints to use in conversion, if any (may be null).
+ * @throws NullPointerException if any ColorSpace is null.
+ */
+ public ColorConvertOp(ColorSpace srcCspace, ColorSpace dstCspace,
+ RenderingHints hints)
+ {
+ if (srcCspace == null || dstCspace == null)
+ throw new NullPointerException();
+ spaces = new ColorSpace[]{srcCspace, dstCspace};
+ this.hints = hints;
+ }
+
+ /**
+ * Convert from a source colorspace to a destinatino colorspace.
+ *
+ * This constructor builds a ColorConvertOp from an array of ICC_Profiles.
+ * The source will be converted through the sequence of color spaces
+ * defined by the profiles. If the sequence of profiles doesn't give a
+ * well-defined conversion, an IllegalArgumentException is thrown.
+ *
+ * If used with BufferedImages that do not match the source or destination
+ * colorspaces specified here, there is an implicit conversion from the
+ * source image to the source ColorSpace, or the destination ColorSpace to
+ * the destination image.
+ *
+ * For Rasters, the first and last profiles must have the same number of
+ * bands as the source and destination Rasters, respectively. If this is
+ * not the case, or there fewer than 2 profiles, an IllegalArgumentException
+ * will be thrown.
+ *
+ * @param profiles An array of ICC_Profile's to convert through.
+ * @param hints Rendering hints to use in conversion, if any (may be null).
+ * @throws NullPointerException if the profile array is null.
+ * @throws IllegalArgumentException if the array is not a well-defined
+ * conversion.
+ */
+ public ColorConvertOp(ICC_Profile[] profiles, RenderingHints hints)
+ {
+ if (profiles == null)
+ throw new NullPointerException();
+
+ this.hints = hints;
+ this.profiles = profiles;
+
+ // Create colorspace array with space for src and dest colorspace
+ // Note that the ICC_ColorSpace constructor will throw an
+ // IllegalArgumentException if the profile is invalid; thus we check
+ // for a "well defined conversion"
+ spaces = new ColorSpace[profiles.length];
+ for (int i = 0; i < profiles.length; i++)
+ spaces[i] = new ICC_ColorSpace(profiles[i]);
+ }
+
+ /**
+ * Convert from source color space to destination color space.
+ *
+ * Only valid for BufferedImage objects, this Op converts from the source
+ * image's color space to the destination image's color space.
+ *
+ * The destination in the filter(BufferedImage, BufferedImage) method cannot
+ * be null for this operation, and it also cannot be used with the
+ * filter(Raster, WritableRaster) method.
+ *
+ * @param hints Rendering hints to use in conversion, if any (may be null).
+ */
+ public ColorConvertOp(RenderingHints hints)
+ {
+ this.hints = hints;
+ spaces = new ColorSpace[0];
+ }
+
+ /**
+ * Converts the source image using the conversion path specified in the
+ * constructor. The resulting image is stored in the destination image if one
+ * is provided; otherwise a new BufferedImage is created and returned.
+ *
+ * The source and destination BufferedImage (if one is supplied) must have
+ * the same dimensions.
+ *
+ * @param src The source image.
+ * @param dst The destination image.
+ * @throws IllegalArgumentException if the rasters and/or color spaces are
+ * incompatible.
+ * @return The transformed image.
+ */
+ public final BufferedImage filter(BufferedImage src, BufferedImage dst)
+ {
+ // TODO: The plan is to create a scanline buffer for intermediate buffers.
+ // For now we just suck it up and create intermediate buffers.
+
+ if (dst == null && spaces.length == 0)
+ throw new IllegalArgumentException("Not enough color space information "
+ + "to complete conversion.");
+
+ if (dst != null
+ && (src.getHeight() != dst.getHeight() || src.getWidth() != dst.getWidth()))
+ throw new IllegalArgumentException("Source and destination images have "
+ + "different dimensions");
+
+ // Make sure input isn't premultiplied by alpha
+ if (src.isAlphaPremultiplied())
+ {
+ BufferedImage tmp = createCompatibleDestImage(src, src.getColorModel());
+ copyimage(src, tmp);
+ tmp.coerceData(false);
+ src = tmp;
+ }
+
+ // Convert through defined intermediate conversions
+ BufferedImage tmp;
+ for (int i = 0; i < spaces.length; i++)
+ {
+ if (src.getColorModel().getColorSpace().getType() != spaces[i].getType())
+ {
+ tmp = createCompatibleDestImage(src,
+ createCompatibleColorModel(src,
+ spaces[i]));
+ copyimage(src, tmp);
+ src = tmp;
+ }
+ }
+
+ // No implicit conversion to destination type needed; return result from the
+ // last intermediate conversions (which was left in src)
+ if (dst == null)
+ dst = src;
+
+ // Implicit conversion to destination image's color space
+ else
+ copyimage(src, dst);
+
+ return dst;
+ }
+
+ /**
+ * Converts the source raster using the conversion path specified in the
+ * constructor. The resulting raster is stored in the destination raster if
+ * one is provided; otherwise a new WritableRaster is created and returned.
+ *
+ * This operation is not valid with every constructor of this class; see
+ * the constructors for details. Further, the source raster must have the
+ * same number of bands as the source ColorSpace, and the destination raster
+ * must have the same number of bands as the destination ColorSpace.
+ *
+ * The source and destination raster (if one is supplied) must also have the
+ * same dimensions.
+ *
+ * @param src The source raster.
+ * @param dest The destination raster.
+ * @throws IllegalArgumentException if the rasters and/or color spaces are
+ * incompatible.
+ * @return The transformed raster.
+ */
+ public final WritableRaster filter(Raster src, WritableRaster dest)
+ {
+ // Various checks to ensure that the rasters and color spaces are compatible
+ if (spaces.length < 2)
+ throw new IllegalArgumentException("Not enough information about " +
+ "source and destination colorspaces.");
+
+ if (spaces[0].getNumComponents() != src.getNumBands()
+ || (dest != null && spaces[spaces.length - 1].getNumComponents() != dest.getNumBands()))
+ throw new IllegalArgumentException("Source or destination raster " +
+ "contains the wrong number of bands.");
+
+ if (dest != null
+ && (src.getHeight() != dest.getHeight() || src.getWidth() != dest.getWidth()))
+ throw new IllegalArgumentException("Source and destination rasters " +
+ "have different dimensions");
+
+ // Need to iterate through each color space.
+ // spaces[0] corresponds to the ColorSpace of the source raster, and
+ // spaces[spaces.length - 1] corresponds to the ColorSpace of the
+ // destination, with any number (or zero) of intermediate conversions.
+
+ for (int i = 0; i < spaces.length - 2; i++)
+ {
+ WritableRaster tmp = createCompatibleDestRaster(src, spaces[i + 1],
+ false,
+ src.getTransferType());
+ copyraster(src, spaces[i], tmp, spaces[i + 1]);
+ src = tmp;
+ }
+
+ // The last conversion is done outside of the loop so that we can
+ // use the dest raster supplied, instead of creating our own temp raster
+ if (dest == null)
+ dest = createCompatibleDestRaster(src, spaces[spaces.length - 1], false,
+ DataBuffer.TYPE_BYTE);
+ copyraster(src, spaces[spaces.length - 2], dest, spaces[spaces.length - 1]);
+
+ return dest;
+ }
+
+ /**
+ * Creates an empty BufferedImage with the size equal to the source and the
+ * correct number of bands for the conversion defined in this Op. The newly
+ * created image is created with the specified ColorModel, or if no ColorModel
+ * is supplied, an appropriate one is chosen.
+ *
+ * @param src The source image.
+ * @param dstCM A color model for the destination image (may be null).
+ * @throws IllegalArgumentException if an appropriate colormodel cannot be
+ * chosen with the information given.
+ * @return The new compatible destination image.
+ */
+ public BufferedImage createCompatibleDestImage(BufferedImage src,
+ ColorModel dstCM)
+ {
+ if (dstCM == null && spaces.length == 0)
+ throw new IllegalArgumentException("Don't know the destination " +
+ "colormodel");
+
+ if (dstCM == null)
+ {
+ dstCM = createCompatibleColorModel(src, spaces[spaces.length - 1]);
+ }
+
+ return new BufferedImage(dstCM,
+ createCompatibleDestRaster(src.getRaster(),
+ dstCM.getColorSpace(),
+ src.getColorModel().hasAlpha,
+ dstCM.getTransferType()),
+ src.isPremultiplied, null);
+ }
+
+ /**
+ * Creates a new WritableRaster with the size equal to the source and the
+ * correct number of bands.
+ *
+ * Note, the new Raster will always use a BYTE storage size, regardless of
+ * the color model or defined destination; this is for compatibility with
+ * the reference implementation.
+ *
+ * @param src The source Raster.
+ * @throws IllegalArgumentException if there isn't enough colorspace
+ * information to create a compatible Raster.
+ * @return The new compatible destination raster.
+ */
+ public WritableRaster createCompatibleDestRaster(Raster src)
+ {
+ if (spaces.length < 2)
+ throw new IllegalArgumentException("Not enough destination colorspace " +
+ "information");
+
+ // Create a new raster with the last ColorSpace in the conversion
+ // chain, and with no alpha (implied)
+ return createCompatibleDestRaster(src, spaces[spaces.length-1], false,
+ DataBuffer.TYPE_BYTE);
+ }
+
+ /**
+ * Returns the array of ICC_Profiles used to create this Op, or null if the
+ * Op was created using ColorSpace arguments.
+ *
+ * @return The array of ICC_Profiles, or null.
+ */
+ public final ICC_Profile[] getICC_Profiles()
+ {
+ return profiles;
+ }
+
+ /**
+ * Returns the rendering hints for this op.
+ *
+ * @return The rendering hints for this Op, or null.
+ */
+ public final RenderingHints getRenderingHints()
+ {
+ return hints;
+ }
+
+ /**
+ * Returns the corresponding destination point for a source point.
+ * Because this is not a geometric operation, the destination and source
+ * points will be identical.
+ *
+ * @param src The source point.
+ * @param dst The transformed destination point.
+ * @return The transformed destination point.
+ */
+ public final Point2D getPoint2D(Point2D src, Point2D dst)
+ {
+ if (dst == null)
+ return (Point2D)src.clone();
+
+ dst.setLocation(src);
+ return dst;
+ }
+
+ /**
+ * Returns the corresponding destination boundary of a source boundary.
+ * Because this is not a geometric operation, the destination and source
+ * boundaries will be identical.
+ *
+ * @param src The source boundary.
+ * @return The boundaries of the destination.
+ */
+ public final Rectangle2D getBounds2D(BufferedImage src)
+ {
+ return src.getRaster().getBounds();
+ }
+
+ /**
+ * Returns the corresponding destination boundary of a source boundary.
+ * Because this is not a geometric operation, the destination and source
+ * boundaries will be identical.
+ *
+ * @param src The source boundary.
+ * @return The boundaries of the destination.
+ */
+ public final Rectangle2D getBounds2D(Raster src)
+ {
+ return src.getBounds();
+ }
+
+ /**
+ * Copy a source image to a destination image, respecting their colorspaces
+ * and performing colorspace conversions if necessary.
+ *
+ * @param src The source image.
+ * @param dst The destination image.
+ */
+ private void copyimage(BufferedImage src, BufferedImage dst)
+ {
+ // This is done using Graphics2D in order to respect the rendering hints.
+ Graphics2D gg = dst.createGraphics();
+
+ // If no hints are set there is no need to call
+ // setRenderingHints on the Graphics2D object.
+ if (hints != null)
+ gg.setRenderingHints(hints);
+
+ gg.drawImage(src, 0, 0, null);
+ gg.dispose();
+ }
+
+ /**
+ * Copy a source raster to a destination raster, performing a colorspace
+ * conversion between the two. The conversion will respect the
+ * KEY_COLOR_RENDERING rendering hint if one is present.
+ *
+ * @param src The source raster.
+ * @param scs The colorspace of the source raster.
+ * @dst The destination raster.
+ * @dcs The colorspace of the destination raster.
+ */
+ private void copyraster(Raster src, ColorSpace scs, WritableRaster dst, ColorSpace dcs)
+ {
+ float[] sbuf = new float[src.getNumBands()];
+
+ if (hints != null
+ && hints.get(RenderingHints.KEY_COLOR_RENDERING) ==
+ RenderingHints.VALUE_COLOR_RENDER_QUALITY)
+ {
+ // use cie for accuracy
+ for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
+ for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
+ dst.setPixel(x, y,
+ dcs.fromCIEXYZ(scs.toCIEXYZ(src.getPixel(x, y, sbuf))));
+ }
+ else
+ {
+ // use rgb - it's probably faster
+ for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
+ for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
+ dst.setPixel(x, y,
+ dcs.fromRGB(scs.toRGB(src.getPixel(x, y, sbuf))));
+ }
+ }
+
+ /**
+ * This method creates a color model with the same colorspace and alpha
+ * settings as the source image. The created color model will always be a
+ * ComponentColorModel and have a BYTE transfer type.
+ *
+ * @param img The source image.
+ * @param cs The ColorSpace to use.
+ * @return A color model compatible with the source image.
+ */
+ private ColorModel createCompatibleColorModel(BufferedImage img, ColorSpace cs)
+ {
+ // The choice of ComponentColorModel and DataBuffer.TYPE_BYTE is based on
+ // Mauve testing of the reference implementation.
+ return new ComponentColorModel(cs,
+ img.getColorModel().hasAlpha(),
+ img.isAlphaPremultiplied(),
+ img.getColorModel().getTransparency(),
+ DataBuffer.TYPE_BYTE);
+ }
+
+ /**
+ * This method creates a compatible Raster, given a source raster, colorspace,
+ * alpha value, and transfer type.
+ *
+ * @param src The source raster.
+ * @param cs The ColorSpace to use.
+ * @param hasAlpha Whether the raster should include a component for an alpha.
+ * @param transferType The size of a single data element.
+ * @return A compatible WritableRaster.
+ */
+ private WritableRaster createCompatibleDestRaster(Raster src, ColorSpace cs,
+ boolean hasAlpha,
+ int transferType)
+ {
+ // The use of a PixelInterleavedSampleModel weas determined using mauve
+ // tests, based on the reference implementation
+
+ int numComponents = cs.getNumComponents();
+ if (hasAlpha)
+ numComponents++;
+
+ int[] offsets = new int[numComponents];
+ for (int i = 0; i < offsets.length; i++)
+ offsets[i] = i;
+
+ DataBuffer db = Buffers.createBuffer(transferType,
+ src.getWidth() * src.getHeight() * numComponents,
+ 1);
+ return new WritableRaster(new PixelInterleavedSampleModel(transferType,
+ src.getWidth(),
+ src.getHeight(),
+ numComponents,
+ numComponents * src.getWidth(),
+ offsets),
+ db, new Point(src.getMinX(), src.getMinY()));
+ }
+}
diff --git a/libjava/classpath/java/awt/image/ColorModel.java b/libjava/classpath/java/awt/image/ColorModel.java
new file mode 100644
index 000000000..ede9e31d8
--- /dev/null
+++ b/libjava/classpath/java/awt/image/ColorModel.java
@@ -0,0 +1,794 @@
+/* ColorModel.java --
+ Copyright (C) 1999, 2000, 2002, 2003, 2004, 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import gnu.java.awt.Buffers;
+
+import java.awt.Point;
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
+import java.util.Arrays;
+
+/**
+ * A color model operates with colors in several formats:
+ *
+ * <ul>
+ * <li>normalized: component samples are in range [0.0, 1.0].</li>
+ *
+ * <li>color model pixel value: all the color component samples for a
+ * sigle pixel packed/encoded in a way natural for the color
+ * model.</li>
+ *
+ * <li>color model pixel int value: only makes sense if the natural
+ * encoding of a single pixel can fit in a single int value.</li>
+ *
+ * <li>array of transferType containing a single pixel: the pixel is
+ * encoded in the natural way of the color model, taking up as many
+ * array elements as needed.</li>
+ *
+ * <li>sRGB pixel int value: a pixel in sRGB color space, encoded in
+ * default 0xAARRGGBB format, assumed not alpha premultiplied.</li>
+ *
+ * <li>single [0, 255] scaled int samples from default sRGB color
+ * space. These are always assumed to be alpha non-premultiplied.</li>
+ *
+ * <li>arrays of unnormalized component samples of single pixel: these
+ * samples are scaled and multiplied according to the color model, but
+ * is otherwise not packed or encoded. Each element of the array is one
+ * separate component sample. The color model only operate on the
+ * components from one pixel at a time, but using offsets, allows
+ * manipulation of arrays that contain the components of more than one
+ * pixel.</li>
+ *
+ * </ul>
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ * @author C. Brian Jones (cbj@gnu.org)
+ */
+public abstract class ColorModel implements Transparency
+{
+ protected int pixel_bits;
+ protected int transferType;
+
+ int[] bits;
+ ColorSpace cspace;
+ int transparency;
+ boolean hasAlpha;
+ boolean isAlphaPremultiplied;
+
+ /**
+ * The standard color model for the common sRGB.
+ */
+ private static final ColorModel S_RGB_MODEL = new SRGBColorModel();
+
+ static int[] nArray(int value, int times)
+ {
+ int[] array = new int[times];
+ java.util.Arrays.fill(array, value);
+ return array;
+ }
+
+ static byte[] nArray(byte value, int times)
+ {
+ byte[] array = new byte[times];
+ java.util.Arrays.fill(array, value);
+ return array;
+ }
+
+ /**
+ * Constructs the default color model. The default color model
+ * can be obtained by calling <code>getRGBdefault</code> of this
+ * class.
+ * @param bits the number of bits wide used for bit size of pixel values
+ */
+ public ColorModel(int bits)
+ {
+ this(bits * 4, // total bits, sRGB, four channels
+ nArray(bits, 4), // bits for each channel
+ ColorSpace.getInstance(ColorSpace.CS_sRGB), // sRGB
+ true, // has alpha
+ false, // not premultiplied
+ TRANSLUCENT,
+ Buffers.smallestAppropriateTransferType(bits * 4));
+ }
+
+ /**
+ * Constructs a ColorModel that translates pixel values to
+ * color/alpha components.
+ *
+ * @exception IllegalArgumentException If the length of the bit array is less
+ * than the number of color or alpha components in this ColorModel, or if the
+ * transparency is not a valid value, or if the sum of the number of bits in
+ * bits is less than 1 or if any of the elements in bits is less than 0.
+ */
+ protected ColorModel(int pixel_bits, int[] bits, ColorSpace cspace,
+ boolean hasAlpha, boolean isAlphaPremultiplied,
+ int transparency, int transferType)
+ {
+ int bits_sum = 0;
+ for (int i = 0; i < bits.length; i++)
+ {
+ if (bits [i] < 0)
+ throw new IllegalArgumentException ();
+
+ bits_sum |= bits [i];
+ }
+
+ if ((bits.length < cspace.getNumComponents())
+ || (bits_sum < 1))
+ throw new IllegalArgumentException ();
+
+ this.pixel_bits = pixel_bits;
+ this.bits = bits;
+ this.cspace = cspace;
+ this.hasAlpha = hasAlpha;
+ this.isAlphaPremultiplied = isAlphaPremultiplied;
+ this.transparency = transparency;
+ this.transferType = transferType;
+ }
+
+ public void finalize()
+ {
+ // Do nothing here.
+ }
+
+ /**
+ * Returns the default color model which in Sun's case is an instance
+ * of <code>DirectColorModel</code>.
+ */
+ public static ColorModel getRGBdefault()
+ {
+ return S_RGB_MODEL;
+ }
+
+ public final boolean hasAlpha()
+ {
+ return hasAlpha;
+ }
+
+ public final boolean isAlphaPremultiplied()
+ {
+ return isAlphaPremultiplied;
+ }
+
+ /**
+ * Get get number of bits wide used for the bit size of pixel values
+ */
+ public int getPixelSize()
+ {
+ return pixel_bits;
+ }
+
+ public int getComponentSize(int componentIdx)
+ {
+ return bits[componentIdx];
+ }
+
+ public int[] getComponentSize()
+ {
+ return bits;
+ }
+
+ public int getTransparency()
+ {
+ return transparency;
+ }
+
+ public int getNumComponents()
+ {
+ return getNumColorComponents() + (hasAlpha ? 1 : 0);
+ }
+
+ public int getNumColorComponents()
+ {
+ return cspace.getNumComponents();
+ }
+
+ /**
+ * Converts pixel value to sRGB and extract red int sample scaled
+ * to range [0, 255].
+ *
+ * @param pixel pixel value that will be interpreted according to
+ * the color model, (assumed alpha premultiplied if color model says
+ * so.)
+ *
+ * @return red sample scaled to range [0, 255], from default color
+ * space sRGB, alpha non-premultiplied.
+ */
+ public abstract int getRed(int pixel);
+
+ /**
+ * Converts pixel value to sRGB and extract green int sample
+ * scaled to range [0, 255].
+ *
+ * @see #getRed(int)
+ */
+ public abstract int getGreen(int pixel);
+
+ /**
+ * Converts pixel value to sRGB and extract blue int sample
+ * scaled to range [0, 255].
+ *
+ * @see #getRed(int)
+ */
+ public abstract int getBlue(int pixel);
+
+ /**
+ * Extract alpha int sample from pixel value, scaled to [0, 255].
+ *
+ * @param pixel pixel value that will be interpreted according to
+ * the color model.
+ *
+ * @return alpha sample, scaled to range [0, 255].
+ */
+ public abstract int getAlpha(int pixel);
+
+ /**
+ * Converts a pixel int value of the color space of the color
+ * model to a sRGB pixel int value.
+ *
+ * This method is typically overriden in subclasses to provide a
+ * more efficient implementation.
+ *
+ * @param pixel pixel value that will be interpreted according to
+ * the color model.
+ *
+ * @return a pixel in sRGB color space, encoded in default
+ * 0xAARRGGBB format. */
+ public int getRGB(int pixel)
+ {
+ return
+ ((getAlpha(pixel) & 0xff) << 24) |
+ (( getRed(pixel) & 0xff) << 16) |
+ ((getGreen(pixel) & 0xff) << 8) |
+ (( getBlue(pixel) & 0xff) << 0);
+ }
+
+
+ /**
+ * In this color model we know that the whole pixel value will
+ * always be contained within the first element of the pixel
+ * array.
+ */
+ final int getPixelFromArray(Object inData) {
+ DataBuffer data =
+ Buffers.createBufferFromData(transferType, inData, 1);
+ Object da = Buffers.getData(data);
+
+ return data.getElem(0);
+ }
+
+ /**
+ * Converts pixel in the given array to sRGB and extract blue int
+ * sample scaled to range [0-255].
+ *
+ * This method is typically overriden in subclasses to provide a
+ * more efficient implementation.
+ *
+ * @param inData array of transferType containing a single pixel. The
+ * pixel should be encoded in the natural way of the color model.
+ */
+ public int getRed(Object inData)
+ {
+ return getRed(getPixelFromArray(inData));
+ }
+
+ /**
+ * @see #getRed(Object)
+ */
+ public int getGreen(Object inData)
+ {
+ return getGreen(getPixelFromArray(inData));
+ }
+
+ /**
+ * @see #getRed(Object)
+ */
+ public int getBlue(Object inData) {
+ return getBlue(getPixelFromArray(inData));
+ }
+
+ /**
+ * @see #getRed(Object)
+ */
+ public int getAlpha(Object inData) {
+ return getAlpha(getPixelFromArray(inData));
+ }
+
+ /**
+ * Converts a pixel in the given array of the color space of the
+ * color model to an sRGB pixel int value.
+ *
+ * <p>This method performs the inverse function of
+ * <code>getDataElements(int rgb, Object pixel)</code>.
+ * I.e. <code>(rgb == cm.getRGB(cm.getDataElements(rgb,
+ * null)))</code>.
+ *
+ * @param inData array of transferType containing a single pixel. The
+ * pixel should be encoded in the natural way of the color model.
+ *
+ * @return a pixel in sRGB color space, encoded in default
+ * 0xAARRGGBB format.
+ *
+ * @see #getDataElements(int, Object)
+ */
+ public int getRGB(Object inData)
+ {
+ return
+ ((getAlpha(inData) & 0xff) << 24) |
+ (( getRed(inData) & 0xff) << 16) |
+ ((getGreen(inData) & 0xff) << 8) |
+ (( getBlue(inData) & 0xff) << 0);
+ }
+
+ /**
+ * Converts an sRGB pixel int value to an array containing a
+ * single pixel of the color space of the color model.
+ *
+ * <p>This method performs the inverse function of
+ * <code>getRGB(Object inData)</code>.
+ *
+ * Outline of conversion process:
+ *
+ * <ol>
+ *
+ * <li>Convert rgb to normalized [0.0, 1.0] sRGB values.</li>
+ *
+ * <li>Convert to color space components using fromRGB in
+ * ColorSpace.</li>
+ *
+ * <li>If color model has alpha and should be premultiplied,
+ * multiply color space components with alpha value</li>
+ *
+ * <li>Scale the components to the correct number of bits.</li>
+ *
+ * <li>Arrange the components in the output array</li>
+ *
+ * </ol>
+ *
+ * @param rgb The color to be converted to dataElements. A pixel
+ * in sRGB color space, encoded in default 0xAARRGGBB format,
+ * assumed not alpha premultiplied.
+ *
+ * @param pixel to avoid needless creation of arrays, an array to
+ * use to return the pixel can be given. If null, a suitable array
+ * will be created.
+ *
+ * @return An array of transferType values representing the color,
+ * in the color model format. The color model defines whether the
+ *
+ * @see #getRGB(Object)
+ */
+ public Object getDataElements(int rgb, Object pixel)
+ {
+ // subclasses has to implement this method.
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Fills an array with the unnormalized component samples from a
+ * pixel value. I.e. decompose the pixel, but not perform any
+ * color conversion.
+ *
+ * This method is typically overriden in subclasses to provide a
+ * more efficient implementation.
+ *
+ * @param pixel pixel value encoded according to the color model.
+ *
+ * @return arrays of unnormalized component samples of single
+ * pixel. The scale and multiplication state of the samples are
+ * according to the color model. Each component sample is stored
+ * as a separate element in the array.
+ */
+ public int[] getComponents(int pixel, int[] components, int offset)
+ {
+ // subclasses has to implement this method.
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Fills an array with the unnormalized component samples from an
+ * array of transferType containing a single pixel. I.e. decompose
+ * the pixel, but not perform any color conversion.
+ *
+ * This method is typically overriden in subclasses to provide a
+ * more efficient implementation.
+ *
+ * @param pixel an array of transferType containing a single pixel. The
+ * pixel should be encoded in the natural way of the color model. If
+ * this argument is not an array, as expected, a {@link ClassCastException}
+ * will be thrown.
+ * @param components an array that will be filled with the color component
+ * of the pixel. If this is null, a new array will be allocated
+ * @param offset index into the components array at which the result
+ * will be stored
+ *
+ * @return arrays of unnormalized component samples of single
+ * pixel. The scale and multiplication state of the samples are
+ * according to the color model. Each component sample is stored
+ * as a separate element in the array.
+ */
+ public int[] getComponents(Object pixel, int[] components, int offset)
+ {
+ // subclasses has to implement this method.
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Convert normalized components to unnormalized components.
+ */
+ public int[] getUnnormalizedComponents(float[] normComponents,
+ int normOffset,
+ int[] components,
+ int offset)
+ {
+ int numComponents = getNumComponents();
+ if (components == null)
+ {
+ components = new int[offset + numComponents];
+ }
+
+ for (int i=0; i<numComponents; i++)
+ {
+ float in = normComponents[normOffset++];
+ int out = (int) (in * ((1<<getComponentSize(i)) - 1));
+ components[offset++] = out;
+ }
+ return components;
+ }
+
+ /**
+ * Convert unnormalized components to normalized components.
+ */
+ public float[] getNormalizedComponents(int[] components,
+ int offset,
+ float[] normComponents,
+ int normOffset)
+ {
+ int numComponents = getNumComponents();
+ if (normComponents == null)
+ {
+ normComponents = new float[normOffset + numComponents];
+ }
+
+ for (int i=0; i<numComponents; i++)
+ {
+ float in = components[offset++];
+ float out = in / ((1<<getComponentSize(i)) - 1);
+ normComponents[normOffset++] = out;
+ }
+ return normComponents;
+ }
+
+ /**
+ * Convert unnormalized components to normalized components.
+ *
+ * @since 1.4
+ */
+ public float[] getNormalizedComponents (Object pixel,
+ float[] normComponents,
+ int normOffset)
+ {
+ int[] components = getComponents(pixel, null, 0);
+ return getNormalizedComponents(components, 0, normComponents, normOffset);
+ }
+
+ /**
+ * Converts the unnormalized component samples from an array to a
+ * pixel value. I.e. composes the pixel from component samples, but
+ * does not perform any color conversion or scaling of the samples.
+ *
+ * This method performs the inverse function of
+ * <code>getComponents(int pixel, int[] components,
+ * int offset)</code>. I.e.
+ *
+ * <code>(pixel == cm.getDataElement(cm.getComponents(pixel, null,
+ * 0), 0))</code>.
+ *
+ * This method is overriden in subclasses since this abstract class throws
+ * UnsupportedOperationException().
+ *
+ * @param components Array of unnormalized component samples of single
+ * pixel. The scale and multiplication state of the samples are according
+ * to the color model. Each component sample is stored as a separate element
+ * in the array.
+ * @param offset Position of the first value of the pixel in components.
+ *
+ * @return pixel value encoded according to the color model.
+ */
+ public int getDataElement(int[] components, int offset)
+ {
+ // subclasses have to implement this method.
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Converts the normalized component samples from an array to a pixel
+ * value. I.e. composes the pixel from component samples, but does not
+ * perform any color conversion or scaling of the samples.
+ *
+ * This method is typically overriden in subclasses to provide a
+ * more efficient implementation. The method provided by this abstract
+ * class converts the components to unnormalized form and returns
+ * getDataElement(int[], int).
+ *
+ * @param components Array of normalized component samples of single pixel.
+ * The scale and multiplication state of the samples are according to the
+ * color model. Each component sample is stored as a separate element in the
+ * array.
+ * @param offset Position of the first value of the pixel in components.
+ *
+ * @return pixel value encoded according to the color model.
+ * @since 1.4
+ */
+ public int getDataElement (float[] components, int offset)
+ {
+ return
+ getDataElement(getUnnormalizedComponents(components, offset, null, 0),
+ 0);
+ }
+
+ public Object getDataElements(int[] components, int offset, Object obj)
+ {
+ // subclasses have to implement this method.
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Converts the normalized component samples from an array to an array of
+ * TransferType values. I.e. composes the pixel from component samples, but
+ * does not perform any color conversion or scaling of the samples.
+ *
+ * If obj is null, a new array of TransferType is allocated and returned.
+ * Otherwise the results are stored in obj and obj is returned. If obj is
+ * not long enough, ArrayIndexOutOfBounds is thrown. If obj is not an array
+ * of primitives, ClassCastException is thrown.
+ *
+ * This method is typically overriden in subclasses to provide a
+ * more efficient implementation. The method provided by this abstract
+ * class converts the components to unnormalized form and returns
+ * getDataElement(int[], int, Object).
+ *
+ * @param components Array of normalized component samples of single pixel.
+ * The scale and multiplication state of the samples are according to the
+ * color model. Each component sample is stored as a separate element in the
+ * array.
+ * @param offset Position of the first value of the pixel in components.
+ * @param obj Array of TransferType or null.
+ *
+ * @return pixel value encoded according to the color model.
+ * @throws ArrayIndexOutOfBoundsException
+ * @throws ClassCastException
+ * @since 1.4
+ */
+ public Object getDataElements(float[] components, int offset, Object obj)
+ {
+ return
+ getDataElements(getUnnormalizedComponents(components, offset, null, 0),
+ 0, obj);
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof ColorModel)) return false;
+
+ ColorModel o = (ColorModel) obj;
+ return
+ (pixel_bits == o.pixel_bits) &&
+ (transferType == o.transferType) &&
+ (transparency == o.transparency) &&
+ (hasAlpha == o.hasAlpha) &&
+ (isAlphaPremultiplied == o.isAlphaPremultiplied) &&
+ Arrays.equals(bits, o.bits) &&
+ (cspace.equals(o.cspace));
+ }
+
+ public final ColorSpace getColorSpace()
+ {
+ return cspace;
+ }
+
+ public ColorModel coerceData(WritableRaster raster,
+ boolean isAlphaPremultiplied)
+ {
+ // This method should always be overridden, but is not abstract.
+ throw new UnsupportedOperationException();
+ }
+
+ void coerceDataWorker(WritableRaster raster,
+ boolean isAlphaPremultiplied)
+ {
+ int w = raster.getWidth();
+ int h = raster.getHeight();
+ int x = raster.getMinX();
+ int y = raster.getMinY();
+ int size = w * h;
+ int numColors = getNumColorComponents();
+ int numComponents = getNumComponents();
+ int alphaScale = (1 << getComponentSize(numColors)) - 1;
+ double[] pixels = raster.getPixels(x, y, w, h, (double[]) null);
+
+ for (int i = 0; i < size; i++)
+ {
+ double alpha = pixels[i * numComponents + numColors] / alphaScale;
+ for (int c = 0; c < numColors; c++)
+ {
+ int offset = i * numComponents + c;
+ if (isAlphaPremultiplied)
+ pixels[offset] = Math.round(pixels[offset] * alpha);
+ else
+ pixels[offset] = Math.round(pixels[offset] / alpha);
+ }
+ }
+
+ raster.setPixels(0, 0, w, h, pixels);
+ }
+
+ /**
+ * Checks if the given raster has a compatible data-layout (SampleModel).
+ * @param raster The Raster to test.
+ * @return true if raster is compatible.
+ */
+ public boolean isCompatibleRaster(Raster raster)
+ {
+ SampleModel sampleModel = raster.getSampleModel();
+ return isCompatibleSampleModel(sampleModel);
+ }
+
+ // Typically overridden
+ public WritableRaster createCompatibleWritableRaster(int w, int h)
+ {
+ return new WritableRaster(createCompatibleSampleModel(w, h),
+ new Point(0, 0));
+ }
+
+ // Typically overridden
+ public SampleModel createCompatibleSampleModel(int w, int h)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ // Typically overridden
+ public boolean isCompatibleSampleModel(SampleModel sm)
+ {
+ return sm.getTransferType() == transferType;
+ }
+
+ public final int getTransferType ()
+ {
+ return transferType;
+ }
+
+ /**
+ * Subclasses must override this method if it is possible for the
+ * color model to have an alpha channel.
+ *
+ * @return null, as per JDK 1.3 doc. Subclasses will only return
+ * null if no alpha raster exists.
+ */
+ public WritableRaster getAlphaRaster(WritableRaster raster)
+ {
+ return null;
+
+ /* It is a mystery to me why we couldn't use the following code...
+
+
+ if (!hasAlpha()) return null;
+
+ SampleModel sm = raster.getSampleModel();
+ int[] alphaBand = { sm.getNumBands() - 1 };
+ SampleModel alphaModel = sm.createSubsetSampleModel(alphaBand);
+ DataBuffer buffer = raster.getDataBuffer();
+ Point origin = new Point(0, 0);
+ return Raster.createWritableRaster(alphaModel, buffer, origin);
+
+
+ ...here, and avoided overriding the method in subclasses,
+ but the Sun docs state that this method always will return
+ null, and that overriding is required. Oh, well.
+ */
+ }
+
+ String stringParam()
+ {
+ return "pixel_bits=" + pixel_bits +
+ ", cspace=" + cspace +
+ ", transferType=" + transferType +
+ ", transparency=" + transparency +
+ ", hasAlpha=" + hasAlpha +
+ ", isAlphaPremultiplied=" + isAlphaPremultiplied;
+ }
+
+ public String toString()
+ {
+ return getClass().getName() + "[" + stringParam() + "]";
+ }
+
+ /**
+ * A color model optimized for standard sRGB.
+ */
+ private static class SRGBColorModel
+ extends DirectColorModel
+ {
+
+ SRGBColorModel()
+ {
+ super(32,0x00FF0000,0x0000FF00,0x000000FF,0xFF000000);
+ }
+
+ public int getAlpha(Object inData)
+ {
+ return ((((int[]) inData)[0]) >> 24) & 0xFF;
+ }
+
+ public int getBlue(Object inData)
+ {
+ return ((((int[]) inData)[0])) & 0xFF;
+ }
+
+ public int getGreen(Object inData)
+ {
+ return ((((int[]) inData)[0]) >> 8) & 0xFF;
+ }
+
+ public int getRed(Object inData)
+ {
+ return ((((int[]) inData)[0]) >> 16) & 0xFF;
+ }
+
+ public int getRGB(Object inData)
+ {
+ return ((int[]) inData)[0];
+ }
+
+ public Object getDataElements(int rgb, Object pixel)
+ {
+ if(pixel == null)
+ {
+ pixel = new int[]{rgb};
+ }
+ else
+ {
+ ((int[]) pixel)[0] = rgb;
+ }
+
+ return pixel;
+ }
+ }
+}
diff --git a/libjava/classpath/java/awt/image/ComponentColorModel.java b/libjava/classpath/java/awt/image/ComponentColorModel.java
new file mode 100644
index 000000000..ef0b84f00
--- /dev/null
+++ b/libjava/classpath/java/awt/image/ComponentColorModel.java
@@ -0,0 +1,408 @@
+/* ComponentColorModel.java --
+ Copyright (C) 2000, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import gnu.java.awt.Buffers;
+
+import java.awt.Point;
+import java.awt.color.ColorSpace;
+import java.util.Arrays;
+
+public class ComponentColorModel extends ColorModel
+{
+ // Find sum of all elements of the array.
+ private static int sum(int[] values)
+ {
+ int sum = 0;
+ for (int i=0; i<values.length; i++)
+ sum += values[i];
+ return sum;
+ }
+
+ // Create an appropriate array of bits, given a colorspace (ie, number of
+ // bands), size of the storage data type, and presence of an alpha band.
+ private static int[] findBits(ColorSpace colorSpace, int transferType,
+ boolean hasAlpha)
+ {
+ int[] bits;
+ if (hasAlpha)
+ bits = new int[colorSpace.getNumComponents()+1];
+ else
+ bits = new int[colorSpace.getNumComponents()];
+
+ Arrays.fill(bits, DataBuffer.getDataTypeSize(transferType));
+
+ return bits;
+ }
+
+ public ComponentColorModel(ColorSpace colorSpace, int[] bits,
+ boolean hasAlpha,
+ boolean isAlphaPremultiplied,
+ int transparency, int transferType)
+ {
+ super(sum(bits), bits, colorSpace, hasAlpha, isAlphaPremultiplied,
+ transparency, transferType);
+ }
+
+ /**
+ * Construct a new ComponentColorModel.
+ *
+ * This constructor makes all bits of each sample significant, so for a
+ * transferType of DataBuffer.BYTE, the bits per sample is 8, etc. If
+ * both hasAlpha and isAlphaPremultiplied are true, color samples are
+ * assumed to be premultiplied by the alpha component. Transparency may be
+ * one of OPAQUE, BITMASK, or TRANSLUCENT.
+ *
+ * @param colorSpace The colorspace for this color model.
+ * @param hasAlpha True if there is an alpha component.
+ * @param isAlphaPremultiplied True if colors are already multiplied by
+ * alpha.
+ * @param transparency The type of alpha values.
+ * @param transferType Data type of pixel sample values.
+ * @since 1.4
+ */
+ public ComponentColorModel(ColorSpace colorSpace,
+ boolean hasAlpha,
+ boolean isAlphaPremultiplied,
+ int transparency, int transferType)
+ {
+ this(colorSpace, findBits(colorSpace, transferType, hasAlpha), hasAlpha,
+ isAlphaPremultiplied, transparency, transferType);
+ }
+
+ public int getRed(int pixel)
+ {
+ if (getNumComponents()>1) throw new IllegalArgumentException();
+ return (int) getRGBFloat(pixel)[0];
+ }
+
+ public int getGreen(int pixel)
+ {
+ if (getNumComponents()>1) throw new IllegalArgumentException();
+ return (int) getRGBFloat(pixel)[0];
+ }
+
+ public int getBlue(int pixel)
+ {
+ if (getNumComponents()>1) throw new IllegalArgumentException();
+ return (int) getRGBFloat(pixel)[0];
+ }
+
+ public int getAlpha(int pixel)
+ {
+ if (getNumComponents()>1) throw new IllegalArgumentException();
+ int shift = 8 - getComponentSize(getNumColorComponents());
+ if (shift >= 0) return pixel << shift;
+ return pixel >> (-shift);
+ }
+
+ public int getRGB(int pixel)
+ {
+ float[] rgb = getRGBFloat(pixel);
+ int ret = getRGB(rgb);
+ if (hasAlpha()) ret |= getAlpha(pixel) << 24;
+ return ret;
+ }
+
+
+ /* Note, it's OK to pass a to large array to toRGB(). Extra
+ elements are ignored. */
+
+ private float[] getRGBFloat(int pixel)
+ {
+ float[] data = { pixel };
+ return cspace.toRGB(data);
+ }
+
+ private float[] getRGBFloat(Object inData)
+ {
+ DataBuffer buffer =
+ Buffers.createBufferFromData(transferType, inData,
+ getNumComponents());
+ int colors = getNumColorComponents();
+ float[] data = new float[colors];
+
+ // FIXME: unpremultiply data that is premultiplied
+ for (int i=0; i<colors; i++)
+ {
+ float maxValue = (1<<getComponentSize(i))-1;
+ data[i] = buffer.getElemFloat(i)/maxValue;
+ }
+ float[] rgb = cspace.toRGB(data);
+ return rgb;
+ }
+
+ public int getRed(Object inData)
+ {
+ return (int) getRGBFloat(inData)[0]*255;
+ }
+
+ public int getGreen(Object inData)
+ {
+ return (int) getRGBFloat(inData)[1]*255;
+ }
+
+ public int getBlue(Object inData)
+ {
+ return (int) getRGBFloat(inData)[2]*255;
+ }
+
+ public int getAlpha(Object inData)
+ {
+ DataBuffer buffer =
+ Buffers.createBufferFromData(transferType, inData,
+ getNumComponents());
+ int shift = 8 - getComponentSize(getNumColorComponents());
+ int alpha = buffer.getElem(getNumColorComponents());
+ if (shift >= 0) return alpha << shift;
+ return alpha >> (-shift);
+ }
+
+ private int getRGB(float[] rgb)
+ {
+ /* NOTE: We could cast to byte instead of int here. This would
+ avoid bits spilling over from one bit field to
+ another. But, if we assume that floats are in the [0.0,
+ 1.0] range, this will never happen anyway. */
+
+ /* Remember to multiply BEFORE casting to int, otherwise, decimal
+ point data will be lost. */
+ int ret =
+ (((int) (rgb[0]*255F)) << 16) |
+ (((int) (rgb[1]*255F)) << 8) |
+ (((int) (rgb[2]*255F)) << 0);
+ return ret;
+ }
+
+ /**
+ * @param inData pixel data of transferType, as returned by the
+ * getDataElements method in SampleModel.
+ */
+ public int getRGB(Object inData)
+ {
+ float[] rgb = getRGBFloat(inData);
+ int ret = getRGB(rgb);
+ if (hasAlpha()) ret |= getAlpha(inData) << 24;
+ return ret;
+ }
+
+ public Object getDataElements(int rgb, Object pixel)
+ {
+ // Convert rgb to [0.0, 1.0] sRGB values.
+ float[] rgbFloats = {
+ ((rgb >> 16)&0xff)/255.0F,
+ ((rgb >> 8)&0xff)/255.0F,
+ ((rgb >> 0)&0xff)/255.0F
+ };
+
+ // Convert from rgb to color space components.
+ float[] data = cspace.fromRGB(rgbFloats);
+ DataBuffer buffer = Buffers.createBuffer(transferType, pixel,
+ getNumComponents());
+ int numColors = getNumColorComponents();
+
+ if (hasAlpha())
+ {
+ float alpha = ((rgb >> 24)&0xff)/255.0F;
+
+ /* If color model has alpha and should be premultiplied, multiply
+ color space components with alpha value. */
+ if (isAlphaPremultiplied()) {
+ for (int i=0; i<numColors; i++)
+ data[i] *= alpha;
+ }
+ // Scale the alpha sample to the correct number of bits.
+ alpha *= (1<<(bits[numColors]-1));
+ // Arrange the alpha sample in the output array.
+ buffer.setElemFloat(numColors, alpha);
+ }
+ for (int i=0; i<numColors; i++)
+ {
+ // Scale the color samples to the correct number of bits.
+ float value = data[i]*(1<<(bits[i]-1));
+ // Arrange the color samples in the output array.
+ buffer.setElemFloat(i, value);
+ }
+ return Buffers.getData(buffer);
+ }
+
+ public int[] getComponents(int pixel, int[] components, int offset)
+ {
+ if (getNumComponents()>1) throw new IllegalArgumentException();
+ if (components == null)
+ components = new int[getNumComponents() + offset];
+ components[offset] = pixel;
+ return components;
+ }
+
+ public int[] getComponents(Object pixel, int[] components, int offset)
+ {
+ DataBuffer buffer = Buffers.createBuffer(transferType, pixel,
+ getNumComponents());
+ int numComponents = getNumComponents();
+
+ if (components == null)
+ components = new int[numComponents + offset];
+
+ for (int i=0; i<numComponents; i++)
+ components[offset++] = buffer.getElem(i);
+
+ return components;
+ }
+
+ public int getDataElement(int[] components, int offset)
+ {
+ if (getNumComponents()>1) throw new IllegalArgumentException();
+ return components[offset];
+ }
+
+ public Object getDataElements(int[] components, int offset, Object obj)
+ {
+ DataBuffer buffer = Buffers.createBuffer(transferType, obj,
+ getNumComponents());
+ int numComponents = getNumComponents();
+
+ for (int i=0; i<numComponents; i++)
+ buffer.setElem(i, components[offset++]);
+
+ return Buffers.getData(buffer);
+ }
+
+ public ColorModel coerceData(WritableRaster raster,
+ boolean isAlphaPremultiplied) {
+ if (this.isAlphaPremultiplied == isAlphaPremultiplied || !hasAlpha())
+ return this;
+
+ /* TODO: provide better implementation based on the
+ assumptions we can make due to the specific type of the
+ color model. */
+ coerceDataWorker(raster, isAlphaPremultiplied);
+
+ return new ComponentColorModel(cspace, hasAlpha, isAlphaPremultiplied,
+ transparency, transferType);
+ }
+
+ public boolean isCompatibleRaster(Raster raster)
+ {
+ return super.isCompatibleRaster(raster);
+ // FIXME: Should we test something more here? (Why override?)
+ }
+
+ public WritableRaster createCompatibleWritableRaster(int w, int h)
+ {
+ SampleModel sm = createCompatibleSampleModel(w, h);
+ Point origin = new Point(0, 0);
+ return Raster.createWritableRaster(sm, origin);
+ }
+
+
+ /**
+ * Creates a <code>SampleModel</code> whose arrangement of pixel
+ * data is compatible to this <code>ColorModel</code>.
+ *
+ * @param w the number of pixels in the horizontal direction.
+ * @param h the number of pixels in the vertical direction.
+ */
+ public SampleModel createCompatibleSampleModel(int w, int h)
+ {
+ int pixelStride, scanlineStride;
+ int[] bandOffsets;
+
+ pixelStride = getNumComponents();
+ scanlineStride = pixelStride * w;
+
+ /* We might be able to re-use the same bandOffsets array among
+ * multiple calls to this method. However, this optimization does
+ * not seem worthwile because setting up descriptive data
+ * structures (such as SampleModels) is neglectible in comparision
+ * to shuffling around masses of pixel data.
+ */
+ bandOffsets = new int[pixelStride];
+ for (int i = 0; i < pixelStride; i++)
+ bandOffsets[i] = i;
+
+ /* FIXME: Think about whether it would make sense to return the
+ * possibly more efficient PixelInterleavedSampleModel for other
+ * transferTypes as well. It seems unlikely that this would break
+ * any user applications, so the Mauve tests on this method
+ * might be too restrictive.
+ */
+ switch (transferType)
+ {
+ case DataBuffer.TYPE_BYTE:
+ case DataBuffer.TYPE_USHORT:
+ return new PixelInterleavedSampleModel(transferType, w, h,
+ pixelStride,
+ scanlineStride,
+ bandOffsets);
+
+ default:
+ return new ComponentSampleModel(transferType, w, h,
+ pixelStride,
+ scanlineStride,
+ bandOffsets);
+ }
+ }
+
+
+ public boolean isCompatibleSampleModel(SampleModel sm)
+ {
+ return
+ (sm instanceof ComponentSampleModel) &&
+ super.isCompatibleSampleModel(sm);
+ }
+
+ public WritableRaster getAlphaRaster(WritableRaster raster)
+ {
+ if (!hasAlpha()) return null;
+
+ SampleModel sm = raster.getSampleModel();
+ int[] alphaBand = { sm.getNumBands() - 1 };
+ SampleModel alphaModel = sm.createSubsetSampleModel(alphaBand);
+ DataBuffer buffer = raster.getDataBuffer();
+ Point origin = new Point(0, 0);
+ return Raster.createWritableRaster(alphaModel, buffer, origin);
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof ComponentColorModel)) return false;
+ return super.equals(obj);
+ }
+}
diff --git a/libjava/classpath/java/awt/image/ComponentSampleModel.java b/libjava/classpath/java/awt/image/ComponentSampleModel.java
new file mode 100644
index 000000000..f32eae319
--- /dev/null
+++ b/libjava/classpath/java/awt/image/ComponentSampleModel.java
@@ -0,0 +1,755 @@
+/* Copyright (C) 2000, 2002, 2006, Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+import java.util.Arrays;
+
+/**
+ * ComponentSampleModel supports a flexible organization of pixel samples in
+ * memory, permitting pixel samples to be interleaved by band, by scanline,
+ * and by pixel.
+ *
+ * A DataBuffer for this sample model has K banks of data. Pixels have N
+ * samples, so there are N bands in the DataBuffer. Each band is completely
+ * contained in one bank of data, but a bank may contain more than one band.
+ * Each pixel sample is stored in a single data element.
+ *
+ * Within a bank, each band begins at an offset stored in bandOffsets. The
+ * banks containing the band is given by bankIndices. Within the bank, there
+ * are three dimensions - band, pixel, and scanline. The dimension ordering
+ * is controlled by bandOffset, pixelStride, and scanlineStride, which means
+ * that any combination of interleavings is supported.
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public class ComponentSampleModel extends SampleModel
+{
+ /** The offsets to the first sample for each band. */
+ protected int[] bandOffsets;
+
+ /** The indices of the bank used to store each band in a data buffer. */
+ protected int[] bankIndices;
+
+ /**
+ * The number of bands in the image.
+ * @specnote This field shadows the protected numBands in SampleModel.
+ */
+ protected int numBands;
+
+ /** Used when creating data buffers. */
+ protected int numBanks;
+
+ /**
+ * The number of data elements between a sample in one row and the
+ * corresponding sample in the next row.
+ */
+ protected int scanlineStride;
+
+ /**
+ * The number of data elements between a sample for one pixel and the
+ * corresponding sample for the next pixel in the same row.
+ */
+ protected int pixelStride;
+
+ /**
+ * Creates a new sample model that assumes that all bands are stored in a
+ * single bank of the {@link DataBuffer}.
+ * <p>
+ * Note that the <code>bandOffsets</code> array is copied to internal storage
+ * to prevent subsequent changes to the array from affecting this object.
+ *
+ * @param dataType the data type (one of {@link DataBuffer#TYPE_BYTE},
+ * {@link DataBuffer#TYPE_USHORT}, {@link DataBuffer#TYPE_SHORT},
+ * {@link DataBuffer#TYPE_INT}, {@link DataBuffer#TYPE_FLOAT} or
+ * {@link DataBuffer#TYPE_DOUBLE}).
+ * @param w the width in pixels.
+ * @param h the height in pixels.
+ * @param pixelStride the number of data elements in the step from a sample
+ * in one pixel to the corresponding sample in the next pixel.
+ * @param scanlineStride the number of data elements in the step from a
+ * sample in a pixel to the corresponding sample in the pixel in the next
+ * row.
+ * @param bandOffsets the offset to the first element for each band, with
+ * the size of the array defining the number of bands (<code>null</code>
+ * not permitted).
+ *
+ * @throws IllegalArgumentException if <code>dataType</code> is not one of
+ * the specified values.
+ * @throws IllegalArgumentException if <code>w</code> is less than or equal
+ * to zero.
+ * @throws IllegalArgumentException if <code>h</code> is less than or equal
+ * to zero.
+ * @throws IllegalArgumentException if <code>w * h</code> exceeds
+ * {@link Integer#MAX_VALUE}.
+ * @throws IllegalArgumentException if <code>pixelStride</code> is negative.
+ * @throws IllegalArgumentException if <code>scanlineStride</code> is less
+ * than or equal to zero.
+ * @throws IllegalArgumentException if <code>bandOffsets</code> has zero
+ * length.
+ */
+ public ComponentSampleModel(int dataType,
+ int w, int h,
+ int pixelStride,
+ int scanlineStride,
+ int[] bandOffsets)
+ {
+ this(dataType, w, h, pixelStride, scanlineStride,
+ new int[bandOffsets.length], bandOffsets);
+ }
+
+ /**
+ * Creates a new sample model that assumes that all bands are stored in a
+ * single bank of the {@link DataBuffer}.
+ *
+ * @param dataType the data type (one of {@link DataBuffer#TYPE_BYTE},
+ * {@link DataBuffer#TYPE_USHORT}, {@link DataBuffer#TYPE_SHORT},
+ * {@link DataBuffer#TYPE_INT}, {@link DataBuffer#TYPE_FLOAT} or
+ * {@link DataBuffer#TYPE_DOUBLE}).
+ * @param w the width in pixels.
+ * @param h the height in pixels.
+ * @param pixelStride the number of data elements in the step from a sample
+ * in one pixel to the corresponding sample in the next pixel.
+ * @param scanlineStride the number of data elements in the step from a
+ * sample in a pixel to the corresponding sample in the pixel in the next
+ * row.
+ * @param bankIndices the index of the bank in which each band is stored
+ * (<code>null</code> not permitted). This array is copied to internal
+ * storage so that subsequent updates to the array do not affect the sample
+ * model.
+ * @param bandOffsets the offset to the first element for each band, with
+ * the size of the array defining the number of bands (<code>null</code>
+ * not permitted). This array is copied to internal storage so that
+ * subsequent updates to the array do not affect the sample model.
+ *
+ * @throws IllegalArgumentException if <code>dataType</code> is not one of
+ * the specified values.
+ * @throws IllegalArgumentException if <code>w</code> is less than or equal
+ * to zero.
+ * @throws IllegalArgumentException if <code>h</code> is less than or equal
+ * to zero.
+ * @throws IllegalArgumentException if <code>w * h</code> exceeds
+ * {@link Integer#MAX_VALUE}.
+ * @throws IllegalArgumentException if <code>pixelStride</code> is negative.
+ * @throws IllegalArgumentException if <code>scanlineStride</code> is less
+ * than or equal to zero.
+ * @throws IllegalArgumentException if <code>bandOffsets</code> has zero
+ * length.
+ */
+ public ComponentSampleModel(int dataType,
+ int w, int h,
+ int pixelStride,
+ int scanlineStride,
+ int[] bankIndices,
+ int[] bandOffsets)
+ {
+ super(dataType, w, h, bandOffsets.length);
+
+ // super permits DataBuffer.TYPE_UNDEFINED but this class doesn't...
+ if (dataType == DataBuffer.TYPE_UNDEFINED)
+ throw new IllegalArgumentException("Unsupported dataType.");
+
+ if ((pixelStride < 0) || (scanlineStride < 0) || (bandOffsets.length < 1)
+ || (bandOffsets.length != bankIndices.length))
+ throw new IllegalArgumentException();
+
+ this.bandOffsets = (int[]) bandOffsets.clone();
+ this.bankIndices = (int[]) bankIndices.clone();
+ this.numBands = bandOffsets.length;
+
+ this.numBanks = 0;
+ for (int b = 0; b < bankIndices.length; b++)
+ this.numBanks = Math.max(this.numBanks, bankIndices[b] + 1);
+
+ this.scanlineStride = scanlineStride;
+ this.pixelStride = pixelStride;
+
+ }
+
+ /**
+ * Creates a new sample model that is compatible with this one, but with the
+ * specified dimensions.
+ *
+ * @param w the width (must be greater than zero).
+ * @param h the height (must be greater than zero).
+ *
+ * @return A new sample model.
+ */
+ public SampleModel createCompatibleSampleModel(int w, int h)
+ {
+ return new ComponentSampleModel(dataType, w, h, pixelStride,
+ scanlineStride, bankIndices,
+ bandOffsets);
+ }
+
+ /**
+ * Creates a new sample model that provides access to a subset of the bands
+ * that this sample model supports.
+ *
+ * @param bands the bands (<code>null</code> not permitted).
+ *
+ * @return The new sample model.
+ */
+ public SampleModel createSubsetSampleModel(int[] bands)
+ {
+ int numBands = bands.length;
+
+ int[] bankIndices = new int[numBands];
+ int[] bandOffsets = new int[numBands];
+ for (int b = 0; b < numBands; b++)
+ {
+ bankIndices[b] = this.bankIndices[bands[b]];
+ bandOffsets[b] = this.bandOffsets[bands[b]];
+ }
+
+ return new ComponentSampleModel(dataType, width, height, pixelStride,
+ scanlineStride, bankIndices,
+ bandOffsets);
+ }
+
+ /**
+ * Creates a new data buffer that is compatible with this sample model.
+ *
+ * @return The new data buffer.
+ */
+ public DataBuffer createDataBuffer()
+ {
+ // Maybe this value should be precalculated in the constructor?
+ int highestOffset = 0;
+ for (int b = 0; b < numBands; b++)
+ highestOffset = Math.max(highestOffset, bandOffsets[b]);
+ int size = pixelStride * (width - 1) + scanlineStride * (height - 1)
+ + highestOffset + 1;
+
+ DataBuffer buffer = null;
+ switch (getTransferType())
+ {
+ case DataBuffer.TYPE_BYTE:
+ buffer = new DataBufferByte(size, numBanks);
+ break;
+ case DataBuffer.TYPE_SHORT:
+ buffer = new DataBufferShort(size, numBanks);
+ break;
+ case DataBuffer.TYPE_USHORT:
+ buffer = new DataBufferUShort(size, numBanks);
+ break;
+ case DataBuffer.TYPE_INT:
+ buffer = new DataBufferInt(size, numBanks);
+ break;
+ case DataBuffer.TYPE_FLOAT:
+ buffer = new DataBufferFloat(size, numBanks);
+ break;
+ case DataBuffer.TYPE_DOUBLE:
+ buffer = new DataBufferDouble(size, numBanks);
+ break;
+ }
+ return buffer;
+ }
+
+ /**
+ * Returns the offset of the sample in band 0 for the pixel at location
+ * <code>(x, y)</code>. This offset can be used to read a sample value from
+ * a {@link DataBuffer}.
+ *
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ *
+ * @return The offset.
+ *
+ * @see #getOffset(int, int, int)
+ */
+ public int getOffset(int x, int y)
+ {
+ return getOffset(x, y, 0);
+ }
+
+ /**
+ * Returns the offset of the sample in band <code>b</code> for the pixel at
+ * location <code>(x, y)</code>. This offset can be used to read a sample
+ * value from a {@link DataBuffer}.
+ *
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ * @param b the band index.
+ *
+ * @return The offset.
+ */
+ public int getOffset(int x, int y, int b)
+ {
+ return bandOffsets[b] + pixelStride * x + scanlineStride * y;
+ }
+
+ /**
+ * Returns the size in bits for each sample (one per band). For this sample
+ * model, each band has the same sample size and this is determined by the
+ * data type for the sample model.
+ *
+ * @return The sample sizes.
+ *
+ * @see SampleModel#getDataType()
+ */
+ public final int[] getSampleSize()
+ {
+ int size = DataBuffer.getDataTypeSize(getDataType());
+ int[] sizes = new int[numBands];
+
+ java.util.Arrays.fill(sizes, size);
+ return sizes;
+ }
+
+ /**
+ * Returns the size in bits for the samples in the specified band. In this
+ * class, the sample size is the same for every band and is determined from
+ * the data type for the model.
+ *
+ * @param band the band index (ignored here).
+ *
+ * @return The sample size in bits.
+ *
+ * @see SampleModel#getDataType()
+ */
+ public final int getSampleSize(int band)
+ {
+ return DataBuffer.getDataTypeSize(getDataType());
+ }
+
+ /**
+ * Returns the indices of the bank(s) in the {@link DataBuffer} used to
+ * store the samples for each band. The returned array is a copy, so that
+ * altering it will not impact the sample model.
+ *
+ * @return The bank indices.
+ */
+ public final int[] getBankIndices()
+ {
+ return (int[]) bankIndices.clone();
+ }
+
+ /**
+ * Returns the offsets to the first sample in each band. The returned array
+ * is a copy, so that altering it will not impact the sample model.
+ *
+ * @return The offsets.
+ */
+ public final int[] getBandOffsets()
+ {
+ return (int[]) bandOffsets.clone();
+ }
+
+ /**
+ * Returns the distance (in terms of element indices) between the sample for
+ * one pixel and the corresponding sample for the equivalent pixel in the
+ * next row. This is used in the calculation of the element offset for
+ * retrieving samples from a {@link DataBuffer}.
+ *
+ * @return The distance between pixel samples in consecutive rows.
+ */
+ public final int getScanlineStride()
+ {
+ return scanlineStride;
+ }
+
+ /**
+ * Returns the distance (in terms of element indices) between the sample for
+ * one pixel and the corresponding sample for the next pixel in a row. This
+ * is used in the calculation of the element offset for retrieving samples
+ * from a {@link DataBuffer}.
+ *
+ * @return The distance between pixel samples in the same row.
+ */
+ public final int getPixelStride()
+ {
+ return pixelStride;
+ }
+
+ /**
+ * Returns the number of data elements used to store the samples for one
+ * pixel. In this model, this is the same as the number of bands.
+ *
+ * @return The number of data elements used to store the samples for one
+ * pixel.
+ */
+ public final int getNumDataElements()
+ {
+ return numBands;
+ }
+
+ /**
+ * Returns the samples for the pixel at location <code>(x, y)</code> in
+ * a primitive array (the array type is determined by the data type for
+ * this model). The <code>obj</code> argument provides an option to supply
+ * an existing array to hold the result, if this is <code>null</code> a new
+ * array will be allocated.
+ *
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ * @param obj a primitive array that, if not <code>null</code>, will be
+ * used to store and return the sample values.
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return An array of sample values for the specified pixel.
+ */
+ public Object getDataElements(int x, int y, Object obj, DataBuffer data)
+ {
+ int type = getTransferType();
+ int numDataEls = getNumDataElements();
+ int offset = y * scanlineStride + x * pixelStride;
+ switch (type)
+ {
+ case DataBuffer.TYPE_BYTE:
+ byte[] bData;
+ if (obj == null)
+ bData = new byte[numDataEls];
+ else
+ bData = (byte[]) obj;
+ for (int i = 0; i < numDataEls; i++)
+ {
+ bData[i] = (byte) data.getElem(bankIndices[i],
+ offset + bandOffsets[i]);
+ }
+ obj = bData;
+ break;
+ case DataBuffer.TYPE_SHORT:
+ case DataBuffer.TYPE_USHORT:
+ short[] sData;
+ if (obj == null)
+ sData = new short[numDataEls];
+ else
+ sData = (short[]) obj;
+ for (int i = 0; i < numDataEls; i++)
+ {
+ sData[i] = (short) data.getElem(bankIndices[i],
+ offset + bandOffsets[i]);
+ }
+ obj = sData;
+ break;
+ case DataBuffer.TYPE_INT:
+ int[] iData;
+ if (obj == null)
+ iData = new int[numDataEls];
+ else
+ iData = (int[]) obj;
+ for (int i = 0; i < numDataEls; i++)
+ {
+ iData[i] = data.getElem(bankIndices[i], offset + bandOffsets[i]);
+ }
+ obj = iData;
+ break;
+ case DataBuffer.TYPE_FLOAT:
+ float[] fData;
+ if (obj == null)
+ fData = new float[numDataEls];
+ else
+ fData = (float[]) obj;
+ for (int i = 0; i < numDataEls; i++)
+ {
+ fData[i] = data.getElemFloat(bankIndices[i],
+ offset + bandOffsets[i]);
+ }
+ obj = fData;
+ break;
+ case DataBuffer.TYPE_DOUBLE:
+ double[] dData;
+ if (obj == null)
+ dData = new double[numDataEls];
+ else
+ dData = (double[]) obj;
+ for (int i = 0; i < numDataEls; i++)
+ {
+ dData[i] = data.getElemDouble(bankIndices[i],
+ offset + bandOffsets[i]);
+ }
+ obj = dData;
+ break;
+ }
+ return obj;
+ }
+
+
+ /**
+ * Returns all the samples for the pixel at location <code>(x, y)</code>
+ * stored in the specified data buffer.
+ *
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ * @param iArray an array that will be populated with the sample values and
+ * returned as the result. The size of this array should be equal to the
+ * number of bands in the model. If the array is <code>null</code>, a new
+ * array is created.
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The samples for the specified pixel.
+ *
+ * @see #setPixel(int, int, int[], DataBuffer)
+ */
+ public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
+ {
+ if (x < 0 || x >= width || y < 0 || y >= height)
+ throw new ArrayIndexOutOfBoundsException("Pixel (" + x + ", " + y
+ + ") is out of bounds.");
+ int offset = pixelStride * x + scanlineStride * y;
+ if (iArray == null)
+ iArray = new int[numBands];
+ for (int b = 0; b < numBands; b++)
+ {
+ iArray[b] = data.getElem(bankIndices[b], offset + bandOffsets[b]);
+ }
+ return iArray;
+ }
+
+ /**
+ * Returns the samples for all the pixels in a rectangular region.
+ *
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ * @param w the width.
+ * @param h the height.
+ * @param iArray an array that if non-<code>null</code> will be populated
+ * with the sample values and returned as the result.
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The samples for all the pixels in the rectangle.
+ */
+ public int[] getPixels(int x, int y, int w, int h, int[] iArray,
+ DataBuffer data)
+ {
+ int offset = pixelStride * x + scanlineStride * y;
+ if (iArray == null)
+ iArray = new int[numBands * w * h];
+ int outOffset = 0;
+ for (y = 0; y < h; y++)
+ {
+ int lineOffset = offset;
+ for (x = 0; x < w; x++)
+ {
+ for (int b = 0; b < numBands; b++)
+ {
+ iArray[outOffset++]
+ = data.getElem(bankIndices[b], lineOffset+bandOffsets[b]);
+ }
+ lineOffset += pixelStride;
+ }
+ offset += scanlineStride;
+ }
+ return iArray;
+ }
+
+ /**
+ * Returns the sample for band <code>b</code> of the pixel at
+ * <code>(x, y)</code> that is stored in the specified data buffer.
+ *
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ * @param b the band index.
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The sample value.
+ *
+ * @throws ArrayIndexOutOfBoundsException if <code>(x, y)</code> is outside
+ * the bounds <code>[0, 0, width, height]</code>.
+ *
+ * @see #setSample(int, int, int, int, DataBuffer)
+ */
+ public int getSample(int x, int y, int b, DataBuffer data)
+ {
+ if (x < 0 || x >= width || y < 0 || y >= height)
+ throw new ArrayIndexOutOfBoundsException("Sample (" + x + ", " + y
+ + ") is out of bounds.");
+ return data.getElem(bankIndices[b], getOffset(x, y, b));
+ }
+
+ /**
+ * Sets the samples for the pixel at location <code>(x, y)</code> from the
+ * supplied primitive array (the array type must be consistent with the data
+ * type for this model).
+ *
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ * @param obj a primitive array containing the pixel's sample values.
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @see #setDataElements(int, int, Object, DataBuffer)
+ */
+ public void setDataElements(int x, int y, Object obj, DataBuffer data)
+ {
+ int type = getTransferType();
+ int numDataEls = getNumDataElements();
+ int offset = y * scanlineStride + x * pixelStride;
+ switch (type)
+ {
+ case DataBuffer.TYPE_BYTE:
+ byte[] bData = (byte[]) obj;
+ for (int i = 0; i < numDataEls; i++)
+ {
+ data.setElem(bankIndices[i], offset + bandOffsets[i],
+ ((int) bData[i]) & 0xFF);
+ }
+ break;
+ case DataBuffer.TYPE_SHORT:
+ case DataBuffer.TYPE_USHORT:
+ short[] sData = (short[]) obj;
+ for (int i = 0; i < numDataEls; i++)
+ {
+ data.setElem(bankIndices[i], offset + bandOffsets[i],
+ ((int) sData[i]) & 0xFFFF);
+ }
+ break;
+ case DataBuffer.TYPE_INT:
+ int[] iData = (int[]) obj;
+ for (int i = 0; i < numDataEls; i++)
+ {
+ data.setElem(bankIndices[i], offset + bandOffsets[i], iData[i]);
+ }
+ break;
+ case DataBuffer.TYPE_FLOAT:
+ float[] fData = (float[]) obj;
+ for (int i = 0; i < numDataEls; i++)
+ {
+ data.setElemFloat(bankIndices[i], offset + bandOffsets[i],
+ fData[i]);
+ }
+ break;
+ case DataBuffer.TYPE_DOUBLE:
+ double[] dData = (double[]) obj;
+ for (int i = 0; i < numDataEls; i++)
+ {
+ data.setElemDouble(bankIndices[i], offset + bandOffsets[i],
+ dData[i]);
+ }
+ break;
+ }
+ }
+
+ /**
+ * Sets the sample values for the pixel at location <code>(x, y)</code>
+ * stored in the specified data buffer.
+ *
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ * @param iArray the pixel sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @see #getPixel(int, int, int[], DataBuffer)
+ */
+ public void setPixel(int x, int y, int[] iArray, DataBuffer data)
+ {
+ int offset = pixelStride * x + scanlineStride * y;
+ for (int b = 0; b < numBands; b++)
+ data.setElem(bankIndices[b], offset + bandOffsets[b], iArray[b]);
+ }
+
+ /**
+ * Sets the sample value for band <code>b</code> of the pixel at location
+ * <code>(x, y)</code> in the specified data buffer.
+ *
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ * @param b the band index.
+ * @param s the sample value.
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @see #getSample(int, int, int, DataBuffer)
+ */
+ public void setSample(int x, int y, int b, int s, DataBuffer data)
+ {
+ data.setElem(bankIndices[b], getOffset(x, y, b), s);
+ }
+
+ /**
+ * Tests this sample model for equality with an arbitrary object. Returns
+ * <code>true</code> if and only if:
+ * <ul>
+ * <li><code>obj</code> is not <code>null</code>;</li>
+ * <li><code>obj</code> is an instance of <code>ComponentSampleModel</code>;
+ * </li>
+ * <li>both models have the same values for the <code>dataType</code>,
+ * <code>width</code>, <code>height</code>, <code>pixelStride</code>,
+ * <code>scanlineStride</code>, <code>bandOffsets</code> and
+ * <code>bankIndices</code> fields.</li>
+ * </ul>
+ *
+ * @param obj the object to test (<code>null</code> permitted).
+ *
+ * @return <code>true</code> if this sample model is equal to
+ * <code>obj</code>, and <code>false</code> otherwise.
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ return false;
+ if (! (obj instanceof ComponentSampleModel))
+ return false;
+ ComponentSampleModel that = (ComponentSampleModel) obj;
+ if (this.dataType != that.dataType)
+ return false;
+ if (this.width != that.width)
+ return false;
+ if (this.height != that.height)
+ return false;
+ if (this.pixelStride != that.pixelStride)
+ return false;
+ if (this.scanlineStride != that.scanlineStride)
+ return false;
+ if (! Arrays.equals(this.bandOffsets, that.bandOffsets))
+ return false;
+ if (! Arrays.equals(this.bankIndices, that.bankIndices))
+ return false;
+ // couldn't find any difference, so...
+ return true;
+ }
+
+ /**
+ * Returns a hash code for this sample model.
+ *
+ * @return The hash code.
+ */
+ public int hashCode()
+ {
+ // this computation is based on the method described in Chapter 3
+ // of Joshua Bloch's Effective Java...
+ int result = 17;
+ result = 37 * result + dataType;
+ result = 37 * result + width;
+ result = 37 * result + height;
+ result = 37 * result + pixelStride;
+ result = 37 * result + scanlineStride;
+ for (int i = 0; i < bandOffsets.length; i++)
+ result = 37 * result + bandOffsets[i];
+ for (int i = 0; i < bankIndices.length; i++)
+ result = 37 * result + bankIndices[i];
+ return result;
+ }
+}
diff --git a/libjava/classpath/java/awt/image/ConvolveOp.java b/libjava/classpath/java/awt/image/ConvolveOp.java
new file mode 100644
index 000000000..10b85f446
--- /dev/null
+++ b/libjava/classpath/java/awt/image/ConvolveOp.java
@@ -0,0 +1,380 @@
+/* ConvolveOp.java --
+ Copyright (C) 2004, 2005, 2006, Free Software Foundation -- ConvolveOp
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.RenderingHints;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * Convolution filter.
+ *
+ * ConvolveOp convolves the source image with a Kernel to generate a
+ * destination image. This involves multiplying each pixel and its neighbors
+ * with elements in the kernel to compute a new pixel.
+ *
+ * Each band in a Raster is convolved and copied to the destination Raster.
+ * For BufferedImages, convolution is applied to all components. Color
+ * conversion will be applied if needed.
+ *
+ * Note that this filter ignores whether the source or destination is alpha
+ * premultiplied. The reference spec states that data will be premultiplied
+ * prior to convolving and divided back out afterwards (if needed), but testing
+ * has shown that this is not the case with their implementation.
+ *
+ * @author jlquinn@optonline.net
+ */
+public class ConvolveOp implements BufferedImageOp, RasterOp
+{
+ /** Edge pixels are set to 0. */
+ public static final int EDGE_ZERO_FILL = 0;
+
+ /** Edge pixels are copied from the source. */
+ public static final int EDGE_NO_OP = 1;
+
+ private Kernel kernel;
+ private int edge;
+ private RenderingHints hints;
+
+ /**
+ * Construct a ConvolveOp.
+ *
+ * The edge condition specifies that pixels outside the area that can be
+ * filtered are either set to 0 or copied from the source image.
+ *
+ * @param kernel The kernel to convolve with.
+ * @param edgeCondition Either EDGE_ZERO_FILL or EDGE_NO_OP.
+ * @param hints Rendering hints for color conversion, or null.
+ */
+ public ConvolveOp(Kernel kernel,
+ int edgeCondition,
+ RenderingHints hints)
+ {
+ this.kernel = kernel;
+ edge = edgeCondition;
+ this.hints = hints;
+ }
+
+ /**
+ * Construct a ConvolveOp.
+ *
+ * The edge condition defaults to EDGE_ZERO_FILL.
+ *
+ * @param kernel The kernel to convolve with.
+ */
+ public ConvolveOp(Kernel kernel)
+ {
+ this.kernel = kernel;
+ edge = EDGE_ZERO_FILL;
+ hints = null;
+ }
+
+ /**
+ * Converts the source image using the kernel specified in the
+ * constructor. The resulting image is stored in the destination image if one
+ * is provided; otherwise a new BufferedImage is created and returned.
+ *
+ * The source and destination BufferedImage (if one is supplied) must have
+ * the same dimensions.
+ *
+ * @param src The source image.
+ * @param dst The destination image.
+ * @throws IllegalArgumentException if the rasters and/or color spaces are
+ * incompatible.
+ * @return The convolved image.
+ */
+ public final BufferedImage filter(BufferedImage src, BufferedImage dst)
+ {
+ if (src == dst)
+ throw new IllegalArgumentException("Source and destination images " +
+ "cannot be the same.");
+
+ if (dst == null)
+ dst = createCompatibleDestImage(src, src.getColorModel());
+
+ // Make sure source image is premultiplied
+ BufferedImage src1 = src;
+ // The spec says we should do this, but mauve testing shows that Sun's
+ // implementation does not check this.
+ /*
+ if (!src.isAlphaPremultiplied())
+ {
+ src1 = createCompatibleDestImage(src, src.getColorModel());
+ src.copyData(src1.getRaster());
+ src1.coerceData(true);
+ }
+ */
+
+ BufferedImage dst1 = dst;
+ if (src1.getColorModel().getColorSpace().getType() != dst.getColorModel().getColorSpace().getType())
+ dst1 = createCompatibleDestImage(src, src.getColorModel());
+
+ filter(src1.getRaster(), dst1.getRaster());
+
+ // Since we don't coerceData above, we don't need to divide it back out.
+ // This is wrong (one mauve test specifically tests converting a non-
+ // premultiplied image to a premultiplied image, and it shows that Sun
+ // simply ignores the premultipled flag, contrary to the spec), but we
+ // mimic it for compatibility.
+ /*
+ if (! dst.isAlphaPremultiplied())
+ dst1.coerceData(false);
+ */
+
+ // Convert between color models if needed
+ if (dst1 != dst)
+ new ColorConvertOp(hints).filter(dst1, dst);
+
+ return dst;
+ }
+
+ /**
+ * Creates an empty BufferedImage with the size equal to the source and the
+ * correct number of bands. The new image is created with the specified
+ * ColorModel, or if no ColorModel is supplied, an appropriate one is chosen.
+ *
+ * @param src The source image.
+ * @param dstCM A color model for the destination image (may be null).
+ * @return The new compatible destination image.
+ */
+ public BufferedImage createCompatibleDestImage(BufferedImage src,
+ ColorModel dstCM)
+ {
+ if (dstCM != null)
+ return new BufferedImage(dstCM,
+ src.getRaster().createCompatibleWritableRaster(),
+ src.isAlphaPremultiplied(), null);
+
+ return new BufferedImage(src.getWidth(), src.getHeight(), src.getType());
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#getRenderingHints()
+ */
+ public final RenderingHints getRenderingHints()
+ {
+ return hints;
+ }
+
+ /**
+ * Get the edge condition for this Op.
+ *
+ * @return The edge condition.
+ */
+ public int getEdgeCondition()
+ {
+ return edge;
+ }
+
+ /**
+ * Returns (a clone of) the convolution kernel.
+ *
+ * @return The convolution kernel.
+ */
+ public final Kernel getKernel()
+ {
+ return (Kernel) kernel.clone();
+ }
+
+ /**
+ * Converts the source raster using the kernel specified in the constructor.
+ * The resulting raster is stored in the destination raster if one is
+ * provided; otherwise a new WritableRaster is created and returned.
+ *
+ * If the convolved value for a sample is outside the range of [0-255], it
+ * will be clipped.
+ *
+ * The source and destination raster (if one is supplied) cannot be the same,
+ * and must also have the same dimensions.
+ *
+ * @param src The source raster.
+ * @param dest The destination raster.
+ * @throws IllegalArgumentException if the rasters identical.
+ * @throws ImagingOpException if the convolution is not possible.
+ * @return The transformed raster.
+ */
+ public final WritableRaster filter(Raster src, WritableRaster dest)
+ {
+ if (src == dest)
+ throw new IllegalArgumentException("src == dest is not allowed.");
+ if (kernel.getWidth() > src.getWidth()
+ || kernel.getHeight() > src.getHeight())
+ throw new ImagingOpException("The kernel is too large.");
+ if (dest == null)
+ dest = createCompatibleDestRaster(src);
+ else if (src.getNumBands() != dest.getNumBands())
+ throw new ImagingOpException("src and dest have different band counts.");
+
+ // calculate the borders that the op can't reach...
+ int kWidth = kernel.getWidth();
+ int kHeight = kernel.getHeight();
+ int left = kernel.getXOrigin();
+ int right = Math.max(kWidth - left - 1, 0);
+ int top = kernel.getYOrigin();
+ int bottom = Math.max(kHeight - top - 1, 0);
+
+ // Calculate max sample values for clipping
+ int[] maxValue = src.getSampleModel().getSampleSize();
+ for (int i = 0; i < maxValue.length; i++)
+ maxValue[i] = (int)Math.pow(2, maxValue[i]) - 1;
+
+ // process the region that is reachable...
+ int regionW = src.width - left - right;
+ int regionH = src.height - top - bottom;
+ float[] kvals = kernel.getKernelData(null);
+ float[] tmp = new float[kWidth * kHeight];
+
+ for (int x = 0; x < regionW; x++)
+ {
+ for (int y = 0; y < regionH; y++)
+ {
+ // FIXME: This needs a much more efficient implementation
+ for (int b = 0; b < src.getNumBands(); b++)
+ {
+ float v = 0;
+ src.getSamples(x, y, kWidth, kHeight, b, tmp);
+ for (int i = 0; i < tmp.length; i++)
+ v += tmp[tmp.length - i - 1] * kvals[i];
+ // FIXME: in the above line, I've had to reverse the order of
+ // the samples array to make the tests pass. I haven't worked
+ // out why this is necessary.
+
+ // This clipping is is undocumented, but determined by testing.
+ if (v > maxValue[b])
+ v = maxValue[b];
+ else if (v < 0)
+ v = 0;
+
+ dest.setSample(x + kernel.getXOrigin(), y + kernel.getYOrigin(),
+ b, v);
+ }
+ }
+ }
+
+ // fill in the top border
+ fillEdge(src, dest, 0, 0, src.width, top, edge);
+
+ // fill in the bottom border
+ fillEdge(src, dest, 0, src.height - bottom, src.width, bottom, edge);
+
+ // fill in the left border
+ fillEdge(src, dest, 0, top, left, regionH, edge);
+
+ // fill in the right border
+ fillEdge(src, dest, src.width - right, top, right, regionH, edge);
+
+ return dest;
+ }
+
+ /**
+ * Fills a range of pixels (typically at the edge of a raster) with either
+ * zero values (if <code>edgeOp</code> is <code>EDGE_ZERO_FILL</code>) or the
+ * corresponding pixel values from the source raster (if <code>edgeOp</code>
+ * is <code>EDGE_NO_OP</code>). This utility method is called by the
+ * {@link #fillEdge(Raster, WritableRaster, int, int, int, int, int)} method.
+ *
+ * @param src the source raster.
+ * @param dest the destination raster.
+ * @param x the x-coordinate of the top left pixel in the range.
+ * @param y the y-coordinate of the top left pixel in the range.
+ * @param w the width of the pixel range.
+ * @param h the height of the pixel range.
+ * @param edgeOp indicates how to determine the values for the range
+ * (either {@link #EDGE_ZERO_FILL} or {@link #EDGE_NO_OP}).
+ */
+ private void fillEdge(Raster src, WritableRaster dest, int x, int y, int w,
+ int h, int edgeOp)
+ {
+ if (w <= 0)
+ return;
+ if (h <= 0)
+ return;
+ if (edgeOp == EDGE_ZERO_FILL) // fill region with zeroes
+ {
+ float[] zeros = new float[src.getNumBands() * w * h];
+ dest.setPixels(x, y, w, h, zeros);
+ }
+ else // copy pixels from source
+ {
+ float[] pixels = new float[src.getNumBands() * w * h];
+ src.getPixels(x, y, w, h, pixels);
+ dest.setPixels(x, y, w, h, pixels);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#createCompatibleDestRaster(java.awt.image.Raster)
+ */
+ public WritableRaster createCompatibleDestRaster(Raster src)
+ {
+ return src.createCompatibleWritableRaster();
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#getBounds2D(java.awt.image.BufferedImage)
+ */
+ public final Rectangle2D getBounds2D(BufferedImage src)
+ {
+ return src.getRaster().getBounds();
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#getBounds2D(java.awt.image.Raster)
+ */
+ public final Rectangle2D getBounds2D(Raster src)
+ {
+ return src.getBounds();
+ }
+
+ /**
+ * Returns the corresponding destination point for a source point. Because
+ * this is not a geometric operation, the destination and source points will
+ * be identical.
+ *
+ * @param src The source point.
+ * @param dst The transformed destination point.
+ * @return The transformed destination point.
+ */
+ public final Point2D getPoint2D(Point2D src, Point2D dst)
+ {
+ if (dst == null) return (Point2D)src.clone();
+ dst.setLocation(src);
+ return dst;
+ }
+}
diff --git a/libjava/classpath/java/awt/image/CropImageFilter.java b/libjava/classpath/java/awt/image/CropImageFilter.java
new file mode 100644
index 000000000..4d8fb624f
--- /dev/null
+++ b/libjava/classpath/java/awt/image/CropImageFilter.java
@@ -0,0 +1,184 @@
+/* CropImageFilter.java -- Java class for cropping image filter
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.Rectangle;
+import java.util.Hashtable;
+
+/**
+ * Currently this filter does almost nothing and needs to be implemented.
+ *
+ * @author C. Brian Jones (cbj@gnu.org)
+ */
+public class CropImageFilter extends ImageFilter
+{
+ int x;
+ int y;
+ int width;
+ int height;
+
+ /**
+ * Construct a new <code>CropImageFilter</code> instance.
+ *
+ * @param x the x-coordinate location of the top-left of the cropped rectangle
+ * @param y the y-coordinate location of the top-left of the cropped rectangle
+ * @param width the width of the cropped rectangle
+ * @param height the height of the cropped rectangle
+ */
+ public CropImageFilter(int x, int y, int width, int height) {
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ }
+
+ /**
+ * An <code>ImageProducer</code> indicates the size of the image
+ * being produced using this method. This filter overrides this
+ * method in order to set the dimentions to the size of the
+ * cropped rectangle instead of the size of the image.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ */
+ public void setDimensions(int width, int height)
+ {
+ if (consumer != null)
+ consumer.setDimensions(this.width, this.height);
+ }
+
+ /**
+ * An <code>ImageProducer</code> can set a list of properties
+ * associated with this image by using this method.
+ * <br>
+ * FIXME - What property is set for this class?
+ *
+ * @param props the list of properties associated with this image
+ */
+ public void setProperties(Hashtable<?, ?> props)
+ {
+ Hashtable<Object, Object> prop2 = (Hashtable<Object, Object>) props;
+ prop2.put("filters", "CropImageFilter");
+ if (consumer != null)
+ consumer.setProperties(prop2);
+ }
+
+ /**
+ * This function delivers a rectangle of pixels where any
+ * pixel(m,n) is stored in the array as a <code>byte</code> at
+ * index (n * scansize + m + offset).
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param model the <code>ColorModel</code> used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the <code>pixels</code> array
+ * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
+ */
+ public void setPixels(int x, int y, int w, int h,
+ ColorModel model, byte[] pixels, int offset, int scansize)
+ {
+ Rectangle filterBounds = new Rectangle(this.x, this.y,
+ this.width, this.height);
+ Rectangle pixelBounds = new Rectangle(x, y, w, h);
+
+ if (filterBounds.intersects(pixelBounds))
+ {
+ Rectangle bounds = filterBounds.intersection(pixelBounds);
+
+ byte[] cropped = new byte[bounds.width * bounds.height];
+ for (int i = 0; i < bounds.height; i++)
+ {
+ int start = (bounds.y - pixelBounds.y + i) * scansize + offset;
+
+ for (int j = 0; j < bounds.width; j++)
+ cropped[i * bounds.width + j] = pixels[start + bounds.x + j];
+ }
+
+ if (consumer != null)
+ consumer.setPixels(0, 0,
+ bounds.width, bounds.height,
+ model, cropped, 0, bounds.width);
+ }
+ }
+
+ /**
+ * This function delivers a rectangle of pixels where any
+ * pixel(m,n) is stored in the array as an <code>int</code> at
+ * index (n * scansize + m + offset).
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param model the <code>ColorModel</code> used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the <code>pixels</code> array
+ * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
+ */
+ public void setPixels(int x, int y, int w, int h,
+ ColorModel model, int[] pixels, int offset, int scansize)
+ {
+ Rectangle filterBounds = new Rectangle(this.x, this.y,
+ this.width, this.height);
+ Rectangle pixelBounds = new Rectangle(x, y, w, h);
+
+ if (filterBounds.intersects(pixelBounds))
+ {
+ Rectangle bounds = filterBounds.intersection(pixelBounds);
+
+ int[] cropped = new int[bounds.width * bounds.height];
+ for (int i = 0; i < bounds.height; i++)
+ {
+ int start = (bounds.y - pixelBounds.y + i) * scansize + offset;
+
+ for (int j = 0; j < bounds.width; j++)
+ cropped[i * bounds.width + j] = pixels[start + bounds.x + j];
+ }
+
+ if (consumer != null)
+ consumer.setPixels(0, 0,
+ bounds.width, bounds.height,
+ model, cropped, 0, bounds.width);
+ }
+ }
+
+}
diff --git a/libjava/classpath/java/awt/image/DataBuffer.java b/libjava/classpath/java/awt/image/DataBuffer.java
new file mode 100644
index 000000000..78bc75ba5
--- /dev/null
+++ b/libjava/classpath/java/awt/image/DataBuffer.java
@@ -0,0 +1,437 @@
+/* Copyright (C) 2000, 2002, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+/**
+ * Class that manages arrays of data elements. A data buffer consists
+ * of one or more banks. A bank is a continuous region of data
+ * elements.
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public abstract class DataBuffer
+{
+ /**
+ * A constant representing a data type that uses <code>byte</code> primitives
+ * as the storage unit.
+ */
+ public static final int TYPE_BYTE = 0;
+
+ /**
+ * A constant representing a data type that uses <code>short</code>
+ * primitives as the storage unit.
+ */
+ public static final int TYPE_USHORT = 1;
+
+ /**
+ * A constant representing a data type that uses <code>short</code>
+ * primitives as the storage unit.
+ */
+ public static final int TYPE_SHORT = 2;
+
+ /**
+ * A constant representing a data type that uses <code>int</code>
+ * primitives as the storage unit.
+ */
+ public static final int TYPE_INT = 3;
+
+ /**
+ * A constant representing a data type that uses <code>float</code>
+ * primitives as the storage unit.
+ */
+ public static final int TYPE_FLOAT = 4;
+
+ /**
+ * A constant representing a data type that uses <code>double</code>
+ * primitives as the storage unit.
+ */
+ public static final int TYPE_DOUBLE = 5;
+
+ /**
+ * A constant representing an undefined data type.
+ */
+ public static final int TYPE_UNDEFINED = 32;
+
+ /** The type of the data elements stored in the data buffer. */
+ protected int dataType;
+
+ /** The number of banks in this buffer. */
+ protected int banks = 1;
+
+ /** Offset into the default (0'th) bank). */
+ protected int offset; // FIXME: Is offsets[0] always mirrored in offset?
+
+ /** The size of the banks. */
+ protected int size;
+
+ /** Offset into each bank. */
+ protected int[] offsets;
+
+ /**
+ * Creates a new <code>DataBuffer</code> with the specified data type and
+ * size. The <code>dataType</code> should be one of the constants
+ * {@link #TYPE_BYTE}, {@link #TYPE_SHORT}, {@link #TYPE_USHORT},
+ * {@link #TYPE_INT}, {@link #TYPE_FLOAT} and {@link #TYPE_DOUBLE}.
+ * <p>
+ * The physical (array-based) storage is allocated by a subclass.
+ *
+ * @param dataType the data type.
+ * @param size the number of elements in the buffer.
+ */
+ protected DataBuffer(int dataType, int size)
+ {
+ this(dataType, size, 1);
+ }
+
+ /**
+ * Creates a new <code>DataBuffer</code> with the specified data type,
+ * size and number of banks. The <code>dataType</code> should be one of
+ * the constants {@link #TYPE_BYTE}, {@link #TYPE_SHORT},
+ * {@link #TYPE_USHORT}, {@link #TYPE_INT}, {@link #TYPE_FLOAT} and
+ * {@link #TYPE_DOUBLE}.
+ * <p>
+ * The physical (array-based) storage is allocated by a subclass.
+ *
+ * @param dataType the data type.
+ * @param size the number of elements in the buffer.
+ * @param numBanks the number of data banks.
+ */
+ protected DataBuffer(int dataType, int size, int numBanks) {
+ this(dataType, size, numBanks, 0);
+ }
+
+ /**
+ * Creates a new <code>DataBuffer</code> with the specified data type,
+ * size and number of banks. An offset (which applies to all banks) is
+ * also specified. The <code>dataType</code> should be one of
+ * the constants {@link #TYPE_BYTE}, {@link #TYPE_SHORT},
+ * {@link #TYPE_USHORT}, {@link #TYPE_INT}, {@link #TYPE_FLOAT} and
+ * {@link #TYPE_DOUBLE}.
+ * <p>
+ * The physical (array-based) storage is allocated by a subclass.
+ *
+ * @param dataType the data type.
+ * @param size the number of elements in the buffer.
+ * @param numBanks the number of data banks.
+ * @param offset the offset to the first element for all banks.
+ */
+ protected DataBuffer(int dataType, int size, int numBanks, int offset) {
+ banks = numBanks;
+ this.dataType = dataType;
+ this.size = size;
+ this.offset = offset;
+
+ offsets = new int[ numBanks ];
+ for(int i = 0; i < numBanks; i++ )
+ offsets[i] = offset;
+ }
+
+ /**
+ * Creates a new <code>DataBuffer</code> with the specified data type,
+ * size and number of banks. An offset (which applies to all banks) is
+ * also specified. The <code>dataType</code> should be one of
+ * the constants {@link #TYPE_BYTE}, {@link #TYPE_SHORT},
+ * {@link #TYPE_USHORT}, {@link #TYPE_INT}, {@link #TYPE_FLOAT} and
+ * {@link #TYPE_DOUBLE}.
+ * <p>
+ * The physical (array-based) storage is allocated by a subclass.
+ *
+ * @param dataType the data type.
+ * @param size the number of elements in the buffer.
+ * @param numBanks the number of data banks.
+ * @param offsets the offsets to the first element for all banks.
+ *
+ * @throws ArrayIndexOutOfBoundsException if
+ * <code>numBanks != offsets.length</code>.
+ */
+ protected DataBuffer(int dataType, int size, int numBanks, int[] offsets) {
+ if (numBanks != offsets.length)
+ throw new ArrayIndexOutOfBoundsException();
+
+ this.dataType = dataType;
+ this.size = size;
+ banks = numBanks;
+ this.offsets = offsets;
+
+ offset = offsets[0];
+ }
+
+ /**
+ * Returns the size (number of bits) of the specified data type. Valid types
+ * are defined by the constants {@link #TYPE_BYTE}, {@link #TYPE_SHORT},
+ * {@link #TYPE_USHORT}, {@link #TYPE_INT}, {@link #TYPE_FLOAT} and
+ * {@link #TYPE_DOUBLE}.
+ *
+ * @param dataType the data type.
+ * @return The number of bits for the specified data type.
+ * @throws IllegalArgumentException if <code>dataType < 0</code> or
+ * <code>dataType > TYPE_DOUBLE</code>.
+ */
+ public static int getDataTypeSize(int dataType) {
+ // Maybe this should be a lookup table instead.
+ switch (dataType)
+ {
+ case TYPE_BYTE:
+ return 8;
+ case TYPE_USHORT:
+ case TYPE_SHORT:
+ return 16;
+ case TYPE_INT:
+ case TYPE_FLOAT:
+ return 32;
+ case TYPE_DOUBLE:
+ return 64;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Returns the type of the data elements in the data buffer. Valid types
+ * are defined by the constants {@link #TYPE_BYTE}, {@link #TYPE_SHORT},
+ * {@link #TYPE_USHORT}, {@link #TYPE_INT}, {@link #TYPE_FLOAT} and
+ * {@link #TYPE_DOUBLE}.
+ *
+ * @return The type.
+ */
+ public int getDataType()
+ {
+ return dataType;
+ }
+
+ /**
+ * Returns the size of the data buffer.
+ *
+ * @return The size.
+ */
+ public int getSize()
+ {
+ return size;
+ }
+
+ /**
+ * Returns the element offset for the first data bank.
+ *
+ * @return The element offset.
+ */
+ public int getOffset()
+ {
+ return offset;
+ }
+
+ /**
+ * Returns the offsets for all the data banks used by this
+ * <code>DataBuffer</code>.
+ *
+ * @return The offsets.
+ */
+ public int[] getOffsets()
+ {
+ if (offsets == null)
+ {
+ // is this necessary?
+ offsets = new int[1];
+ offsets[0] = offset;
+ }
+ return offsets;
+ }
+
+ /**
+ * Returns the number of data banks for this <code>DataBuffer</code>.
+ * @return The number of data banks.
+ */
+ public int getNumBanks()
+ {
+ return banks;
+ }
+
+ /**
+ * Returns an element from the first data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
+ public int getElem(int i)
+ {
+ return getElem(0, i);
+ }
+
+ /**
+ * Returns an element from a particular data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
+ public abstract int getElem(int bank, int i);
+
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElem(int i, int val)
+ {
+ setElem(0, i, val);
+ }
+
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public abstract void setElem(int bank, int i, int val);
+
+ /**
+ * Returns an element from the first data bank, converted to a
+ * <code>float</code>. The offset (specified in the constructor) is added
+ * to <code>i</code> before accessing the underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
+ public float getElemFloat(int i)
+ {
+ return getElem(i);
+ }
+
+ /**
+ * Returns an element from a particular data bank, converted to a
+ * <code>float</code>. The offset (specified in the constructor) is
+ * added to <code>i</code> before accessing the underlying data array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
+ public float getElemFloat(int bank, int i)
+ {
+ return getElem(bank, i);
+ }
+
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElemFloat(int i, float val)
+ {
+ setElem(i, (int) val);
+ }
+
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElemFloat(int bank, int i, float val)
+ {
+ setElem(bank, i, (int) val);
+ }
+
+ /**
+ * Returns an element from the first data bank, converted to a
+ * <code>double</code>. The offset (specified in the constructor) is added
+ * to <code>i</code> before accessing the underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
+ public double getElemDouble(int i)
+ {
+ return getElem(i);
+ }
+
+ /**
+ * Returns an element from a particular data bank, converted to a
+ * <code>double</code>. The offset (specified in the constructor) is
+ * added to <code>i</code> before accessing the underlying data array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
+ public double getElemDouble(int bank, int i)
+ {
+ return getElem(bank, i);
+ }
+
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElemDouble(int i, double val)
+ {
+ setElem(i, (int) val);
+ }
+
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElemDouble(int bank, int i, double val)
+ {
+ setElem(bank, i, (int) val);
+ }
+}
diff --git a/libjava/classpath/java/awt/image/DataBufferByte.java b/libjava/classpath/java/awt/image/DataBufferByte.java
new file mode 100644
index 000000000..01364b07a
--- /dev/null
+++ b/libjava/classpath/java/awt/image/DataBufferByte.java
@@ -0,0 +1,245 @@
+/* Copyright (C) 2000, 2002 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+/* This is one of several classes that are nearly identical. Maybe we
+ should have a central template and generate all these files. This
+ is one of the cases where templates or macros would have been
+ useful to have in Java.
+
+ This file has been created using search-replace. My only fear is
+ that these classes will grow out-of-sync as of a result of changes
+ that are not propagated to the other files. As always, mirroring
+ code is a maintenance nightmare. */
+
+/**
+ * A {@link DataBuffer} that uses an array of <code>byte</code> primitives
+ * to represent each of its banks.
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public final class DataBufferByte extends DataBuffer
+{
+ private byte[] data;
+ private byte[][] bankData;
+
+ /**
+ * Creates a new data buffer with a single data bank containing the
+ * specified number of <code>byte</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ */
+ public DataBufferByte(int size)
+ {
+ super(TYPE_BYTE, size, 1, 0);
+ bankData = new byte[1][];
+ data = new byte[size];
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer with the specified number of data banks,
+ * each containing the specified number of <code>byte</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ * @param numBanks the number of data banks.
+ */
+ public DataBufferByte(int size, int numBanks)
+ {
+ super(TYPE_BYTE, size, numBanks);
+ bankData = new byte[numBanks][size];
+ data = bankData[0];
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data bank.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ */
+ public DataBufferByte(byte[] dataArray, int size)
+ {
+ super(TYPE_BYTE, size, 1, 0);
+ bankData = new byte[1][];
+ data = dataArray;
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data bank, with
+ * the specified offset to the first element.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ * @param offset the offset to the first element in the array.
+ */
+ public DataBufferByte(byte[] dataArray, int size, int offset)
+ {
+ super(TYPE_BYTE, size, 1, offset);
+ bankData = new byte[1][];
+ data = dataArray;
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data banks.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
+ public DataBufferByte(byte[][] dataArray, int size)
+ {
+ super(TYPE_BYTE, size, dataArray.length);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data banks, with
+ * the specified offsets to the first element in each bank.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ * @param offsets the offsets to the first element in each data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
+ public DataBufferByte(byte[][] dataArray, int size, int[] offsets)
+ {
+ super(TYPE_BYTE, size, dataArray.length, offsets);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ /**
+ * Returns the first data bank.
+ *
+ * @return The first data bank.
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+
+ /**
+ * Returns a data bank.
+ *
+ * @param bank the bank index.
+ * @return A data bank.
+ */
+ public byte[] getData(int bank)
+ {
+ return bankData[bank];
+ }
+
+ /**
+ * Returns the array underlying this <code>DataBuffer</code>.
+ *
+ * @return The data banks.
+ */
+ public byte[][] getBankData()
+ {
+ return bankData;
+ }
+
+ /**
+ * Returns an element from the first data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
+ public int getElem(int i)
+ {
+ return data[i+offset] & 0xff; // get unsigned byte as int
+ }
+
+ /**
+ * Returns an element from a particular data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
+ public int getElem(int bank, int i)
+ {
+ // get unsigned byte as int
+ return bankData[bank][i+offsets[bank]] & 0xff;
+ }
+
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElem(int i, int val)
+ {
+ data[i+offset] = (byte) val;
+ }
+
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElem(int bank, int i, int val)
+ {
+ bankData[bank][i+offsets[bank]] = (byte) val;
+ }
+}
diff --git a/libjava/classpath/java/awt/image/DataBufferDouble.java b/libjava/classpath/java/awt/image/DataBufferDouble.java
new file mode 100644
index 000000000..31c5ebd8c
--- /dev/null
+++ b/libjava/classpath/java/awt/image/DataBufferDouble.java
@@ -0,0 +1,288 @@
+/* Copyright (C) 2004, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+/* This is one of several classes that are nearly identical. Maybe we
+ should have a central template and generate all these files. This
+ is one of the cases where templates or macros would have been
+ useful to have in Java.
+
+ This file has been created using search-replace. My only fear is
+ that these classes will grow out-of-sync as of a result of changes
+ that are not propagated to the other files. As always, mirroring
+ code is a maintenance nightmare. */
+
+/**
+ * A {@link DataBuffer} that uses an array of <code>double</code> primitives
+ * to represent each of its banks.
+ *
+ * @since 1.4
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ */
+public final class DataBufferDouble
+ extends DataBuffer
+{
+ private double[] data;
+ private double[][] bankData;
+
+ /**
+ * Creates a new data buffer with a single data bank containing the
+ * specified number of <code>double</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ */
+ public DataBufferDouble(int size)
+ {
+ super(TYPE_DOUBLE, size, 1, 0);
+ bankData = new double[1][];
+ data = new double[size];
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer with the specified number of data banks,
+ * each containing the specified number of <code>double</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ * @param numBanks the number of data banks.
+ */
+ public DataBufferDouble(int size, int numBanks)
+ {
+ super(TYPE_DOUBLE, size, numBanks);
+ bankData = new double[numBanks][size];
+ data = bankData[0];
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data bank.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ */
+ public DataBufferDouble(double[] dataArray, int size)
+ {
+ super(TYPE_DOUBLE, size, 1, 0);
+ bankData = new double[1][];
+ data = dataArray;
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data bank, with
+ * the specified offset to the first element.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ * @param offset the offset to the first element in the array.
+ */
+ public DataBufferDouble(double[] dataArray, int size, int offset)
+ {
+ super(TYPE_DOUBLE, size, 1, offset);
+ bankData = new double[1][];
+ data = dataArray;
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data banks.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
+ public DataBufferDouble(double[][] dataArray, int size)
+ {
+ super(TYPE_DOUBLE, size, dataArray.length);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data banks, with
+ * the specified offsets to the first element in each bank.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ * @param offsets the offsets to the first element in each data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
+ public DataBufferDouble(double[][] dataArray, int size, int[] offsets)
+ {
+ super(TYPE_DOUBLE, size, dataArray.length, offsets);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ /**
+ * Returns the first data bank.
+ *
+ * @return The first data bank.
+ */
+ public double[] getData()
+ {
+ return data;
+ }
+
+ /**
+ * Returns a data bank.
+ *
+ * @param bank the bank index.
+ * @return A data bank.
+ */
+ public double[] getData(int bank)
+ {
+ return bankData[bank];
+ }
+
+ /**
+ * Returns the array underlying this <code>DataBuffer</code>.
+ *
+ * @return The data banks.
+ */
+ public double[][] getBankData()
+ {
+ return bankData;
+ }
+
+ /**
+ * Returns an element from the first data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
+ public int getElem(int i)
+ {
+ return (int) data[i+offset];
+ }
+
+ /**
+ * Returns an element from a particular data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
+ public int getElem(int bank, int i)
+ {
+ return (int) bankData[bank][i+offsets[bank]];
+ }
+
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElem(int i, int val)
+ {
+ data[i+offset] = val;
+ }
+
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElem(int bank, int i, int val)
+ {
+ bankData[bank][i+offsets[bank]] = val;
+ }
+
+ public float getElemFloat(int i)
+ {
+ return (float) data[i+offset];
+ }
+
+ public float getElemFloat(int bank, int i)
+ {
+ return (float) bankData[bank][i+offsets[bank]];
+ }
+
+ public void setElemFloat(int i, float val)
+ {
+ data[i+offset] = val;
+ }
+
+ public void setElemFloat(int bank, int i, float val)
+ {
+ bankData[bank][i+offsets[bank]] = val;
+ }
+
+ public double getElemDouble(int i)
+ {
+ return data[i + offset];
+ }
+
+ public double getElemDouble(int bank, int i)
+ {
+ return bankData[bank][i + offsets[bank]];
+ }
+
+ public void setElemDouble(int i, double val)
+ {
+ data[i + offset] = val;
+ }
+
+ public void setElemDouble(int bank, int i, double val)
+ {
+ bankData[bank][i + offsets[bank]] = val;
+ }
+}
diff --git a/libjava/classpath/java/awt/image/DataBufferFloat.java b/libjava/classpath/java/awt/image/DataBufferFloat.java
new file mode 100644
index 000000000..44a0a3892
--- /dev/null
+++ b/libjava/classpath/java/awt/image/DataBufferFloat.java
@@ -0,0 +1,286 @@
+/* Copyright (C) 2004, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+/* This is one of several classes that are nearly identical. Maybe we
+ should have a central template and generate all these files. This
+ is one of the cases where templates or macros would have been
+ useful to have in Java.
+
+ This file has been created using search-replace. My only fear is
+ that these classes will grow out-of-sync as of a result of changes
+ that are not propagated to the other files. As always, mirroring
+ code is a maintenance nightmare. */
+
+/**
+ * A {@link DataBuffer} that uses an array of <code>float</code> primitives
+ * to represent each of its banks.
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ */
+public final class DataBufferFloat
+ extends DataBuffer
+{
+ private float[] data;
+ private float[][] bankData;
+
+ /**
+ * Creates a new data buffer with a single data bank containing the
+ * specified number of <code>float</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ */
+ public DataBufferFloat(int size)
+ {
+ super(TYPE_FLOAT, size, 1, 0);
+ bankData = new float[1][];
+ data = new float[size];
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer with the specified number of data banks,
+ * each containing the specified number of <code>float</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ * @param numBanks the number of data banks.
+ */
+ public DataBufferFloat(int size, int numBanks)
+ {
+ super(TYPE_FLOAT, size, numBanks);
+ bankData = new float[numBanks][size];
+ data = bankData[0];
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data bank.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ */
+ public DataBufferFloat(float[] dataArray, int size)
+ {
+ super(TYPE_FLOAT, size, 1, 0);
+ bankData = new float[1][];
+ data = dataArray;
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data bank, with
+ * the specified offset to the first element.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ * @param offset the offset to the first element in the array.
+ */
+ public DataBufferFloat(float[] dataArray, int size, int offset)
+ {
+ super(TYPE_FLOAT, size, 1, offset);
+ bankData = new float[1][];
+ data = dataArray;
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data banks.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
+ public DataBufferFloat(float[][] dataArray, int size)
+ {
+ super(TYPE_FLOAT, size, dataArray.length);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data banks, with
+ * the specified offsets to the first element in each bank.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ * @param offsets the offsets to the first element in each data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
+ public DataBufferFloat(float[][] dataArray, int size, int[] offsets)
+ {
+ super(TYPE_FLOAT, size, dataArray.length, offsets);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ /**
+ * Returns the first data bank.
+ *
+ * @return The first data bank.
+ */
+ public float[] getData()
+ {
+ return data;
+ }
+
+ /**
+ * Returns a data bank.
+ *
+ * @param bank the bank index.
+ * @return A data bank.
+ */
+ public float[] getData(int bank)
+ {
+ return bankData[bank];
+ }
+
+ /**
+ * Returns the array underlying this <code>DataBuffer</code>.
+ *
+ * @return The data banks.
+ */
+ public float[][] getBankData()
+ {
+ return bankData;
+ }
+
+ /**
+ * Returns an element from the first data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
+ public int getElem(int i)
+ {
+ return (int) data[i+offset];
+ }
+
+ /**
+ * Returns an element from a particular data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
+ public int getElem(int bank, int i)
+ {
+ return (int) bankData[bank][i+offsets[bank]];
+ }
+
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElem(int i, int val)
+ {
+ data[i+offset] = val;
+ }
+
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElem(int bank, int i, int val)
+ {
+ bankData[bank][i+offsets[bank]] = val;
+ }
+
+ public float getElemFloat(int i)
+ {
+ return data[i+offset];
+ }
+
+ public float getElemFloat(int bank, int i)
+ {
+ return bankData[bank][i+offsets[bank]];
+ }
+
+ public void setElemFloat(int i, float val)
+ {
+ data[i+offset] = val;
+ }
+
+ public void setElemFloat(int bank, int i, float val)
+ {
+ bankData[bank][i+offsets[bank]] = val;
+ }
+
+ public double getElemDouble(int i)
+ {
+ return getElemFloat(i);
+ }
+
+ public double getElemDouble(int bank, int i)
+ {
+ return getElemFloat(bank, i);
+ }
+
+ public void setElemDouble(int i, double val)
+ {
+ setElemFloat(i, (float) val);
+ }
+
+ public void setElemDouble(int bank, int i, double val)
+ {
+ setElemFloat(bank, i, (float) val);
+ }
+}
diff --git a/libjava/classpath/java/awt/image/DataBufferInt.java b/libjava/classpath/java/awt/image/DataBufferInt.java
new file mode 100644
index 000000000..db9d5bc30
--- /dev/null
+++ b/libjava/classpath/java/awt/image/DataBufferInt.java
@@ -0,0 +1,244 @@
+/* Copyright (C) 2000, 2002, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+/* This is one of several classes that are nearly identical. Maybe we
+ should have a central template and generate all these files. This
+ is one of the cases where templates or macros would have been
+ useful to have in Java.
+
+ This file has been created using search-replace. My only fear is
+ that these classes will grow out-of-sync as of a result of changes
+ that are not propagated to the other files. As always, mirroring
+ code is a maintenance nightmare. */
+
+/**
+ * A {@link DataBuffer} that uses an array of <code>int</code> primitives
+ * to represent each of its banks.
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public final class DataBufferInt extends DataBuffer
+{
+ private int[] data;
+ private int[][] bankData;
+
+ /**
+ * Creates a new data buffer with a single data bank containing the
+ * specified number of <code>int</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ */
+ public DataBufferInt(int size)
+ {
+ super(TYPE_INT, size, 1, 0);
+ bankData = new int[1][];
+ data = new int[size];
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer with the specified number of data banks,
+ * each containing the specified number of <code>int</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ * @param numBanks the number of data banks.
+ */
+ public DataBufferInt(int size, int numBanks)
+ {
+ super(TYPE_INT, size, numBanks);
+ bankData = new int[numBanks][size];
+ data = bankData[0];
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data bank.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ */
+ public DataBufferInt(int[] dataArray, int size)
+ {
+ super(TYPE_INT, size, 1, 0);
+ bankData = new int[1][];
+ data = dataArray;
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data bank, with
+ * the specified offset to the first element.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ * @param offset the offset to the first element in the array.
+ */
+ public DataBufferInt(int[] dataArray, int size, int offset)
+ {
+ super(TYPE_INT, size, 1, offset);
+ bankData = new int[1][];
+ data = dataArray;
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data banks.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
+ public DataBufferInt(int[][] dataArray, int size)
+ {
+ super(TYPE_INT, size, dataArray.length);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data banks, with
+ * the specified offsets to the first element in each bank.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ * @param offsets the offsets to the first element in each data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
+ public DataBufferInt(int[][] dataArray, int size, int[] offsets)
+ {
+ super(TYPE_INT, size, dataArray.length, offsets);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ /**
+ * Returns the first data bank.
+ *
+ * @return The first data bank.
+ */
+ public int[] getData()
+ {
+ return data;
+ }
+
+ /**
+ * Returns a data bank.
+ *
+ * @param bank the bank index.
+ * @return A data bank.
+ */
+ public int[] getData(int bank)
+ {
+ return bankData[bank];
+ }
+
+ /**
+ * Returns the array underlying this <code>DataBuffer</code>.
+ *
+ * @return The data banks.
+ */
+ public int[][] getBankData()
+ {
+ return bankData;
+ }
+
+ /**
+ * Returns an element from the first data bank. The <code>offset</code> is
+ * added to the specified index before accessing the underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
+ public int getElem(int i)
+ {
+ return data[i+offset];
+ }
+
+ /**
+ * Returns an element from a particular data bank. The <code>offset</code>
+ * is added to the specified index before accessing the underlying data
+ * array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
+ public int getElem(int bank, int i)
+ {
+ // get unsigned int as int
+ return bankData[bank][i+offsets[bank]];
+ }
+
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElem(int i, int val)
+ {
+ data[i+offset] = val;
+ }
+
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElem(int bank, int i, int val)
+ {
+ bankData[bank][i+offsets[bank]] = val;
+ }
+}
diff --git a/libjava/classpath/java/awt/image/DataBufferShort.java b/libjava/classpath/java/awt/image/DataBufferShort.java
new file mode 100644
index 000000000..2156d7571
--- /dev/null
+++ b/libjava/classpath/java/awt/image/DataBufferShort.java
@@ -0,0 +1,245 @@
+/* DataBufferShort.java --
+ Copyright (C) 2004, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+/* This is one of several classes that are nearly identical. Maybe we
+ should have a central template and generate all these files. This
+ is one of the cases where templates or macros would have been
+ useful to have in Java.
+
+ This file has been created using search-replace. My only fear is
+ that these classes will grow out-of-sync as of a result of changes
+ that are not propagated to the other files. As always, mirroring
+ code is a maintenance nightmare. */
+
+/**
+ * A {@link DataBuffer} that uses an array of <code>short</code> primitives
+ * to represent each of its banks.
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public final class DataBufferShort extends DataBuffer
+{
+ private short[] data;
+ private short[][] bankData;
+
+ /**
+ * Creates a new data buffer with a single data bank containing the
+ * specified number of <code>short</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ */
+ public DataBufferShort(int size)
+ {
+ super(TYPE_SHORT, size, 1, 0);
+ bankData = new short[1][];
+ data = new short[size];
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer with the specified number of data banks,
+ * each containing the specified number of <code>short</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ * @param numBanks the number of data banks.
+ */
+ public DataBufferShort(int size, int numBanks)
+ {
+ super(TYPE_SHORT, size, numBanks);
+ bankData = new short[numBanks][size];
+ data = bankData[0];
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data bank.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ */
+ public DataBufferShort(short[] dataArray, int size)
+ {
+ super(TYPE_SHORT, size, 1, 0);
+ bankData = new short[1][];
+ data = dataArray;
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data bank, with
+ * the specified offset to the first element.
+ * <p>
+ * Note: there is no exception when <code>dataArray</code> is
+ * <code>null</code>, but in that case an exception will be thrown
+ * later if you attempt to access the data buffer.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ * @param offset the offset to the first element in the array.
+ */
+ public DataBufferShort(short[] dataArray, int size, int offset)
+ {
+ super(TYPE_SHORT, size, 1, offset);
+ bankData = new short[1][];
+ data = dataArray;
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data banks.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
+ public DataBufferShort(short[][] dataArray, int size)
+ {
+ super(TYPE_SHORT, size, dataArray.length);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data banks, with
+ * the specified offsets to the first element in each bank.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ * @param offsets the offsets to the first element in each data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
+ public DataBufferShort(short[][] dataArray, int size, int[] offsets)
+ {
+ super(TYPE_SHORT, size, dataArray.length, offsets);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ /**
+ * Returns the first data bank.
+ *
+ * @return The first data bank.
+ */
+ public short[] getData()
+ {
+ return data;
+ }
+
+ /**
+ * Returns a data bank.
+ *
+ * @param bank the bank index.
+ * @return A data bank.
+ */
+ public short[] getData(int bank)
+ {
+ return bankData[bank];
+ }
+
+ /**
+ * Returns the array underlying this <code>DataBuffer</code>.
+ *
+ * @return The data banks.
+ */
+ public short[][] getBankData()
+ {
+ return bankData;
+ }
+
+ /**
+ * Returns an element from the first data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
+ public int getElem(int i)
+ {
+ return data[i+offset];
+ }
+
+ /**
+ * Returns an element from a particular data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
+ public int getElem(int bank, int i)
+ {
+ return bankData[bank][i+offsets[bank]];
+ }
+
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElem(int i, int val)
+ {
+ data[i+offset] = (short) val;
+ }
+
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElem(int bank, int i, int val)
+ {
+ bankData[bank][i+offsets[bank]] = (short) val;
+ }
+}
diff --git a/libjava/classpath/java/awt/image/DataBufferUShort.java b/libjava/classpath/java/awt/image/DataBufferUShort.java
new file mode 100644
index 000000000..d2cadcf0b
--- /dev/null
+++ b/libjava/classpath/java/awt/image/DataBufferUShort.java
@@ -0,0 +1,246 @@
+/* DataBufferUShort.java --
+ Copyright (C) 2000, 2002, 2004, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+/* This is one of several classes that are nearly identical. Maybe we
+ should have a central template and generate all these files. This
+ is one of the cases where templates or macros would have been
+ useful to have in Java.
+
+ This file has been created using search-replace. My only fear is
+ that these classes will grow out-of-sync as of a result of changes
+ that are not propagated to the other files. As always, mirroring
+ code is a maintenance nightmare. */
+
+/**
+ * A {@link DataBuffer} that uses an array of <code>short</code> primitives
+ * to represent each of its banks.
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public final class DataBufferUShort extends DataBuffer
+{
+ private short[] data;
+ private short[][] bankData;
+
+ /**
+ * Creates a new data buffer with a single data bank containing the
+ * specified number of <code>short</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ */
+ public DataBufferUShort(int size)
+ {
+ super(TYPE_USHORT, size, 1, 0);
+ bankData = new short[1][];
+ data = new short[size];
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer with the specified number of data banks,
+ * each containing the specified number of <code>short</code> elements.
+ *
+ * @param size the number of elements in the data bank.
+ * @param numBanks the number of data banks.
+ */
+ public DataBufferUShort(int size, int numBanks)
+ {
+ super(TYPE_USHORT, size, numBanks);
+ bankData = new short[numBanks][size];
+ data = bankData[0];
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data bank.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ *
+ * @throws NullPointerException if dataArray is null
+ */
+ public DataBufferUShort(short[] dataArray, int size)
+ {
+ super(TYPE_USHORT, size, 1, 0);
+ if (dataArray == null)
+ throw new NullPointerException();
+ bankData = new short[1][];
+ data = dataArray;
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data bank, with
+ * the specified offset to the first element.
+ *
+ * @param dataArray the data bank.
+ * @param size the number of elements in the data bank.
+ * @param offset the offset to the first element in the array.
+ *
+ * @throws NullPointerException if dataArray is null
+ */
+ public DataBufferUShort(short[] dataArray, int size, int offset)
+ {
+ super(TYPE_USHORT, size, 1, offset);
+ if (dataArray == null)
+ throw new NullPointerException();
+ bankData = new short[1][];
+ data = dataArray;
+ bankData[0] = data;
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data banks.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
+ public DataBufferUShort(short[][] dataArray, int size)
+ {
+ super(TYPE_USHORT, size, dataArray.length);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ /**
+ * Creates a new data buffer backed by the specified data banks, with
+ * the specified offsets to the first element in each bank.
+ *
+ * @param dataArray the data banks.
+ * @param size the number of elements in the data bank.
+ * @param offsets the offsets to the first element in each data bank.
+ *
+ * @throws NullPointerException if <code>dataArray</code> is
+ * <code>null</code>.
+ */
+ public DataBufferUShort(short[][] dataArray, int size, int[] offsets)
+ {
+ super(TYPE_USHORT, size, dataArray.length, offsets);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ /**
+ * Returns the first data bank.
+ *
+ * @return The first data bank.
+ */
+ public short[] getData()
+ {
+ return data;
+ }
+
+ /**
+ * Returns a data bank.
+ *
+ * @param bank the bank index.
+ * @return A data bank.
+ */
+ public short[] getData(int bank)
+ {
+ return bankData[bank];
+ }
+
+ /**
+ * Returns the array underlying this <code>DataBuffer</code>.
+ *
+ * @return The data banks.
+ */
+ public short[][] getBankData()
+ {
+ return bankData;
+ }
+
+ /**
+ * Returns an element from the first data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param i the element index.
+ * @return The element.
+ */
+ public int getElem(int i)
+ {
+ return data[i+offset] & 0xffff; // get unsigned short as int
+ }
+
+ /**
+ * Returns an element from a particular data bank. The offset (specified in
+ * the constructor) is added to <code>i</code> before accessing the
+ * underlying data array.
+ *
+ * @param bank the bank index.
+ * @param i the element index.
+ * @return The element.
+ */
+ public int getElem(int bank, int i)
+ {
+ // get unsigned short as int
+ return bankData[bank][i+offsets[bank]] & 0xffff;
+ }
+
+ /**
+ * Sets an element in the first data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElem(int i, int val)
+ {
+ data[i+offset] = (short) val;
+ }
+
+ /**
+ * Sets an element in a particular data bank. The offset (specified in the
+ * constructor) is added to <code>i</code> before updating the underlying
+ * data array.
+ *
+ * @param bank the data bank index.
+ * @param i the element index.
+ * @param val the new element value.
+ */
+ public void setElem(int bank, int i, int val)
+ {
+ bankData[bank][i+offsets[bank]] = (short) val;
+ }
+}
diff --git a/libjava/classpath/java/awt/image/DirectColorModel.java b/libjava/classpath/java/awt/image/DirectColorModel.java
new file mode 100644
index 000000000..a464fed30
--- /dev/null
+++ b/libjava/classpath/java/awt/image/DirectColorModel.java
@@ -0,0 +1,435 @@
+/* DirectColorModel.java --
+ Copyright (C) 1999, 2000, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import gnu.java.awt.Buffers;
+
+import java.awt.Point;
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
+
+/**
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ * @author C. Brian Jones (cbj@gnu.org)
+ * @author Mark Benvenuto (mcb54@columbia.edu)
+ */
+public class DirectColorModel extends PackedColorModel
+{
+ /**
+ * For the color model created with this constructor the pixels
+ * will have fully opaque alpha components with a value of 255.
+ * Each mask should describe a fully contiguous set of bits in the
+ * most likely order of alpha, red, green, blue from the most significant
+ * byte to the least significant byte.
+ *
+ * @param pixelBits the number of bits wide used for bit size of pixel values
+ * @param rmask the bits describing the red component of a pixel
+ * @param gmask the bits describing the green component of a pixel
+ * @param bmask the bits describing the blue component of a pixel
+ */
+ public DirectColorModel(int pixelBits, int rmask, int gmask, int bmask)
+ {
+ this(ColorSpace.getInstance(ColorSpace.CS_sRGB), pixelBits,
+ rmask, gmask, bmask, 0,
+ false, // not alpha premultiplied
+ Buffers.smallestAppropriateTransferType(pixelBits) // find type
+ );
+ }
+
+ /**
+ * For the color model created with this constructor the pixels
+ * will have fully opaque alpha components with a value of 255.
+ * Each mask should describe a fully contiguous set of bits in the
+ * most likely order of red, green, blue from the most significant
+ * byte to the least significant byte.
+ *
+ * @param pixelBits the number of bits wide used for bit size of pixel values
+ * @param rmask the bits describing the red component of a pixel
+ * @param gmask the bits describing the green component of a pixel
+ * @param bmask the bits describing the blue component of a pixel
+ * @param amask the bits describing the alpha component of a pixel
+ */
+ public DirectColorModel(int pixelBits,
+ int rmask, int gmask, int bmask, int amask)
+ {
+ this(ColorSpace.getInstance(ColorSpace.CS_sRGB), pixelBits,
+ rmask, gmask, bmask, amask,
+ false, // not alpha premultiplied
+ Buffers.smallestAppropriateTransferType(pixelBits) // find type
+ );
+ }
+
+ public DirectColorModel(ColorSpace cspace, int pixelBits,
+ int rmask, int gmask, int bmask, int amask,
+ boolean isAlphaPremultiplied,
+ int transferType)
+ {
+ super(cspace, pixelBits,
+ rmask, gmask, bmask, amask, isAlphaPremultiplied,
+ ((amask == 0) ? Transparency.OPAQUE : Transparency.TRANSLUCENT),
+ transferType);
+ }
+
+ public final int getRedMask()
+ {
+ return getMask(0);
+ }
+
+ public final int getGreenMask()
+ {
+ return getMask(1);
+ }
+
+ public final int getBlueMask()
+ {
+ return getMask(2);
+ }
+
+ public final int getAlphaMask()
+ {
+ return hasAlpha() ? getMask(3) : 0;
+ }
+
+ /**
+ * Get the red component of the given pixel.
+ * <br>
+ */
+ public final int getRed(int pixel)
+ {
+ return extractAndNormalizeSample(pixel, 0);
+ }
+
+ /**
+ * Get the green component of the given pixel.
+ * <br>
+ */
+ public final int getGreen(int pixel)
+ {
+ return extractAndNormalizeSample(pixel, 1);
+ }
+
+ /**
+ * Get the blue component of the given pixel.
+ * <br>
+ */
+ public final int getBlue(int pixel)
+ {
+ return extractAndNormalizeSample(pixel, 2);
+ }
+
+ /**
+ * Get the alpha component of the given pixel.
+ * <br>
+ */
+ public final int getAlpha(int pixel)
+ {
+ if (!hasAlpha())
+ return 255;
+ return extractAndScaleSample(pixel, 3);
+ }
+
+ private int extractAndNormalizeSample(int pixel, int component)
+ {
+ int value = extractAndScaleSample(pixel, component);
+ if (hasAlpha() && isAlphaPremultiplied() && getAlpha(pixel) != 0)
+ value = value*255/getAlpha(pixel);
+ return value;
+ }
+
+ private int extractAndScaleSample(int pixel, int component)
+ {
+ int field = pixel & getMask(component);
+ int to8BitShift =
+ 8 - shifts[component] - getComponentSize(component);
+ return (to8BitShift>0) ?
+ (field << to8BitShift) :
+ (field >>> (-to8BitShift));
+ }
+
+ /**
+ * Get the RGB color value of the given pixel using the default
+ * RGB color model.
+ * <br>
+ *
+ * @param pixel a pixel value
+ */
+ public final int getRGB(int pixel)
+ {
+ /* FIXME: The Sun docs show that this method is overridden, but I
+ don't see any way to improve on the superclass
+ implementation. */
+ return super.getRGB(pixel);
+ }
+
+ public int getRed(Object inData)
+ {
+ return getRed(getPixelFromArray(inData));
+ }
+
+ public int getGreen(Object inData)
+ {
+ return getGreen(getPixelFromArray(inData));
+ }
+
+ public int getBlue(Object inData)
+ {
+ return getBlue(getPixelFromArray(inData));
+ }
+
+ public int getAlpha(Object inData)
+ {
+ return getAlpha(getPixelFromArray(inData));
+ }
+
+ public int getRGB(Object inData)
+ {
+ return getRGB(getPixelFromArray(inData));
+ }
+
+ /**
+ * Converts a normalized pixel int value in the sRGB color
+ * space to an array containing a single pixel of the color space
+ * of the color model.
+ *
+ * <p>This method performs the inverse function of
+ * <code>getRGB(Object inData)</code>.
+ *
+ * @param rgb pixel as a normalized sRGB, 0xAARRGGBB value.
+ *
+ * @param pixel to avoid needless creation of arrays, an array to
+ * use to return the pixel can be given. If null, a suitable array
+ * will be created.
+ *
+ * @return array of transferType containing a single pixel. The
+ * pixel should be encoded in the natural way of the color model.
+ *
+ * @see #getRGB(Object)
+ */
+ public Object getDataElements(int rgb, Object pixel)
+ {
+ // FIXME: handle alpha multiply
+
+ int pixelValue = 0;
+ int a = 0;
+ if (hasAlpha()) {
+ a = (rgb >>> 24) & 0xff;
+ pixelValue = valueToField(a, 3, 8);
+ }
+
+ if (hasAlpha() && isAlphaPremultiplied())
+ {
+ int r, g, b;
+ /* if r=0xff and a=0xff, then resulting
+ value will be (r*a)>>>8 == 0xfe... This seems wrong.
+ We should divide by 255 rather than shifting >>>8 after
+ multiplying.
+
+ Too bad, shifting is probably less expensive.
+ r = ((rgb >>> 16) & 0xff)*a;
+ g = ((rgb >>> 8) & 0xff)*a;
+ b = ((rgb >>> 0) & 0xff)*a; */
+ /* The r, g, b values we calculate are 16 bit. This allows
+ us to avoid discarding the lower 8 bits obtained if
+ multiplying with the alpha band. */
+
+ // using 16 bit values
+ r = ((rgb >>> 8) & 0xff00)*a/255;
+ g = ((rgb >>> 0) & 0xff00)*a/255;
+ b = ((rgb << 8) & 0xff00)*a/255;
+ pixelValue |=
+ valueToField(r, 0, 16) | // Red
+ valueToField(g, 1, 16) | // Green
+ valueToField(b, 2, 16); // Blue
+ }
+ else
+ {
+ int r, g, b;
+ // using 8 bit values
+ r = (rgb >>> 16) & 0xff;
+ g = (rgb >>> 8) & 0xff;
+ b = (rgb >>> 0) & 0xff;
+
+ pixelValue |=
+ valueToField(r, 0, 8) | // Red
+ valueToField(g, 1, 8) | // Green
+ valueToField(b, 2, 8); // Blue
+ }
+
+ /* In this color model, the whole pixel fits in the first element
+ of the array. */
+ DataBuffer buffer = Buffers.createBuffer(transferType, pixel, 1);
+ buffer.setElem(0, pixelValue);
+ return Buffers.getData(buffer);
+ }
+
+ /**
+ * Converts a value to the correct field bits based on the
+ * information derived from the field masks.
+ *
+ * @param highBit the position of the most significant bit in the
+ * val parameter.
+ */
+ private int valueToField(int val, int component, int highBit)
+ {
+ int toFieldShift =
+ getComponentSize(component) + shifts[component] - highBit;
+ int ret = (toFieldShift>0) ?
+ (val << toFieldShift) :
+ (val >>> (-toFieldShift));
+ return ret & getMask(component);
+ }
+
+ /**
+ * Converts a 16 bit value to the correct field bits based on the
+ * information derived from the field masks.
+ */
+ private int value16ToField(int val, int component)
+ {
+ int toFieldShift = getComponentSize(component) + shifts[component] - 16;
+ return (toFieldShift>0) ?
+ (val << toFieldShift) :
+ (val >>> (-toFieldShift));
+ }
+
+ /**
+ * Fills an array with the unnormalized component samples from a
+ * pixel value. I.e. decompose the pixel, but not perform any
+ * color conversion.
+ */
+ public final int[] getComponents(int pixel, int[] components, int offset)
+ {
+ int numComponents = getNumComponents();
+ if (components == null) components = new int[offset + numComponents];
+
+ for (int b=0; b<numComponents; b++)
+ components[offset++] = (pixel&getMask(b)) >>> shifts[b];
+
+ return components;
+ }
+
+ public final int[] getComponents(Object pixel, int[] components,
+ int offset)
+ {
+ return getComponents(getPixelFromArray(pixel), components, offset);
+ }
+
+ /**
+ * Creates a <code>WriteableRaster</code> that has a <code>SampleModel</code>
+ * that is compatible with this <code>ColorModel</code>.
+ *
+ * @param w the width of the writeable raster to create
+ * @param h the height of the writeable raster to create
+ *
+ * @throws IllegalArgumentException if <code>w</code> or <code>h</code>
+ * is less than or equal to zero
+ */
+ public final WritableRaster createCompatibleWritableRaster(int w, int h)
+ {
+ // Sun also makes this check here.
+ if(w <= 0 || h <= 0)
+ throw new IllegalArgumentException("width (=" + w + ") and height (="
+ + h + ") must be > 0");
+
+ SampleModel sm = createCompatibleSampleModel(w, h);
+ Point origin = new Point(0, 0);
+ return Raster.createWritableRaster(sm, origin);
+ }
+
+ public int getDataElement(int[] components, int offset)
+ {
+ int numComponents = getNumComponents();
+ int pixelValue = 0;
+
+ for (int c=0; c<numComponents; c++)
+ pixelValue |= (components[offset++] << shifts[c]) & getMask(c);
+
+ return pixelValue;
+ }
+
+ public Object getDataElements(int[] components, int offset, Object obj)
+ {
+ /* In this color model, the whole pixel fits in the first element
+ of the array. */
+ int pixelValue = getDataElement(components, offset);
+
+ DataBuffer buffer = Buffers.createBuffer(transferType, obj, 1);
+ buffer.setElem(0, pixelValue);
+ return Buffers.getData(buffer);
+ }
+
+ public final ColorModel coerceData (WritableRaster raster,
+ boolean isAlphaPremultiplied)
+ {
+ if (this.isAlphaPremultiplied == isAlphaPremultiplied || !hasAlpha())
+ return this;
+
+ /* TODO: provide better implementation based on the
+ assumptions we can make due to the specific type of the
+ color model. */
+ coerceDataWorker(raster, isAlphaPremultiplied);
+
+ return new DirectColorModel(cspace, pixel_bits, getRedMask(),
+ getGreenMask(), getBlueMask(), getAlphaMask(),
+ isAlphaPremultiplied, transferType);
+ }
+
+ public boolean isCompatibleRaster(Raster raster)
+ {
+ /* FIXME: the Sun docs say this method is overridden here,
+ but I don't see any way to improve upon the implementation
+ in ColorModel. */
+ return super.isCompatibleRaster(raster);
+ }
+
+ String stringParam()
+ {
+ return super.stringParam() +
+ ", redMask=" + Integer.toHexString(getRedMask()) +
+ ", greenMask=" + Integer.toHexString(getGreenMask()) +
+ ", blueMask=" + Integer.toHexString(getBlueMask()) +
+ ", alphaMask=" + Integer.toHexString(getAlphaMask());
+ }
+
+ public String toString()
+ {
+ /* FIXME: Again, docs say override, but how do we improve upon the
+ superclass implementation? */
+ return super.toString();
+ }
+}
diff --git a/libjava/classpath/java/awt/image/FilteredImageSource.java b/libjava/classpath/java/awt/image/FilteredImageSource.java
new file mode 100644
index 000000000..f56a93ad1
--- /dev/null
+++ b/libjava/classpath/java/awt/image/FilteredImageSource.java
@@ -0,0 +1,124 @@
+/* FilteredImageSource.java -- Java class for providing image data
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.util.Hashtable;
+
+/**
+ *
+ * @see ImageConsumer
+ * @author C. Brian Jones (cbj@gnu.org)
+ */
+public class FilteredImageSource implements ImageProducer
+{
+ ImageProducer ip;
+ ImageFilter filter;
+ Hashtable consumers = new Hashtable();
+
+ /**
+ * The given filter is applied to the given image producer
+ * to create a new image producer.
+ */
+ public FilteredImageSource(ImageProducer ip, ImageFilter filter) {
+ this.ip = ip;
+ this.filter = filter;
+ }
+
+ /**
+ * Used to register an <code>ImageConsumer</code> with this
+ * <code>ImageProducer</code>.
+ */
+ public synchronized void addConsumer(ImageConsumer ic) {
+ if (consumers.containsKey(ic))
+ return;
+
+ ImageFilter f = filter.getFilterInstance(ic);
+ consumers.put(ic, f);
+ ip.addConsumer(f);
+ }
+
+ /**
+ * Used to determine if the given <code>ImageConsumer</code> is
+ * already registered with this <code>ImageProducer</code>.
+ */
+ public synchronized boolean isConsumer(ImageConsumer ic) {
+ ImageFilter f = (ImageFilter)consumers.get(ic);
+ if (f != null)
+ return ip.isConsumer(f);
+ return false;
+ }
+
+ /**
+ * Used to remove an <code>ImageConsumer</code> from the list of
+ * registered consumers for this <code>ImageProducer</code>.
+ */
+ public synchronized void removeConsumer(ImageConsumer ic) {
+ ImageFilter f = (ImageFilter)consumers.remove(ic);
+ if (f != null)
+ ip.removeConsumer(f);
+ }
+
+ /**
+ * Used to register an <code>ImageConsumer</code> with this
+ * <code>ImageProducer</code> and then immediately start
+ * reconstruction of the image data to be delivered to all
+ * registered consumers.
+ */
+ public void startProduction(ImageConsumer ic) {
+ ImageFilter f;
+ if (!(consumers.containsKey(ic))) {
+ f = filter.getFilterInstance(ic);
+ consumers.put(ic, f);
+ ip.addConsumer(f);
+ } else {
+ f = (ImageFilter)consumers.get( ic );
+ }
+ ip.startProduction(f);
+ }
+
+ /**
+ * Used to register an <code>ImageConsumer</code> with this
+ * <code>ImageProducer</code> and then request that this producer
+ * resend the image data in the order top-down, left-right.
+ */
+ public void requestTopDownLeftRightResend(ImageConsumer ic) {
+ ImageFilter f = (ImageFilter)consumers.get(ic);
+ ip.requestTopDownLeftRightResend(f);
+ }
+}
diff --git a/libjava/classpath/java/awt/image/ImageConsumer.java b/libjava/classpath/java/awt/image/ImageConsumer.java
new file mode 100644
index 000000000..8f3c2b144
--- /dev/null
+++ b/libjava/classpath/java/awt/image/ImageConsumer.java
@@ -0,0 +1,216 @@
+/* ImageConsumer.java -- Java interface for image consumption
+ Copyright (C) 1999, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.util.Hashtable;
+
+/**
+ * An object implementing the <code>ImageProducer</code> interface can
+ * use objects implementing this interface to deliver the image data.
+ *
+ * @author C. Brian Jones (cbj@gnu.org)
+ */
+public interface ImageConsumer
+{
+ /**
+ * The pixel order may be random. This should be
+ * the default assumption of the <code>ImageConsumer</code>.
+ *
+ * @see #setHints
+ */
+ int RANDOMPIXELORDER = 1;
+
+ /**
+ * The pixel order is top-down, left-right.
+ *
+ * @see #setHints
+ */
+ int TOPDOWNLEFTRIGHT = 2;
+
+ /**
+ * The pixel order is in multiples of complete scanlines.
+ *
+ * @see #setHints
+ */
+ int COMPLETESCANLINES = 4;
+
+ /**
+ * The pixels will be delivered in a single pass. There is at
+ * most one call to <code>setPixels</code> for any single pixel.
+ *
+ * @see #setHints
+ * @see #setPixels(int, int, int, int, ColorModel, int[], int, int)
+ */
+ int SINGLEPASS = 8;
+
+ /**
+ * The pixels will be delivered with multiple calls to
+ * <code>setPixels</code>. The image contains a single frame
+ * which ends when <code>imageComplete</code> is called with the
+ * <code>STATICIMAGEDONE</code> flag. If the image is constantly
+ * changing such as with video then the end of each frame is
+ * marked by a similar call to <code>imageComplete</code> with the
+ * <code>SINGLEFRAMEDONE</code> flag.
+ *
+ * @see #setHints
+ * @see #imageComplete
+ */
+ int SINGLEFRAME = 16;
+
+ /**
+ * Indicates an error occurred while producing an image.
+ *
+ * @see #imageComplete
+ */
+ int IMAGEERROR = 1;
+
+ /**
+ * A single frame is complete but more will follow.
+ *
+ * @see #imageComplete
+ */
+ int SINGLEFRAMEDONE = 2;
+
+ /**
+ * The image is complete and no more pixels or frames will follow.
+ *
+ * @see #imageComplete
+ */
+ int STATICIMAGEDONE = 3;
+
+ /**
+ * Production of the image has been aborted.
+ *
+ * @see #imageComplete
+ */
+ int IMAGEABORTED = 4;
+
+ /**
+ * An <code>ImageProducer</code> indicates the size of the image
+ * being produced using this method.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ */
+ void setDimensions(int width, int height);
+
+ /**
+ * An <code>ImageProducer</code> can set a list of properties
+ * associated with this image by using this method.
+ *
+ * @param props the list of properties associated with this image
+ */
+ void setProperties(Hashtable<?,?> props);
+
+ /**
+ * This <code>ColorModel</code> should indicate the model used by
+ * the majority of calls to <code>setPixels</code>. Each call to
+ * <code>setPixels</code> could however indicate a different
+ * <code>ColorModel</code>.
+ *
+ * @param model the color model to be used most often by setPixels
+ * @see ColorModel
+ */
+ void setColorModel(ColorModel model);
+
+ /**
+ * The <code>ImageProducer</code> should call this method with a
+ * bit mask of hints from any of <code>RANDOMPIXELORDER</code>,
+ * <code>TOPDOWNLEFTRIGHT</code>, <code>COMPLETESCANLINES</code>,
+ * <code>SINGLEPASS</code>, <code>SINGLEFRAME</code>.
+ *
+ * @param flags a bit mask of hints
+ */
+ void setHints(int flags);
+
+ /**
+ * Deliver a subset of an ImageProducer's pixels to this ImageConsumer.
+ *
+ * Each element of the pixels array represents one pixel. The
+ * pixel data is formatted according to the color model model.
+ * The x and y parameters are the coordinates of the block of
+ * pixels being delivered to this ImageConsumer. They are
+ * specified relative to the top left corner of the image being
+ * produced. Likewise, w and h are the pixel block's dimensions.
+ *
+ * @param x x coordinate of pixel block
+ * @param y y coordinate of pixel block
+ * @param w width of pixel block
+ * @param h height of pixel block
+ * @param model color model used to interpret pixel data
+ * @param pixels pixel block data
+ * @param offset offset into pixels array
+ * @param scansize width of one row in the pixel block
+ */
+ void setPixels(int x, int y, int w, int h,
+ ColorModel model, byte[] pixels, int offset, int scansize);
+
+ /**
+ * Deliver a subset of an ImageProducer's pixels to this ImageConsumer.
+ *
+ * Each element of the pixels array represents one pixel. The
+ * pixel data is formatted according to the color model model.
+ * The x and y parameters are the coordinates of the rectangular
+ * region of pixels being delivered to this ImageConsumer,
+ * specified relative to the top left corner of the image being
+ * produced. Likewise, w and h are the pixel region's dimensions.
+ *
+ * @param x x coordinate of pixel block
+ * @param y y coordinate of pixel block
+ * @param w width of pixel block
+ * @param h height of pixel block
+ * @param model color model used to interpret pixel data
+ * @param pixels pixel block data
+ * @param offset offset into pixels array
+ * @param scansize width of one row in the pixel block
+ */
+ void setPixels(int x, int y, int w, int h,
+ ColorModel model, int[] pixels, int offset, int scansize);
+
+ /**
+ * The <code>ImageProducer</code> calls this method to indicate a
+ * single frame or the entire image is complete. The method is
+ * also used to indicate an error in loading or producing the
+ * image.
+ *
+ * @param status the status of image production, represented by a
+ * bitwise OR of ImageConsumer flags
+ */
+ void imageComplete(int status);
+}
diff --git a/libjava/classpath/java/awt/image/ImageFilter.java b/libjava/classpath/java/awt/image/ImageFilter.java
new file mode 100644
index 000000000..10df82e25
--- /dev/null
+++ b/libjava/classpath/java/awt/image/ImageFilter.java
@@ -0,0 +1,226 @@
+/* ImageFilter.java -- Java class for filtering images
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.util.Hashtable;
+
+/**
+ * The <code>ImageFilter</code> class is a base class which can be
+ * extended to provide different types of filters for an image. By
+ * default this class does nothing to an image passing through it.
+ *
+ * @author C. Brian Jones (cbj@gnu.org)
+ */
+public class ImageFilter implements ImageConsumer, Cloneable
+{
+ /**
+ * The consumer this filter is filtering an image data stream for.
+ * It is initialized in the method <code>getFilterInstance</code>.
+ */
+ protected ImageConsumer consumer = null;
+
+ /**
+ * The <code>ImageConsumer</code> can use this method to request
+ * the pixels be delivered in top-down, left-right order.
+ * <br>
+ * The filter can respond in three different ways.
+ * <ul>
+ * <li>The default behavior is to forward the request to the
+ * <code>ImageProducer</code>
+ * using the method <code>requestTopDownLeftRightResend</code>
+ * and using the filter as the consumer.</li>
+ * <li>The filter has the pixels and can retransmit them in the
+ * top-down, left-right order.</li>
+ * <li>The filter can do nothing when this method is called.</li>
+ * </ul>
+ */
+ public void resendTopDownLeftRight(ImageProducer ip)
+ {
+ ip.requestTopDownLeftRightResend(this);
+ }
+
+ /**
+ * By default, returns a shallow copy of the object created by
+ * <code>Object.clone()</code>
+ *
+ * @see java.lang.Object#clone ()
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ // This should never happen as this class implements the
+ // Cloneable interface.
+ throw new InternalError ();
+ }
+ }
+
+ /**
+ * This is the only method which can set the
+ * <code>ImageConsumer</code> for this filter. By default a clone
+ * of this filter with the appropriate consumer set is returned.
+ *
+ * @see #clone ()
+ */
+ public ImageFilter getFilterInstance(ImageConsumer ic)
+ {
+ ImageFilter f = (ImageFilter)clone();
+ f.consumer = ic;
+ return f;
+ }
+
+ /**
+ * An <code>ImageProducer</code> indicates the size of the image
+ * being produced using this method. A filter can override this
+ * method to intercept these calls from the producer in order to
+ * change either the width or the height before in turn calling
+ * the consumer's <code>setDimensions</code> method.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ */
+ public void setDimensions(int width, int height)
+ {
+ consumer.setDimensions(width, height);
+ }
+
+ /**
+ * An <code>ImageProducer</code> can set a list of properties
+ * associated with this image by using this method.
+ *
+ * @param props the list of properties associated with this image
+ */
+ public void setProperties(Hashtable<?,?> props)
+ {
+ Hashtable copy = (Hashtable) props.clone();
+ Object o = copy.get("filters");
+ if (o == null)
+ copy.put("filters", toString());
+ else if (o instanceof String)
+ copy.put("filters", ((String) o) + toString());
+
+ consumer.setProperties(copy);
+ }
+
+ /**
+ * Override this method to process calls to this method from the
+ * <code>ImageProducer</code>. By default the <code>setColorModel</code>
+ * method of the consumer is called with the specified <code>model</code>.
+ *
+ * @param model the color model to be used most often by setPixels
+ *
+ * @see ColorModel
+ */
+ public void setColorModel(ColorModel model)
+ {
+ consumer.setColorModel(model);
+ }
+
+ /**
+ * The <code>ImageProducer</code> should call this method with a
+ * bit mask of hints from any of <code>RANDOMPIXELORDER</code>,
+ * <code>TOPDOWNLEFTRIGHT</code>, <code>COMPLETESCANLINES</code>,
+ * <code>SINGLEPASS</code>, <code>SINGLEFRAME</code> from the
+ * <code>ImageConsumer</code> interface.
+ *
+ * @param flags a bit mask of hints
+ * @see ImageConsumer
+ */
+ public void setHints(int flags)
+ {
+ consumer.setHints(flags);
+ }
+
+ /**
+ * This function delivers a rectangle of pixels where any
+ * pixel(m,n) is stored in the array as a <code>byte</code> at
+ * index (n * scansize + m + offset).
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param model the <code>ColorModel</code> used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the <code>pixels</code> array
+ * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
+ */
+ public void setPixels(int x, int y, int w, int h,
+ ColorModel model, byte[] pixels, int offset,
+ int scansize)
+ {
+ consumer.setPixels(x, y, w, h, model, pixels, offset, scansize);
+ }
+
+ /**
+ * This function delivers a rectangle of pixels where any
+ * pixel(m,n) is stored in the array as an <code>int</code> at
+ * index (n * scansize + m + offset).
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param model the <code>ColorModel</code> used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the <code>pixels</code> array
+ * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
+ */
+ public void setPixels(int x, int y, int w, int h,
+ ColorModel model, int[] pixels, int offset,
+ int scansize)
+ {
+ consumer.setPixels(x, y, w, h, model, pixels, offset, scansize);
+ }
+
+ /**
+ * The <code>ImageProducer</code> calls this method to indicate a
+ * single frame or the entire image is complete. The method is
+ * also used to indicate an error in loading or producing the
+ * image.
+ */
+ public void imageComplete(int status)
+ {
+ consumer.imageComplete(status);
+ }
+}
diff --git a/libjava/classpath/java/awt/image/ImageObserver.java b/libjava/classpath/java/awt/image/ImageObserver.java
new file mode 100644
index 000000000..e63d4bba1
--- /dev/null
+++ b/libjava/classpath/java/awt/image/ImageObserver.java
@@ -0,0 +1,129 @@
+/* ImageObserver.java -- Java interface for asynchronous updates to an image
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.Image;
+
+/**
+ * An object implementing the <code>ImageObserver</code> interface can
+ * receive updates on image construction from an
+ * <code>ImageProducer</code> asynchronously.
+ *
+ * @see ImageProducer
+ * @author C. Brian Jones (cbj@gnu.org)
+ */
+public interface ImageObserver
+{
+ /**
+ * The width of the image has been provided as the
+ * <code>width</code> argument to <code>imageUpdate</code>.
+ *
+ * @see #imageUpdate
+ */
+ int WIDTH = 1;
+
+ /**
+ * The height of the image has been provided as the
+ * <code>height</code> argument to <code>imageUpdate</code>.
+ *
+ * @see #imageUpdate
+ */
+ int HEIGHT = 2;
+
+ /**
+ * The properties of the image have been provided.
+ *
+ * @see #imageUpdate
+ * @see java.awt.Image#getProperty (java.lang.String, java.awt.image.ImageObserver)
+ */
+ int PROPERTIES = 4;
+
+ /**
+ * More pixels are now available for drawing a scaled variation of
+ * the image.
+ *
+ * @see #imageUpdate
+ */
+ int SOMEBITS = 8;
+
+ /**
+ * All the pixels needed to draw a complete frame of a multi-frame
+ * image are available.
+ *
+ * @see #imageUpdate
+ */
+ int FRAMEBITS = 16;
+
+ /**
+ * An image with a single frame, a static image, is complete.
+ *
+ * @see #imageUpdate
+ */
+ int ALLBITS = 32;
+
+ /**
+ * An error was encountered while producing the image.
+ *
+ * @see #imageUpdate
+ */
+ int ERROR = 64;
+
+ /**
+ * Production of the image was aborted.
+ *
+ * @see #imageUpdate
+ */
+ int ABORT = 128;
+
+ /**
+ * This is a callback method for an asynchronous image producer to
+ * provide updates on the production of the image as it happens.
+ *
+ * @param image the image the update refers to
+ * @param flags a bit mask indicating what is provided with this update
+ * @param x the x coordinate of the image
+ * @param y the y coordinate of the image
+ * @param width the width of the image
+ * @param height the height of the image
+ *
+ * @see java.awt.Image
+ */
+ boolean imageUpdate(Image image, int flags, int x,
+ int y, int width, int height);
+}
diff --git a/libjava/classpath/java/awt/image/ImageProducer.java b/libjava/classpath/java/awt/image/ImageProducer.java
new file mode 100644
index 000000000..c0f9ad4c7
--- /dev/null
+++ b/libjava/classpath/java/awt/image/ImageProducer.java
@@ -0,0 +1,84 @@
+/* ImageProducer.java -- Java interface for image production
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+/**
+ * An object implementing the <code>ImageProducer</code> interface can
+ * produce data for images. Each image has a corresponding
+ * <code>ImageProducer</code> which is needed for things such as
+ * resizing the image.
+ *
+ * @see ImageConsumer
+ * @author C. Brian Jones (cbj@gnu.org)
+ */
+public interface ImageProducer
+{
+ /**
+ * Used to register an <code>ImageConsumer</code> with this
+ * <code>ImageProducer</code>.
+ */
+ void addConsumer(ImageConsumer ic);
+
+ /**
+ * Used to determine if the given <code>ImageConsumer</code> is
+ * already registered with this <code>ImageProducer</code>.
+ */
+ boolean isConsumer(ImageConsumer ic);
+
+ /**
+ * Used to remove an <code>ImageConsumer</code> from the list of
+ * registered consumers for this <code>ImageProducer</code>.
+ */
+ void removeConsumer(ImageConsumer ic);
+
+ /**
+ * Used to register an <code>ImageConsumer</code> with this
+ * <code>ImageProducer</code> and then immediately start
+ * reconstruction of the image data to be delivered to all
+ * registered consumers.
+ */
+ void startProduction(ImageConsumer ic);
+
+ /**
+ * Used to register an <code>ImageConsumer</code> with this
+ * <code>ImageProducer</code> and then request that this producer
+ * resend the image data in the order top-down, left-right.
+ */
+ void requestTopDownLeftRightResend(ImageConsumer ic);
+}
diff --git a/libjava/classpath/java/awt/image/ImagingOpException.java b/libjava/classpath/java/awt/image/ImagingOpException.java
new file mode 100644
index 000000000..ca40e9ed3
--- /dev/null
+++ b/libjava/classpath/java/awt/image/ImagingOpException.java
@@ -0,0 +1,66 @@
+/* ImagingOpException.java -- indicates an imaging filter failure
+ Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+/**
+ * This exception is thrown when <code>BufferedImageOp</code> or
+ * <code>RasterOp</code> filters cannot process an image.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see BufferedImageOp
+ * @see RasterOp
+ * @status updated to 1.4
+ */
+public class ImagingOpException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 8026288481846276658L;
+
+ /**
+ * Create a new instance with a descriptive error message.
+ *
+ * @param message the descriptive error message
+ */
+ public ImagingOpException(String message)
+ {
+ super(message);
+ }
+} // class ImagingOpException
diff --git a/libjava/classpath/java/awt/image/IndexColorModel.java b/libjava/classpath/java/awt/image/IndexColorModel.java
new file mode 100644
index 000000000..340d38e89
--- /dev/null
+++ b/libjava/classpath/java/awt/image/IndexColorModel.java
@@ -0,0 +1,736 @@
+/* IndexColorModel.java -- Java class for interpreting Pixel objects
+ Copyright (C) 1999, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+import gnu.java.awt.Buffers;
+
+import java.awt.color.ColorSpace;
+import java.math.BigInteger;
+
+/**
+ * Color model similar to pseudo visual in X11.
+ * <br><br>
+ * This color model maps linear pixel values to actual RGB and alpha colors.
+ * Thus, pixel values are indexes into the color map. Each color component is
+ * an 8-bit unsigned value.
+ * <br><br>
+ * The <code>IndexColorModel</code> supports a map of valid pixels, allowing
+ * the representation of holes in the the color map. The valid map is
+ * represented as a {@link BigInteger} where each bit indicates the validity
+ * of the map entry with the same index.
+ * <br><br>
+ * Colors can have alpha components for transparency support. If alpha
+ * component values aren't given, color values are opaque. The model also
+ * supports a reserved pixel value to represent completely transparent colors,
+ * no matter what the actual color component values are.
+ * <br><br>
+ * <code>IndexColorModel</code> supports anywhere from 1 to 16 bit index
+ * values. The allowed transfer types are {@link DataBuffer#TYPE_BYTE} and
+ * {@link DataBuffer#TYPE_USHORT}.
+ *
+ * @author C. Brian Jones (cbj@gnu.org)
+ */
+public class IndexColorModel extends ColorModel
+{
+ private int map_size;
+ private boolean opaque; // no alpha, but doesn't account for trans
+ private int trans = -1;
+ private int[] rgb;
+ private BigInteger validBits = BigInteger.ZERO;
+
+ /**
+ * Creates a new indexed color model for <code>size</code> color elements
+ * with no alpha component. Each array must contain at least
+ * <code>size</code> elements. For each array, the i-th color is described
+ * by reds[i], greens[i] and blues[i].
+ *
+ * @param bits the number of bits needed to represent <code>size</code>
+ * colors.
+ * @param size the number of colors in the color map.
+ * @param reds the red component of all colors.
+ * @param greens the green component of all colors.
+ * @param blues the blue component of all colors.
+ *
+ * @throws IllegalArgumentException if <code>bits</code> &lt; 1 or
+ * <code>bits</code> &gt; 16.
+ * @throws NullPointerException if any of the arrays is <code>null</code>.
+ * @throws ArrayIndexOutOfBoundsException if <code>size</code> is greater
+ * than the length of the component arrays.
+ */
+ public IndexColorModel(int bits, int size, byte[] reds, byte[] greens,
+ byte[] blues)
+ {
+ this(bits, size, reds, greens, blues, (byte[]) null);
+ }
+
+ /**
+ * Creates a new indexed color model for <code>size</code> color elements.
+ * Each array must contain at least <code>size</code> elements. For each
+ * array, the i-th color is described by reds[i], greens[i] and blues[i].
+ * All the colors are opaque except for the transparent color.
+ *
+ * @param bits the number of bits needed to represent <code>size</code>
+ * colors
+ * @param size the number of colors in the color map
+ * @param reds the red component of all colors
+ * @param greens the green component of all colors
+ * @param blues the blue component of all colors
+ * @param trans the index of the transparent color (use -1 for no
+ * transparent color).
+ *
+ * @throws IllegalArgumentException if <code>bits</code> &lt; 1 or
+ * <code>bits</code> &gt; 16.
+ * @throws NullPointerException if any of the arrays is <code>null</code>.
+ * @throws ArrayIndexOutOfBoundsException if <code>size</code> is greater
+ * than the length of the component arrays.
+ */
+ public IndexColorModel(int bits, int size, byte[] reds, byte[] greens,
+ byte[] blues, int trans)
+ {
+ super(bits, nArray(8, (0 <= trans && trans < size) ? 4 : 3),
+ ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ (0 <= trans && trans < size), // hasAlpha
+ false, OPAQUE,
+ Buffers.smallestAppropriateTransferType(bits));
+ if (bits < 1)
+ throw new IllegalArgumentException("bits < 1");
+ if (bits > 16)
+ throw new IllegalArgumentException("bits > 16");
+ if (size < 1)
+ throw new IllegalArgumentException("size < 1");
+ map_size = size;
+ rgb = createColorMap(bits, size);
+ for (int i = 0; i < size; i++)
+ {
+ rgb[i] = (0xff000000
+ | ((reds[i] & 0xff) << 16)
+ | ((greens[i] & 0xff) << 8)
+ | (blues[i] & 0xff));
+ }
+
+ setTransparentPixel(trans);
+
+ // Generate a bigint with 1's for every pixel
+ validBits = validBits.setBit(size).subtract(BigInteger.ONE);
+ }
+
+ /**
+ * Creates a new indexed color model for <code>size</code> color elements
+ * including alpha. Each array must contain at least <code>size</code>
+ * elements. For each array, the i-th color is described
+ * by reds[i], greens[i], blues[i] and alphas[i].
+ *
+ * @param bits the number of bits needed to represent <code>size</code>
+ * colors.
+ * @param size the number of colors in the color map.
+ * @param reds the red component of all colors.
+ * @param greens the green component of all colors.
+ * @param blues the blue component of all colors.
+ * @param alphas the alpha component of all colors (<code>null</code>
+ * permitted).
+ *
+ * @throws IllegalArgumentException if <code>bits</code> &lt; 1 or
+ * <code>bits</code> &gt; 16.
+ * @throws NullPointerException if <code>reds</code>, <code>greens</code> or
+ * <code>blues</code> is <code>null</code>.
+ * @throws ArrayIndexOutOfBoundsException if <code>size</code> is greater
+ * than the length of the component arrays.
+ */
+ public IndexColorModel(int bits, int size, byte[] reds, byte[] greens,
+ byte[] blues, byte[] alphas)
+ {
+ super(bits, nArray(8, (alphas == null ? 3 : 4)),
+ ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ (alphas != null), false, TRANSLUCENT,
+ Buffers.smallestAppropriateTransferType(bits));
+ if (bits < 1)
+ throw new IllegalArgumentException("bits < 1");
+ if (bits > 16)
+ throw new IllegalArgumentException("bits > 16");
+ if (size < 1)
+ throw new IllegalArgumentException("size < 1");
+ map_size = size;
+ opaque = (alphas == null);
+
+ rgb = createColorMap(bits, size);
+ if (alphas == null)
+ {
+ for (int i = 0; i < size; i++)
+ {
+ rgb[i] = (0xff000000
+ | ((reds[i] & 0xff) << 16)
+ | ((greens[i] & 0xff) << 8)
+ | (blues[i] & 0xff));
+ }
+ transparency = OPAQUE;
+ }
+ else
+ {
+ byte alphaZero = (byte) 0x00;
+ byte alphaOne = (byte) 0xFF;
+ for (int i = 0; i < size; i++)
+ {
+ alphaZero = (byte) (alphaZero | alphas[i]);
+ alphaOne = (byte) (alphaOne & alphas[i]);
+ rgb[i] = ((alphas[i] & 0xff) << 24
+ | ((reds[i] & 0xff) << 16)
+ | ((greens[i] & 0xff) << 8)
+ | (blues[i] & 0xff));
+ }
+ if ((alphaZero == (byte) 0x00) || (alphaOne == (byte) 0xFF))
+ transparency = BITMASK;
+ else
+ transparency = TRANSLUCENT;
+ }
+
+ // Generate a bigint with 1's for every pixel
+ validBits = validBits.setBit(size).subtract(BigInteger.ONE);
+ }
+
+ /**
+ * Creates a new indexed color model using the color components in
+ * <code>cmap</code>. If <code>hasAlpha</code> is <code>true</code> then
+ * <code>cmap</code> contains an alpha component after each of the red, green
+ * and blue components.
+ *
+ * @param bits the number of bits needed to represent <code>size</code>
+ * colors
+ * @param size the number of colors in the color map
+ * @param cmap packed color components
+ * @param start the offset of the first color component in <code>cmap</code>
+ * @param hasAlpha <code>cmap</code> has alpha values
+ * @throws IllegalArgumentException if bits &lt; 1, bits &gt; 16, or size
+ * &lt; 1.
+ * @throws NullPointerException if <code>cmap</code> is <code>null</code>.
+ */
+ public IndexColorModel(int bits, int size, byte[] cmap, int start,
+ boolean hasAlpha)
+ {
+ this(bits, size, cmap, start, hasAlpha, -1);
+ }
+
+ /**
+ * Construct an IndexColorModel from an array of red, green, blue, and
+ * optional alpha components. The component values are interleaved as RGB(A).
+ *
+ * @param bits the number of bits needed to represent <code>size</code>
+ * colors
+ * @param size the number of colors in the color map
+ * @param cmap interleaved color components
+ * @param start the offset of the first color component in <code>cmap</code>
+ * @param hasAlpha <code>cmap</code> has alpha values
+ * @param trans the index of the transparent color
+ * @throws IllegalArgumentException if bits &lt; 1, bits &gt; 16, or size
+ * &lt; 1.
+ * @throws NullPointerException if <code>cmap</code> is <code>null</code>.
+ */
+ public IndexColorModel(int bits, int size, byte[] cmap, int start,
+ boolean hasAlpha, int trans)
+ {
+ super(bits, nArray(8, hasAlpha || (0 <= trans && trans < size) ? 4 : 3),
+ ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ hasAlpha || (0 <= trans && trans < size), false, OPAQUE,
+ Buffers.smallestAppropriateTransferType(bits));
+ if (bits < 1)
+ throw new IllegalArgumentException("bits < 1");
+ if (bits > 16)
+ throw new IllegalArgumentException("bits > 16");
+ if (size < 1)
+ throw new IllegalArgumentException("size < 1");
+ map_size = size;
+ opaque = !hasAlpha;
+
+ rgb = createColorMap(bits, size);
+ if (hasAlpha)
+ {
+ int alpha;
+ int alphaZero = 0x00; // use to detect all zeros
+ int alphaOne = 0xff; // use to detect all ones
+ for (int i = 0; i < size; i++) {
+ alpha = cmap[4 * i + 3 + start] & 0xff;
+ alphaZero = alphaZero | alpha;
+ alphaOne = alphaOne & alpha;
+ rgb[i] =
+ ( alpha << 24
+ // red
+ | ((cmap[4 * i + start] & 0xff) << 16)
+ // green
+ | ((cmap[4 * i + 1 + start] & 0xff) << 8)
+ // blue
+ | (cmap[4 * i + 2 + start] & 0xff));
+ }
+ if (alphaZero == 0)
+ transparency = BITMASK;
+ else if (alphaOne == 255)
+ transparency = (trans != -1 ? BITMASK : OPAQUE);
+ else
+ transparency = TRANSLUCENT;
+ }
+ else
+ {
+ for (int i = 0; i < size; i++)
+ rgb[i] = (0xff000000
+ // red
+ | ((cmap[3 * i + start] & 0xff) << 16)
+ // green
+ | ((cmap[3 * i + 1 + start] & 0xff) << 8)
+ // blue
+ | (cmap[3 * i + 2 + start] & 0xff));
+ if (trans != -1)
+ transparency = BITMASK;
+ }
+
+ setTransparentPixel(trans);
+
+ // Generate a bigint with 1's for every pixel
+ validBits = validBits.setBit(size).subtract(BigInteger.ONE);
+ }
+
+ /**
+ * Construct an IndexColorModel from an array of <code>size</code> packed
+ * colors. Each int element contains 8-bit red, green, blue, and optional
+ * alpha values packed in order. If hasAlpha is false, then all the colors
+ * are opaque except for the transparent color.
+ *
+ * @param bits the number of bits needed to represent <code>size</code>
+ * colors
+ * @param size the number of colors in the color map
+ * @param cmap packed color components
+ * @param start the offset of the first color component in <code>cmap</code>
+ * @param hasAlpha <code>cmap</code> has alpha values
+ * @param trans the index of the transparent color
+ * @param transferType {@link DataBuffer#TYPE_BYTE} or
+ {@link DataBuffer#TYPE_USHORT}.
+ * @throws IllegalArgumentException if bits &lt; 1, bits &gt; 16, or size
+ * &lt; 1.
+ * @throws IllegalArgumentException if <code>transferType</code> is something
+ * other than {@link DataBuffer#TYPE_BYTE} or
+ * {@link DataBuffer#TYPE_USHORT}.
+ */
+ public IndexColorModel(int bits, int size, int[] cmap, int start,
+ boolean hasAlpha, int trans, int transferType)
+ {
+ super(bits,
+ nArray(8, 4), // bits for each channel
+ ColorSpace.getInstance(ColorSpace.CS_sRGB), // sRGB
+ true, // has alpha
+ false, // not premultiplied
+ TRANSLUCENT, transferType);
+ if (transferType != DataBuffer.TYPE_BYTE
+ && transferType != DataBuffer.TYPE_USHORT)
+ throw new IllegalArgumentException();
+ if (bits > 16)
+ throw new IllegalArgumentException("bits > 16");
+ if (size < 1)
+ throw new IllegalArgumentException("size < 1");
+ map_size = size;
+ opaque = !hasAlpha;
+ rgb = createColorMap(bits, size);
+ if (!hasAlpha)
+ for (int i = 0; i < size; i++)
+ rgb[i] = cmap[i + start] | 0xff000000;
+ else
+ System.arraycopy(cmap, start, rgb, 0, size);
+
+ setTransparentPixel(trans);
+
+ // Generate a bigint with 1's for every pixel
+ validBits = validBits.setBit(size).subtract(BigInteger.ONE);
+ }
+
+ /**
+ * Construct an IndexColorModel using a colormap with holes.
+ * <br><br>
+ * The IndexColorModel is built from the array of ints defining the
+ * colormap. Each element contains red, green, blue, and alpha
+ * components. The ColorSpace is sRGB. The transparency value is
+ * automatically determined.
+ * <br><br>
+ * This constructor permits indicating which colormap entries are valid,
+ * using the validBits argument. Each entry in cmap is valid if the
+ * corresponding bit in validBits is set.
+ *
+ * @param bits the number of bits needed to represent <code>size</code>
+ * colors.
+ * @param size the number of colors in the color map.
+ * @param cmap packed color components.
+ * @param start the offset of the first color component in <code>cmap</code>.
+ * @param transferType {@link DataBuffer#TYPE_BYTE} or
+ * {@link DataBuffer#TYPE_USHORT}.
+ * @param validBits a map of the valid entries in <code>cmap</code>.
+ * @throws IllegalArgumentException if bits &lt; 1, bits &gt; 16, or size
+ * &lt; 1.
+ * @throws IllegalArgumentException if transferType is something other than
+ * {@link DataBuffer#TYPE_BYTE} or {@link DataBuffer#TYPE_USHORT}.
+ */
+ public IndexColorModel(int bits, int size, int[] cmap, int start,
+ int transferType, BigInteger validBits)
+ {
+ super(bits, // total bits, sRGB, four channels
+ nArray(8, 4), // bits for each channel
+ ColorSpace.getInstance(ColorSpace.CS_sRGB), // sRGB
+ true, // has alpha
+ false, // not premultiplied
+ TRANSLUCENT, transferType);
+ if (transferType != DataBuffer.TYPE_BYTE
+ && transferType != DataBuffer.TYPE_USHORT)
+ throw new IllegalArgumentException();
+ if (bits > 16)
+ throw new IllegalArgumentException("bits > 16");
+ if (size < 1)
+ throw new IllegalArgumentException("size < 1");
+ map_size = size;
+ opaque = false;
+ this.trans = -1;
+ this.validBits = validBits;
+
+ rgb = createColorMap(bits, size);
+ if (!hasAlpha)
+ for (int i = 0; i < size; i++)
+ rgb[i] = cmap[i + start] | 0xff000000;
+ else
+ System.arraycopy(cmap, start, rgb, 0, size);
+ }
+
+ /**
+ * Returns the size of the color lookup table.
+ *
+ * @return The size of the color lookup table.
+ */
+ public final int getMapSize()
+ {
+ return map_size;
+ }
+
+ /**
+ * Get the index of the transparent color in this color model.
+ *
+ * @return The index of the color that is considered transparent, or -1 if
+ * there is no transparent color.
+ */
+ public final int getTransparentPixel()
+ {
+ return trans;
+ }
+
+ /**
+ * Fills the supplied array with the red component of each color in the
+ * lookup table.
+ *
+ * @param r an array that is at least as large as {@link #getMapSize()}.
+ * @throws NullPointerException if <code>r</code> is <code>null</code>.
+ * @throws ArrayIndexOutOfBoundsException if <code>r</code> has less
+ * than {@link #getMapSize()} elements.
+ */
+ public final void getReds(byte[] r)
+ {
+ int i;
+ for (i = 0; i < map_size; i++)
+ r[i] = (byte) ((0x00FF0000 & rgb[i]) >> 16);
+ }
+
+ /**
+ * Fills the supplied array with the green component of each color in the
+ * lookup table.
+ *
+ * @param g an array that is at least as large as {@link #getMapSize()}.
+ * @throws NullPointerException if <code>g</code> is <code>null</code>.
+ * @throws ArrayIndexOutOfBoundsException if <code>g</code> has less
+ * than {@link #getMapSize()} elements.
+ */
+ public final void getGreens(byte[] g)
+ {
+ int i;
+ for (i = 0; i < map_size; i++)
+ g[i] = (byte) ((0x0000FF00 & rgb[i]) >> 8);
+ }
+
+ /**
+ * Fills the supplied array with the blue component of each color in the
+ * lookup table.
+ *
+ * @param b an array that is at least as large as {@link #getMapSize()}.
+ * @throws NullPointerException if <code>b</code> is <code>null</code>.
+ * @throws ArrayIndexOutOfBoundsException if <code>b</code> has less
+ * than {@link #getMapSize()} elements.
+ */
+ public final void getBlues(byte[] b)
+ {
+ int i;
+ for (i = 0; i < map_size; i++)
+ b[i] = (byte) (0x000000FF & rgb[i]);
+ }
+
+ /**
+ * Fills the supplied array with the alpha component of each color in the
+ * lookup table. If the model has a transparent pixel specified, the alpha
+ * for that pixel will be 0.
+ *
+ * @param a an array that is at least as large as {@link #getMapSize()}.
+ * @throws NullPointerException if <code>a</code> is <code>null</code>.
+ * @throws ArrayIndexOutOfBoundsException if <code>a</code> has less
+ * than {@link #getMapSize()} elements.
+ */
+ public final void getAlphas(byte[] a)
+ {
+ int i;
+ for (i = 0; i < map_size; i++)
+ if (i == trans)
+ a[i] = (byte) 0;
+ else
+ a[i] = (byte) ((0xFF000000 & rgb[i]) >> 24);
+ }
+
+ /**
+ * Returns the red component of the color in the lookup table for the
+ * given pixel value.
+ *
+ * @param pixel the pixel lookup value.
+ *
+ * @return The red component of the color in the lookup table.
+ * @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative.
+ */
+ public final int getRed(int pixel)
+ {
+ if (pixel < map_size)
+ return (0x00FF0000 & rgb[pixel]) >> 16;
+
+ return 0;
+ }
+
+ /**
+ * Returns the green component of the color in the lookup table for the
+ * given pixel value.
+ *
+ * @param pixel the pixel lookup value.
+ *
+ * @return The green component of the color in the lookup table.
+ * @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative.
+ */
+ public final int getGreen(int pixel)
+ {
+ if (pixel < map_size)
+ return (0x0000FF00 & rgb[pixel]) >> 8;
+
+ return 0;
+ }
+
+ /**
+ * Returns the blue component of the color in the lookup table for the
+ * given pixel value.
+ *
+ * @param pixel the pixel lookup value.
+ *
+ * @return The blue component of the color in the lookup table.
+ * @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative.
+ */
+ public final int getBlue(int pixel)
+ {
+ if (pixel < map_size)
+ return 0x000000FF & rgb[pixel];
+
+ return 0;
+ }
+
+ /**
+ * Returns the alpha component of the color in the lookup table for the
+ * given pixel value. If no alpha channel was specified when the color model
+ * was created, then 255 is returned for all pixels except the transparent
+ * pixel (if one is defined - see {@link #getTransparentPixel()}) which
+ * returns an alpha of 0.
+ *
+ * @param pixel the pixel lookup value.
+ *
+ * @return The alpha component of the color in the lookup table (in the
+ * range 0 to 255).
+ * @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative.
+ */
+ public final int getAlpha(int pixel)
+ {
+ return (rgb[pixel] >> 24) & 0xFF;
+ }
+
+ /**
+ * Get the RGB color value of the given pixel using the default
+ * RGB color model.
+ *
+ * @param pixel the pixel lookup value.
+ * @return The RGB color value.
+ * @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative.
+ */
+ public final int getRGB(int pixel)
+ {
+ if (pixel >= 0 && pixel < map_size)
+ return rgb[pixel];
+
+ return 0;
+ }
+
+ /**
+ * Get the RGB color values of all pixels in the map using the default
+ * RGB color model.
+ *
+ * @param rgb The destination array.
+ */
+ public final void getRGBs(int[] rgb)
+ {
+ System.arraycopy(this.rgb, 0, rgb, 0, map_size);
+ }
+
+ /**
+ * Return <code>true</code> if the lookup table contains valid data for
+ * <code>pixel</code>, and <code>false</code> otherwise.
+ *
+ * @param pixel the pixel value used to index the color lookup table.
+ * @return <code>true</code> if <code>pixel</code> is valid,
+ * <code>false</code> otherwise.
+ */
+ public boolean isValid(int pixel)
+ {
+ if (pixel >= 0)
+ return validBits.testBit(pixel);
+ return false;
+ }
+
+ /**
+ * Return <code>true</code> if all pixels are valid, <code>false</code>
+ * otherwise.
+ *
+ * @return <code>true</code> if all pixels are valid, <code>false</code>
+ * otherwise.
+ */
+ public boolean isValid()
+ {
+ // Generate a bigint with 1's for every pixel
+ BigInteger allbits = new BigInteger("0");
+ allbits = allbits.setBit(map_size);
+ allbits = allbits.subtract(new BigInteger("1"));
+ return allbits.equals(validBits);
+ }
+
+ /**
+ * Returns a binary value ({@link BigInteger}) where each bit represents an
+ * entry in the color lookup table. If the bit is on, the entry is valid.
+ *
+ * @return The binary value.
+ */
+ public BigInteger getValidPixels()
+ {
+ return validBits;
+ }
+
+ /**
+ * Construct a {@link BufferedImage} with rgb pixel values from a
+ * {@link Raster}.
+ *
+ * Constructs a new BufferedImage in which each pixel is an RGBA int from
+ * a Raster with index-valued pixels. If this model has no alpha component
+ * or transparent pixel, the type of the new BufferedImage is TYPE_INT_RGB.
+ * Otherwise the type is TYPE_INT_ARGB. If forceARGB is true, the type is
+ * forced to be TYPE_INT_ARGB no matter what.
+ *
+ * @param raster The source of pixel values.
+ * @param forceARGB True if type must be TYPE_INT_ARGB.
+ * @return New BufferedImage with RBGA int pixel values.
+ */
+ public BufferedImage convertToIntDiscrete(Raster raster, boolean forceARGB)
+ {
+ int type = forceARGB ? BufferedImage.TYPE_INT_ARGB
+ : ((opaque && trans == -1) ? BufferedImage.TYPE_INT_RGB :
+ BufferedImage.TYPE_INT_ARGB);
+
+ // FIXME: assuming that raster has only 1 band since pixels are supposed
+ // to be int indexes.
+ // FIXME: it would likely be more efficient to fetch a complete array,
+ // but it would take much more memory.
+ // FIXME: I'm not sure if transparent pixels or alpha values need special
+ // handling here.
+ BufferedImage im = new BufferedImage(raster.width, raster.height, type);
+ for (int x = raster.minX; x < raster.width + raster.minX; x++)
+ for (int y = raster.minY; y < raster.height + raster.minY; y++)
+ im.setRGB(x, y, rgb[raster.getSample(x, y, 0)]);
+
+ return im;
+ }
+
+ /**
+ * Creates a {@link SampleModel} that is compatible to this color model.
+ * This will be a {@link MultiPixelPackedSampleModel} for bits/pixel of
+ * 1, 2 or 4, or a {@link ComponentColorModel} for the other cases.
+ *
+ * @param w the width of the sample model to create
+ * @param h the height of the sample model to create
+ *
+ * @return a compatible sample model
+ */
+ public SampleModel createCompatibleSampleModel(int w, int h)
+ {
+ SampleModel sm;
+ if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4)
+ sm = new MultiPixelPackedSampleModel(transferType, w, h, pixel_bits);
+ else
+ sm = new ComponentSampleModel(transferType, w, h, 1, w, new int[]{0});
+ return sm;
+ }
+
+ /**
+ * Sets the transparent pixel. This is called by the various constructors.
+ *
+ * @param t the transparent pixel
+ */
+ private void setTransparentPixel(int t)
+ {
+ if (t >= 0 && t < map_size)
+ {
+ rgb[t] &= 0xffffff; // Make the value transparent.
+ trans = t;
+ if (transparency == OPAQUE)
+ {
+ transparency = BITMASK;
+ hasAlpha = true;
+ }
+ }
+ }
+
+ private int[] createColorMap(int bits, int size)
+ {
+ // According to a Mauve test, the RI allocates at least 256 entries here.
+ int realSize = Math.max(256, Math.max(1 << bits, size));
+ return new int[realSize];
+ }
+}
diff --git a/libjava/classpath/java/awt/image/Kernel.java b/libjava/classpath/java/awt/image/Kernel.java
new file mode 100644
index 000000000..ae0ff1469
--- /dev/null
+++ b/libjava/classpath/java/awt/image/Kernel.java
@@ -0,0 +1,171 @@
+/* Kernel.java -- Java class for an image processing kernel
+ Copyright (C) 2004, 2005, 2006, Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+/**
+ * Kernel represents an image processing kernel. It gets used to hold
+ * convolution filters among other purposes. It stores an array of float
+ * values representing a 2-dimensional array in row-major order.
+ *
+ * @author Jerry Quinn (jlquinn@optonline.net)
+ */
+public class Kernel implements Cloneable
+{
+ /** The kernel width. */
+ private final int width;
+
+ /** The kernel height. */
+ private final int height;
+
+ /** Internal storage for the kernel's values. */
+ private final float[] data;
+
+ /**
+ * Creates a new <code>Kernel</code> instance with the specified dimensions
+ * and values. The first <code>width * height</code> values in the specified
+ * <code>data</code> array are copied to internal storage.
+ *
+ * @param width the kernel width.
+ * @param height the kernel height.
+ * @param data the source data array (<code>null</code> not permitted).
+ *
+ * @throws IllegalArgumentException if <code>data.length</code> is less than
+ * <code>width * height</code>.
+ * @throws IllegalArgumentException if <code>width</code> or
+ * <code>height</code> is less than zero.
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
+ public Kernel(int width, int height, float[] data)
+ throws IllegalArgumentException
+ {
+ this.width = width;
+ this.height = height;
+ if (data.length < width * height || width < 0 || height < 0)
+ throw new IllegalArgumentException();
+ this.data = new float[width * height];
+ System.arraycopy(data, 0, this.data, 0, width * height);
+ }
+
+ /**
+ * Returns the x-origin for the kernel, which is calculated as
+ * <code>(width - 1) / 2</code>.
+ *
+ * @return The x-origin for the kernel.
+ */
+ public final int getXOrigin()
+ {
+ return (width - 1) / 2;
+ }
+
+ /**
+ * Returns the y-origin for the kernel, which is calculated as
+ * <code>(height - 1) / 2</code>.
+ *
+ * @return The y-origin for the kernel.
+ */
+ public final int getYOrigin()
+ {
+ return (height - 1) / 2;
+ }
+
+ /**
+ * Returns the kernel width (as supplied to the constructor).
+ *
+ * @return The kernel width.
+ */
+ public final int getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Returns the kernel height (as supplied to the constructor).
+ *
+ * @return The kernel height.
+ */
+ public final int getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * Returns an array containing a copy of the kernel data. If the
+ * <code>data</code> argument is non-<code>null</code>, the kernel values
+ * are copied into it and then <code>data</code> is returned as the result.
+ * If the <code>data</code> argument is <code>null</code>, this method
+ * allocates a new array then populates and returns it.
+ *
+ * @param data an array to copy the return values into (if
+ * <code>null</code>, a new array is allocated).
+ *
+ * @return The array with copied values.
+ *
+ * @throws IllegalArgumentException if <code>data.length</code> is less than
+ * the kernel's <code>width * height</code>.
+ */
+ public final float[] getKernelData(float[] data)
+ throws IllegalArgumentException
+ {
+ if (data == null)
+ return (float[]) this.data.clone();
+
+ if (data.length < this.data.length)
+ throw new IllegalArgumentException();
+
+ System.arraycopy(this.data, 0, data, 0, this.data.length);
+ return data;
+ }
+
+ /**
+ * Returns a clone of this kernel.
+ *
+ * @return a clone of this Kernel.
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // Impossible
+ }
+ }
+}
diff --git a/libjava/classpath/java/awt/image/LookupOp.java b/libjava/classpath/java/awt/image/LookupOp.java
new file mode 100644
index 000000000..0bc79a00b
--- /dev/null
+++ b/libjava/classpath/java/awt/image/LookupOp.java
@@ -0,0 +1,307 @@
+/* LookupOp.java -- Filter that converts each pixel using a lookup table.
+ Copyright (C) 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.RenderingHints;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * LookupOp is a filter that converts each pixel using a lookup table.
+ *
+ * For filtering Rasters, the lookup table must have either one component
+ * that is applied to all bands, or one component for every band in the
+ * Rasters.
+ *
+ * For BufferedImages, the lookup table may apply to both color and alpha
+ * components. If the lookup table contains one component, or if there are
+ * the same number of components as color components in the source, the table
+ * applies to all color components. Otherwise the table applies to all
+ * components including alpha. Alpha premultiplication is ignored during the
+ * lookup filtering.
+ *
+ * After filtering, if color conversion is necessary, the conversion happens,
+ * taking alpha premultiplication into account.
+ *
+ * @author jlquinn
+ */
+public class LookupOp implements BufferedImageOp, RasterOp
+{
+ private LookupTable lut;
+ private RenderingHints hints;
+
+ /**
+ * Construct a new LookupOp using the given LookupTable.
+ *
+ * @param lookup LookupTable to use.
+ * @param hints Rendering hints (can be null).
+ */
+ public LookupOp(LookupTable lookup, RenderingHints hints)
+ {
+ lut = lookup;
+ this.hints = hints;
+ }
+
+ /**
+ * Converts the source image using the lookup table specified in the
+ * constructor. The resulting image is stored in the destination image if one
+ * is provided; otherwise a new BufferedImage is created and returned.
+ *
+ * The source image cannot use an IndexColorModel, and the destination image
+ * (if one is provided) must have the same size.
+ *
+ * @param src The source image.
+ * @param dst The destination image.
+ * @throws IllegalArgumentException if the rasters and/or color spaces are
+ * incompatible.
+ * @throws ArrayIndexOutOfBoundsException if a pixel in the source is not
+ * contained in the LookupTable.
+ * @return The convolved image.
+ */
+ public final BufferedImage filter(BufferedImage src, BufferedImage dst)
+ {
+ if (src.getColorModel() instanceof IndexColorModel)
+ throw new IllegalArgumentException("LookupOp.filter: IndexColorModel "
+ + "not allowed");
+
+ if (lut.getNumComponents() != 1
+ && lut.getNumComponents() != src.getColorModel().getNumComponents()
+ && lut.getNumComponents() != src.getColorModel().getNumColorComponents())
+ throw new IllegalArgumentException("LookupOp.filter: Incompatible " +
+ "lookup table and source image");
+
+ if (dst == null)
+ dst = createCompatibleDestImage(src, null);
+
+ else if (src.getHeight() != dst.getHeight() || src.getWidth() != dst.getWidth())
+ throw new IllegalArgumentException("Source and destination images are " +
+ "different sizes.");
+
+ // Set up for potential colormodel mismatch
+ BufferedImage tgt;
+ if (dst.getColorModel().equals(src.getColorModel()))
+ tgt = dst;
+ else
+ tgt = createCompatibleDestImage(src, src.getColorModel());
+
+ Raster sr = src.getRaster();
+ WritableRaster dr = tgt.getRaster();
+
+ if (src.getColorModel().hasAlpha() &&
+ (lut.getNumComponents() == 1 ||
+ lut.getNumComponents() == src.getColorModel().getNumColorComponents()))
+ {
+ // Need to ignore alpha for lookup
+ int[] dbuf = new int[src.getColorModel().getNumComponents()];
+ int tmpBands = src.getColorModel().getNumColorComponents();
+ int[] tmp = new int[tmpBands];
+
+ // Filter the pixels
+ for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
+ for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
+ {
+ // Filter only color components, but also copy alpha
+ sr.getPixel(x, y, dbuf);
+ System.arraycopy(dbuf, 0, tmp, 0, tmpBands);
+ dr.setPixel(x, y, lut.lookupPixel(tmp, dbuf));
+
+ /* The reference implementation does not use LookupTable.lookupPixel,
+ * but rather it seems to copy the table into a native array. The
+ * effect of this (a probable bug in their implementation) is that
+ * an out-of-bounds lookup on a ByteLookupTable will *not* throw an
+ * out of bounds exception, but will instead return random garbage.
+ * A bad lookup on a ShortLookupTable, however, will throw an
+ * exception.
+ *
+ * Instead of mimicing this behaviour, we always throw an
+ * ArrayOutofBoundsException by virtue of using
+ * LookupTable.lookupPixle.
+ */
+ }
+ }
+ else
+ {
+ // No alpha to ignore
+ int[] dbuf = new int[src.getColorModel().getNumComponents()];
+
+ // Filter the pixels
+ for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
+ for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
+ dr.setPixel(x, y, lut.lookupPixel(sr.getPixel(x, y, dbuf), dbuf));
+ }
+
+ if (tgt != dst)
+ new ColorConvertOp(hints).filter(tgt, dst);
+
+ return dst;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#getBounds2D(java.awt.image.BufferedImage)
+ */
+ public final Rectangle2D getBounds2D(BufferedImage src)
+ {
+ return src.getRaster().getBounds();
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#createCompatibleDestImage(java.awt.image.BufferedImage, java.awt.image.ColorModel)
+ */
+ public BufferedImage createCompatibleDestImage(BufferedImage src,
+ ColorModel dstCM)
+ {
+ if (dstCM != null)
+ return new BufferedImage(dstCM,
+ src.getRaster().createCompatibleWritableRaster(),
+ src.isAlphaPremultiplied(), null);
+
+ // This is a strange exception, done for compatibility with the reference
+ // (as demonstrated by a mauve testcase)
+ int imgType = src.getType();
+ if (imgType == BufferedImage.TYPE_USHORT_GRAY)
+ imgType = BufferedImage.TYPE_BYTE_GRAY;
+
+ return new BufferedImage(src.getWidth(), src.getHeight(), imgType);
+ }
+
+ /**
+ * Returns the corresponding destination point for a given source point.
+ *
+ * This Op will return the source point unchanged.
+ *
+ * @param src The source point.
+ * @param dst The destination point.
+ */
+ public final Point2D getPoint2D(Point2D src, Point2D dst)
+ {
+ if (dst == null)
+ return (Point2D) src.clone();
+
+ dst.setLocation(src);
+ return dst;
+ }
+
+ /**
+ * Return the LookupTable for this op.
+ *
+ * @return The lookup table.
+ */
+ public final LookupTable getTable()
+ {
+ return lut;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#getRenderingHints()
+ */
+ public final RenderingHints getRenderingHints()
+ {
+ return hints;
+ }
+
+ /**
+ * Filter a raster through a lookup table.
+ *
+ * Applies the lookup table for this Rasterop to each pixel of src and
+ * puts the results in dest. If dest is null, a new Raster is created and
+ * returned.
+ *
+ * @param src The source raster.
+ * @param dest The destination raster.
+ * @return The WritableRaster with the filtered pixels.
+ * @throws IllegalArgumentException if lookup table has more than one
+ * component but not the same as src and dest.
+ * @throws ArrayIndexOutOfBoundsException if a pixel in the source is not
+ * contained in the LookupTable.
+ */
+ public final WritableRaster filter(Raster src, WritableRaster dest)
+ {
+ if (dest == null)
+ // Allocate a raster if needed
+ dest = createCompatibleDestRaster(src);
+ else
+ if (src.getNumBands() != dest.getNumBands())
+ throw new IllegalArgumentException("Source and destination rasters " +
+ "are incompatible.");
+
+ if (lut.getNumComponents() != 1
+ && lut.getNumComponents() != src.getNumBands())
+ throw new IllegalArgumentException("Lookup table is incompatible with " +
+ "this raster.");
+
+ // Allocate pixel storage.
+ int[] tmp = new int[src.getNumBands()];
+
+ // Filter the pixels
+ for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
+ for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
+ dest.setPixel(x, y, lut.lookupPixel(src.getPixel(x, y, tmp), tmp));
+
+ /* The reference implementation does not use LookupTable.lookupPixel,
+ * but rather it seems to copy the table into a native array. The
+ * effect of this (a probable bug in their implementation) is that
+ * an out-of-bounds lookup on a ByteLookupTable will *not* throw an
+ * out of bounds exception, but will instead return random garbage.
+ * A bad lookup on a ShortLookupTable, however, will throw an
+ * exception.
+ *
+ * Instead of mimicing this behaviour, we always throw an
+ * ArrayOutofBoundsException by virtue of using
+ * LookupTable.lookupPixle.
+ */
+ return dest;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#getBounds2D(java.awt.image.Raster)
+ */
+ public final Rectangle2D getBounds2D(Raster src)
+ {
+ return src.getBounds();
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#createCompatibleDestRaster(java.awt.image.Raster)
+ */
+ public WritableRaster createCompatibleDestRaster(Raster src)
+ {
+ return src.createCompatibleWritableRaster();
+ }
+
+}
diff --git a/libjava/classpath/java/awt/image/LookupTable.java b/libjava/classpath/java/awt/image/LookupTable.java
new file mode 100644
index 000000000..d104b2fd5
--- /dev/null
+++ b/libjava/classpath/java/awt/image/LookupTable.java
@@ -0,0 +1,109 @@
+/* LookupTable.java -- Java class for a pixel translation table.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+/**
+ * LookupTable represents translation arrays for pixel values. It wraps one
+ * or more data arrays for each layer (or component) in an image, such as
+ * Alpha, R, G, and B. When doing translation, the offset is subtracted from
+ * the pixel values to allow a subset of an array to be used.
+ *
+ * @see ByteLookupTable
+ * @see ShortLookupTable
+ *
+ * @author Jerry Quinn (jlquinn@optonline.net)
+ * @version 1.0
+ */
+public abstract class LookupTable
+{
+ // Not protected since that's part of the public API.
+ int offset;
+ int numComponents;
+
+ /**
+ * Creates a new <code>LookupTable</code> instance.
+ *
+ * If numComponents is 1, the same translation table is used for all pixel
+ * components.
+ *
+ * @param offset Offset to be subtracted.
+ * @param numComponents Number of image components.
+ * @exception IllegalArgumentException if offset < 0 or numComponents < 1.
+ */
+ protected LookupTable(int offset, int numComponents)
+ throws IllegalArgumentException
+ {
+ if (offset < 0 || numComponents < 1)
+ throw new IllegalArgumentException();
+ this.offset = offset;
+ this.numComponents = numComponents;
+ }
+
+ /** Return the number of components. */
+ public int getNumComponents()
+ {
+ return numComponents;
+ }
+
+ /** Return the offset. */
+ public int getOffset()
+ {
+ return offset;
+ }
+
+
+ /**
+ * Return translated values for a pixel.
+ *
+ * For each value in the pixel src, use the value minus offset as an index
+ * in the component array and copy the value there to the output for the
+ * component. If dest is null, the output is a new array, otherwise the
+ * translated values are written to dest. Dest can be the same array as
+ * src.
+ *
+ * For example, if the pixel src is [2, 4, 3], and offset is 1, the output
+ * is [comp1[1], comp2[3], comp3[2]], where comp1, comp2, and comp3 are the
+ * translation arrays.
+ *
+ * @param src Component values of a pixel.
+ * @param dest Destination array for values, or null.
+ * @return Translated values for the pixel.
+ */
+ public abstract int[] lookupPixel(int[] src, int[] dest);
+}
diff --git a/libjava/classpath/java/awt/image/MemoryImageSource.java b/libjava/classpath/java/awt/image/MemoryImageSource.java
new file mode 100644
index 000000000..e8780f6f5
--- /dev/null
+++ b/libjava/classpath/java/awt/image/MemoryImageSource.java
@@ -0,0 +1,429 @@
+/* MemoryImageSource.java -- Java class for providing image data
+ Copyright (C) 1999, 2004, 2006, Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.util.Hashtable;
+import java.util.Vector;
+
+/**
+ * An image producer that delivers image data from an array.
+ */
+public class MemoryImageSource implements ImageProducer
+{
+ private boolean animated = false;
+ private boolean fullbuffers = false;
+ private int[] pixeli;
+ private int width;
+ private int height;
+ private int offset;
+ private int scansize;
+ private byte[] pixelb;
+ private ColorModel cm;
+ private Hashtable props = new Hashtable();
+ private Vector consumers = new Vector();
+
+ /**
+ * Construct an image producer that reads image data from a byte
+ * array.
+ *
+ * @param w width of image
+ * @param h height of image
+ * @param cm the color model used to represent pixel values
+ * @param pix a byte array of pixel values
+ * @param off the offset into the array at which the first pixel is stored
+ * @param scan the number of array elements that represents a single pixel row
+ */
+ public MemoryImageSource(int w, int h, ColorModel cm, byte[] pix, int off,
+ int scan)
+ {
+ this(w, h, cm, pix, off, scan, null);
+ }
+
+ /**
+ * Constructs an ImageProducer from memory.
+ *
+ * @param w the image width.
+ * @param h the image height.
+ * @param cm the color model.
+ * @param pix the image data.
+ * @param off the offset to the first pixel in the array.
+ * @param scan the number of array elements from a pixel on one row to the
+ * corresponding pixel on the next row.
+ * @param props image properties (<code>null</code> permitted).
+ */
+ public MemoryImageSource(int w, int h, ColorModel cm, byte[] pix, int off,
+ int scan, Hashtable<?,?> props)
+ {
+ width = w;
+ height = h;
+ this.cm = cm;
+ offset = off;
+ scansize = scan;
+ this.props = props;
+ int max = ((scansize > width) ? scansize : width);
+ pixelb = pix;
+ }
+
+ /**
+ * Construct an image producer that reads image data from an
+ * integer array.
+ *
+ * @param w width of image
+ * @param h height of image
+ * @param cm the color model used to represent pixel values
+ * @param pix an integer array of pixel values
+ * @param off the offset into the array at which the first pixel is stored
+ * @param scan the number of array elements that represents a single pixel row
+ */
+ public MemoryImageSource(int w, int h, ColorModel cm, int[] pix, int off,
+ int scan)
+ {
+ this(w, h, cm, pix, off, scan, null);
+ }
+
+ /**
+ * Constructs an ImageProducer from memory
+ *
+ * @param w the image width.
+ * @param h the image height.
+ * @param cm the color model.
+ * @param pix the image data.
+ * @param off the offset to the first pixel in the array.
+ * @param scan the number of array elements from a pixel on one row to the
+ * corresponding pixel on the next row.
+ * @param props image properties (<code>null</code> permitted).
+ */
+ public MemoryImageSource(int w, int h, ColorModel cm, int[] pix, int off,
+ int scan, Hashtable<?,?> props)
+ {
+ width = w;
+ height = h;
+ this.cm = cm;
+ offset = off;
+ scansize = scan;
+ this.props = props;
+ int max = ((scansize > width) ? scansize : width);
+ pixeli = pix;
+ }
+
+ /**
+ * Constructs an ImageProducer from memory using the default RGB ColorModel.
+ *
+ * @param w the image width.
+ * @param h the image height.
+ * @param pix the image data.
+ * @param off the offset to the first pixel in the array.
+ * @param scan the number of array elements from a pixel on one row to the
+ * corresponding pixel on the next row.
+ * @param props image properties (<code>null</code> permitted).
+
+ */
+ public MemoryImageSource(int w, int h, int[] pix, int off, int scan,
+ Hashtable<?,?> props)
+ {
+ this(w, h, ColorModel.getRGBdefault(), pix, off, scan, props);
+ }
+
+ /**
+ * Constructs an ImageProducer from memory using the default RGB ColorModel.
+ *
+ * @param w the image width.
+ * @param h the image height.
+ * @param pix the image data.
+ * @param off the offset to the first pixel in the array.
+ * @param scan the number of array elements from a pixel on one row to the
+ * corresponding pixel on the next row.
+ */
+ public MemoryImageSource(int w, int h, int[] pix, int off, int scan)
+ {
+ this(w, h, ColorModel.getRGBdefault(), pix, off, scan, null);
+ }
+
+ /**
+ * Used to register an <code>ImageConsumer</code> with this
+ * <code>ImageProducer</code>.
+ *
+ * @param ic the image consumer.
+ */
+ public synchronized void addConsumer(ImageConsumer ic)
+ {
+ if (consumers.contains(ic))
+ return;
+
+ consumers.addElement(ic);
+ }
+
+ /**
+ * Used to determine if the given <code>ImageConsumer</code> is
+ * already registered with this <code>ImageProducer</code>.
+ *
+ * @param ic the image consumer.
+ */
+ public synchronized boolean isConsumer(ImageConsumer ic)
+ {
+ if (consumers.contains(ic))
+ return true;
+ return false;
+ }
+
+ /**
+ * Used to remove an <code>ImageConsumer</code> from the list of
+ * registered consumers for this <code>ImageProducer</code>.
+ *
+ * @param ic the image consumer.
+ */
+ public synchronized void removeConsumer(ImageConsumer ic)
+ {
+ consumers.removeElement(ic);
+ }
+
+ /**
+ * Used to register an <code>ImageConsumer</code> with this
+ * <code>ImageProducer</code> and then immediately start
+ * reconstruction of the image data to be delivered to all
+ * registered consumers.
+ */
+ public void startProduction(ImageConsumer ic)
+ {
+ if (! (consumers.contains(ic)))
+ consumers.addElement(ic);
+
+ Vector list = (Vector) consumers.clone();
+ for (int i = 0; i < list.size(); i++)
+ {
+ ic = (ImageConsumer) list.elementAt(i);
+ sendPicture(ic);
+ if (animated)
+ ic.imageComplete(ImageConsumer.SINGLEFRAMEDONE);
+ else
+ ic.imageComplete(ImageConsumer.STATICIMAGEDONE);
+ }
+ }
+
+ /**
+ * Used to register an <code>ImageConsumer</code> with this
+ * <code>ImageProducer</code> and then request that this producer
+ * resend the image data in the order top-down, left-right.
+ *
+ * @param ic the image consumer.
+ */
+ public void requestTopDownLeftRightResend(ImageConsumer ic)
+ {
+ startProduction(ic);
+ }
+
+ /**
+ * Changes a flag to indicate whether this MemoryImageSource supports
+ * animations.
+ *
+ * @param animated A flag indicating whether this class supports animations
+ */
+ public synchronized void setAnimated(boolean animated)
+ {
+ this.animated = animated;
+ }
+
+ /**
+ * A flag to indicate whether or not to send full buffer updates when
+ * sending animation. If this flag is set then full buffers are sent
+ * in the newPixels methods instead of just regions.
+ *
+ * @param fullbuffers a flag indicating whether to send the full buffers
+ */
+ public synchronized void setFullBufferUpdates(boolean fullbuffers)
+ {
+ this.fullbuffers = fullbuffers;
+ }
+
+ /**
+ * Send an animation frame to the image consumers.
+ */
+ public void newPixels()
+ {
+ if (animated == true)
+ {
+ ImageConsumer ic;
+ Vector list = (Vector) consumers.clone();
+ for (int i = 0; i < list.size(); i++)
+ {
+ ic = (ImageConsumer) list.elementAt(i);
+ sendPicture(ic);
+ ic.imageComplete(ImageConsumer.SINGLEFRAME);
+ }
+ }
+ }
+
+ private void sendPicture(ImageConsumer ic)
+ {
+ ic.setHints(ImageConsumer.TOPDOWNLEFTRIGHT);
+ if (props != null)
+ ic.setProperties(props);
+ ic.setDimensions(width, height);
+ ic.setColorModel(cm);
+ if (pixeli != null)
+ ic.setPixels(0, 0, width, height, cm, pixeli, offset, scansize);
+ else
+ ic.setPixels(0, 0, width, height, cm, pixelb, offset, scansize);
+ }
+
+ /**
+ * Send an animation frame to the image consumers containing the specified
+ * pixels unless setFullBufferUpdates is set.
+ *
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ * @param w the width.
+ * @param h the height.
+ */
+ public synchronized void newPixels(int x, int y, int w, int h)
+ {
+ if (animated == true)
+ {
+ if (fullbuffers)
+ newPixels();
+ else
+ {
+ ImageConsumer ic;
+ Vector list = (Vector) consumers.clone();
+ for (int i = 0; i < list.size(); i++)
+ {
+ ic = (ImageConsumer) list.elementAt(i);
+ ic.setHints(ImageConsumer.TOPDOWNLEFTRIGHT);
+ if (props != null)
+ ic.setProperties(props);
+ if (pixeli != null)
+ {
+ int[] pixelbuf = new int[w * h];
+ for (int row = y; row < y + h; row++)
+ System.arraycopy(pixeli, row * scansize + x + offset,
+ pixelbuf, 0, w * h);
+ ic.setPixels(x, y, w, h, cm, pixelbuf, 0, w);
+ }
+ else
+ {
+ byte[] pixelbuf = new byte[w * h];
+ for (int row = y; row < y + h; row++)
+ System.arraycopy(pixelb, row * scansize + x + offset,
+ pixelbuf, 0, w * h);
+
+ ic.setPixels(x, y, w, h, cm, pixelbuf, 0, w);
+ }
+ ic.imageComplete(ImageConsumer.SINGLEFRAME);
+ }
+ }
+ }
+ }
+
+ /**
+ * Send an animation frame to the image consumers containing the specified
+ * pixels unless setFullBufferUpdates is set.
+ *
+ * If framenotify is set then a notification is sent when the frame
+ * is sent otherwise no status is sent.
+ *
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ * @param w the width.
+ * @param h the height.
+ * @param framenotify send notification?
+ */
+ public synchronized void newPixels(int x, int y, int w, int h,
+ boolean framenotify)
+ {
+ if (animated == true)
+ {
+ if (fullbuffers)
+ newPixels();
+ else
+ {
+ ImageConsumer ic;
+ Vector list = (Vector) consumers.clone();
+ for (int i = 0; i < list.size(); i++)
+ {
+ ic = (ImageConsumer) list.elementAt(i);
+ ic.setHints(ImageConsumer.TOPDOWNLEFTRIGHT);
+ if (props != null)
+ ic.setProperties(props);
+ if (pixeli != null)
+ {
+ int[] pixelbuf = new int[w * h];
+ for (int row = y; row < y + h; row++)
+ System.arraycopy(pixeli, row * scansize + x + offset,
+ pixelbuf, 0, w * h);
+ ic.setPixels(x, y, w, h, cm, pixelbuf, 0, w);
+ }
+ else
+ {
+ byte[] pixelbuf = new byte[w * h];
+ for (int row = y; row < y + h; row++)
+ System.arraycopy(pixelb, row * scansize + x + offset,
+ pixelbuf, 0, w * h);
+ ic.setPixels(x, y, w, h, cm, pixelbuf, 0, w);
+ }
+ if (framenotify == true)
+ ic.imageComplete(ImageConsumer.SINGLEFRAME);
+ }
+ }
+ }
+ }
+
+ public synchronized void newPixels(byte[] newpix, ColorModel newmodel,
+ int offset, int scansize)
+ {
+ pixeli = null;
+ pixelb = newpix;
+ cm = newmodel;
+ this.offset = offset;
+ this.scansize = scansize;
+ if (animated == true)
+ newPixels();
+ }
+
+ public synchronized void newPixels(int[] newpix, ColorModel newmodel,
+ int offset, int scansize)
+ {
+ pixelb = null;
+ pixeli = newpix;
+ cm = newmodel;
+ this.offset = offset;
+ this.scansize = scansize;
+ if (animated == true)
+ newPixels();
+ }
+}
diff --git a/libjava/classpath/java/awt/image/MultiPixelPackedSampleModel.java b/libjava/classpath/java/awt/image/MultiPixelPackedSampleModel.java
new file mode 100644
index 000000000..592611cbb
--- /dev/null
+++ b/libjava/classpath/java/awt/image/MultiPixelPackedSampleModel.java
@@ -0,0 +1,603 @@
+/* Copyright (C) 2004, 2006, Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+import gnu.java.awt.Buffers;
+import gnu.java.lang.CPStringBuilder;
+
+/**
+ * MultiPixelPackedSampleModel provides a single band model that supports
+ * multiple pixels in a single unit. Pixels have 2^n bits and 2^k pixels fit
+ * per data element.
+ *
+ * @author Jerry Quinn (jlquinn@optonline.net)
+ */
+public class MultiPixelPackedSampleModel extends SampleModel
+{
+ private int scanlineStride;
+ private int[] bitMasks;
+ private int[] bitOffsets;
+ private int[] sampleSize;
+ private int dataBitOffset;
+ private int elemBits;
+ private int numberOfBits;
+ private int numElems;
+
+ /**
+ * Creates a new <code>MultiPixelPackedSampleModel</code> with the specified
+ * data type, which should be one of:
+ * <ul>
+ * <li>{@link DataBuffer#TYPE_BYTE};</li>
+ * <li>{@link DataBuffer#TYPE_USHORT};</li>
+ * <li>{@link DataBuffer#TYPE_INT};</li>
+ * </ul>
+ *
+ * @param dataType the data type.
+ * @param w the width (in pixels).
+ * @param h the height (in pixels).
+ * @param numberOfBits the number of bits per pixel (must be a power of 2).
+ */
+ public MultiPixelPackedSampleModel(int dataType, int w, int h,
+ int numberOfBits)
+ {
+ this(dataType, w, h, numberOfBits, 0, 0);
+ }
+
+ /**
+ * Creates a new <code>MultiPixelPackedSampleModel</code> with the specified
+ * data type, which should be one of:
+ * <ul>
+ * <li>{@link DataBuffer#TYPE_BYTE};</li>
+ * <li>{@link DataBuffer#TYPE_USHORT};</li>
+ * <li>{@link DataBuffer#TYPE_INT};</li>
+ * </ul>
+ *
+ * @param dataType the data type.
+ * @param w the width (in pixels).
+ * @param h the height (in pixels).
+ * @param numberOfBits the number of bits per pixel (must be a power of 2).
+ * @param scanlineStride the number of data elements from a pixel on one
+ * row to the corresponding pixel in the next row.
+ * @param dataBitOffset the offset to the first data bit.
+ */
+ public MultiPixelPackedSampleModel(int dataType, int w, int h,
+ int numberOfBits, int scanlineStride,
+ int dataBitOffset)
+ {
+ super(dataType, w, h, 1);
+
+ switch (dataType)
+ {
+ case DataBuffer.TYPE_BYTE:
+ elemBits = 8;
+ break;
+ case DataBuffer.TYPE_USHORT:
+ elemBits = 16;
+ break;
+ case DataBuffer.TYPE_INT:
+ elemBits = 32;
+ break;
+ default:
+ throw new IllegalArgumentException("MultiPixelPackedSampleModel"
+ + " unsupported dataType");
+ }
+
+ this.dataBitOffset = dataBitOffset;
+
+ this.numberOfBits = numberOfBits;
+ if (numberOfBits > elemBits)
+ throw new RasterFormatException("MultiPixelPackedSampleModel pixel size"
+ + " larger than dataType");
+ switch (numberOfBits)
+ {
+ case 1: case 2: case 4: case 8: case 16: case 32: break;
+ default:
+ throw new RasterFormatException("MultiPixelPackedSampleModel pixel"
+ + " size not 2^n bits");
+ }
+ numElems = elemBits / numberOfBits;
+
+ // Compute scan line large enough for w pixels.
+ if (scanlineStride == 0)
+ scanlineStride = ((dataBitOffset + w * numberOfBits) - 1) / elemBits + 1;
+ this.scanlineStride = scanlineStride;
+
+
+ sampleSize = new int[1];
+ sampleSize[0] = numberOfBits;
+
+ bitMasks = new int[numElems];
+ bitOffsets = new int[numElems];
+ for (int i=0; i < numElems; i++)
+ {
+ bitOffsets[numElems - i- 1] = numberOfBits * i;
+ bitMasks[numElems - i - 1] = ((1 << numberOfBits) - 1) <<
+ bitOffsets[numElems - i - 1];
+ }
+ }
+
+ /**
+ * Creates a new <code>MultiPixelPackedSample</code> model with the same
+ * data type and bits per pixel as this model, but with the specified
+ * dimensions.
+ *
+ * @param w the width (in pixels).
+ * @param h the height (in pixels).
+ *
+ * @return The new sample model.
+ */
+ public SampleModel createCompatibleSampleModel(int w, int h)
+ {
+ /* FIXME: We can avoid recalculation of bit offsets and sample
+ sizes here by passing these from the current instance to a
+ special private constructor. */
+ return new MultiPixelPackedSampleModel(dataType, w, h, numberOfBits);
+ }
+
+ /**
+ * Creates a DataBuffer for holding pixel data in the format and
+ * layout described by this SampleModel. The returned buffer will
+ * consist of one single bank.
+ *
+ * @return A new data buffer.
+ */
+ public DataBuffer createDataBuffer()
+ {
+ int size = scanlineStride * height;
+ if (dataBitOffset > 0)
+ size += (dataBitOffset - 1) / elemBits + 1;
+ return Buffers.createBuffer(getDataType(), size);
+ }
+
+ /**
+ * Returns the number of data elements required to transfer a pixel in the
+ * get/setDataElements() methods.
+ *
+ * @return <code>1</code>.
+ */
+ public int getNumDataElements()
+ {
+ return 1;
+ }
+
+ /**
+ * Returns an array containing the size (in bits) of the samples in each
+ * band. The <code>MultiPixelPackedSampleModel</code> class supports only
+ * one band, so this method returns an array with length <code>1</code>.
+ *
+ * @return An array containing the size (in bits) of the samples in band zero.
+ *
+ * @see #getSampleSize(int)
+ */
+ public int[] getSampleSize()
+ {
+ return (int[]) sampleSize.clone();
+ }
+
+ /**
+ * Returns the size of the samples in the specified band. Note that the
+ * <code>MultiPixelPackedSampleModel</code> supports only one band -- this
+ * method ignored the <code>band</code> argument, and always returns the size
+ * of band zero.
+ *
+ * @param band the band (this parameter is ignored).
+ *
+ * @return The size of the samples in band zero.
+ *
+ * @see #getSampleSize()
+ */
+ public int getSampleSize(int band)
+ {
+ return sampleSize[0];
+ }
+
+ /**
+ * Returns the index in the data buffer that stores the pixel at (x, y).
+ *
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ *
+ * @return The index in the data buffer that stores the pixel at (x, y).
+ *
+ * @see #getBitOffset(int)
+ */
+ public int getOffset(int x, int y)
+ {
+ return scanlineStride * y + ((dataBitOffset + x * numberOfBits) / elemBits);
+ }
+
+ /**
+ * The bit offset (within an element in the data buffer) of the pixels with
+ * the specified x-coordinate.
+ *
+ * @param x the x-coordinate.
+ *
+ * @return The bit offset.
+ */
+ public int getBitOffset(int x)
+ {
+ return (dataBitOffset + x * numberOfBits) % elemBits;
+ }
+
+ /**
+ * Returns the offset to the first data bit.
+ *
+ * @return The offset to the first data bit.
+ */
+ public int getDataBitOffset()
+ {
+ return dataBitOffset;
+ }
+
+ /**
+ * Returns the number of data elements from a pixel in one row to the
+ * corresponding pixel in the next row.
+ *
+ * @return The scanline stride.
+ */
+ public int getScanlineStride()
+ {
+ return scanlineStride;
+ }
+
+ /**
+ * Returns the number of bits per pixel.
+ *
+ * @return The number of bits per pixel.
+ */
+ public int getPixelBitStride()
+ {
+ return numberOfBits;
+ }
+
+ /**
+ * Returns the transfer type, which is one of the following (depending on
+ * the number of bits per sample for this model):
+ * <ul>
+ * <li>{@link DataBuffer#TYPE_BYTE};</li>
+ * <li>{@link DataBuffer#TYPE_USHORT};</li>
+ * <li>{@link DataBuffer#TYPE_INT};</li>
+ * </ul>
+ *
+ * @return The transfer type.
+ */
+ public int getTransferType()
+ {
+ if (numberOfBits <= DataBuffer.getDataTypeSize(DataBuffer.TYPE_BYTE))
+ return DataBuffer.TYPE_BYTE;
+ else if (numberOfBits <= DataBuffer.getDataTypeSize(DataBuffer.TYPE_USHORT))
+ return DataBuffer.TYPE_USHORT;
+ return DataBuffer.TYPE_INT;
+ }
+
+ /**
+ * Normally this method returns a sample model for accessing a subset of
+ * bands of image data, but since <code>MultiPixelPackedSampleModel</code>
+ * only supports a single band, this overridden implementation just returns
+ * a new instance of <code>MultiPixelPackedSampleModel</code>, with the same
+ * attributes as this instance.
+ *
+ * @param bands the bands to include in the subset (this is ignored, except
+ * that if it is non-<code>null</code> a check is made to ensure that the
+ * array length is equal to <code>1</code>).
+ *
+ * @throws RasterFormatException if <code>bands</code> is not
+ * <code>null</code> and <code>bands.length != 1</code>.
+ */
+ public SampleModel createSubsetSampleModel(int[] bands)
+ {
+ if (bands != null && bands.length != 1)
+ throw new RasterFormatException("MultiPixelPackedSampleModel only"
+ + " supports one band");
+ return new MultiPixelPackedSampleModel(dataType, width, height,
+ numberOfBits, scanlineStride, dataBitOffset);
+ }
+
+ /**
+ * Extract one pixel and return in an array of transfer type.
+ *
+ * Extracts the pixel at x, y from data and stores into the 0th index of the
+ * array obj, since there is only one band. If obj is null, a new array of
+ * getTransferType() is created.
+ *
+ * @param x The x-coordinate of the pixel rectangle to store in
+ * <code>obj</code>.
+ * @param y The y-coordinate of the pixel rectangle to store in
+ * <code>obj</code>.
+ * @param obj The primitive array to store the pixels into or null to force
+ * creation.
+ * @param data The DataBuffer that is the source of the pixel data.
+ * @return The primitive array containing the pixel data.
+ * @see java.awt.image.SampleModel#getDataElements(int, int, Object,
+ * DataBuffer)
+ */
+ public Object getDataElements(int x, int y, Object obj, DataBuffer data)
+ {
+ int pixel = getSample(x, y, 0, data);
+ switch (getTransferType())
+ {
+ case DataBuffer.TYPE_BYTE:
+ if (obj == null)
+ obj = new byte[1];
+ ((byte[]) obj)[0] = (byte) pixel;
+ return obj;
+ case DataBuffer.TYPE_USHORT:
+ if (obj == null)
+ obj = new short[1];
+ ((short[]) obj)[0] = (short) pixel;
+ return obj;
+ case DataBuffer.TYPE_INT:
+ if (obj == null)
+ obj = new int[1];
+ ((int[]) obj)[0] = pixel;
+ return obj;
+ default:
+ // Seems like the only sensible thing to do.
+ throw new ClassCastException();
+ }
+ }
+
+ /**
+ * Returns an array (of length 1) containing the sample for the pixel at
+ * (x, y) in the specified data buffer. If <code>iArray</code> is not
+ * <code>null</code>, it will be populated with the sample value and
+ * returned as the result of this function (this avoids allocating a new
+ * array instance).
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param iArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return An array containing the pixel sample value.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
+ public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
+ {
+ if (iArray == null)
+ iArray = new int[1];
+ iArray[0] = getSample(x, y, 0, data);
+ return iArray;
+ }
+
+ /**
+ * Returns the sample value for the pixel at (x, y) in the specified data
+ * buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The sample value.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
+ public int getSample(int x, int y, int b, DataBuffer data)
+ {
+ int pos =
+ ((dataBitOffset + x * numberOfBits) % elemBits) / numberOfBits;
+ int offset = getOffset(x, y);
+ int samples = data.getElem(offset);
+ return (samples & bitMasks[pos]) >>> bitOffsets[pos];
+ }
+
+ /**
+ * Set the pixel at x, y to the value in the first element of the primitive
+ * array obj.
+ *
+ * @param x The x-coordinate of the data elements in <code>obj</code>.
+ * @param y The y-coordinate of the data elements in <code>obj</code>.
+ * @param obj The primitive array containing the data elements to set.
+ * @param data The DataBuffer to store the data elements into.
+ */
+ public void setDataElements(int x, int y, Object obj, DataBuffer data)
+ {
+ int transferType = getTransferType();
+ try
+ {
+ switch (transferType)
+ {
+ case DataBuffer.TYPE_BYTE:
+ {
+ byte[] in = (byte[]) obj;
+ setSample(x, y, 0, in[0] & 0xFF, data);
+ return;
+ }
+ case DataBuffer.TYPE_USHORT:
+ {
+ short[] in = (short[]) obj;
+ setSample(x, y, 0, in[0] & 0xFFFF, data);
+ return;
+ }
+ case DataBuffer.TYPE_INT:
+ {
+ int[] in = (int[]) obj;
+ setSample(x, y, 0, in[0], data);
+ return;
+ }
+ default:
+ throw new ClassCastException("Unsupported data type");
+ }
+ }
+ catch (ArrayIndexOutOfBoundsException aioobe)
+ {
+ String msg = "While writing data elements" +
+ ", x=" + x + ", y=" + y +
+ ", width=" + width + ", height=" + height +
+ ", scanlineStride=" + scanlineStride +
+ ", offset=" + getOffset(x, y) +
+ ", data.getSize()=" + data.getSize() +
+ ", data.getOffset()=" + data.getOffset() +
+ ": " + aioobe;
+ throw new ArrayIndexOutOfBoundsException(msg);
+ }
+ }
+
+ /**
+ * Sets the sample value for the pixel at (x, y) in the specified data
+ * buffer to the specified value.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param iArray the sample value (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>iArray</code> or
+ * <code>data</code> is <code>null</code>.
+ *
+ * @see #setSample(int, int, int, int, DataBuffer)
+ */
+ public void setPixel(int x, int y, int[] iArray, DataBuffer data)
+ {
+ setSample(x, y, 0, iArray[0], data);
+ }
+
+ /**
+ * Sets the sample value for a band for the pixel at (x, y) in the
+ * specified data buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param s the sample value.
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
+ public void setSample(int x, int y, int b, int s, DataBuffer data)
+ {
+ int bitpos =
+ ((dataBitOffset + x * numberOfBits) % elemBits) / numberOfBits;
+ int offset = getOffset(x, y);
+
+ s = s << bitOffsets[bitpos];
+ s = s & bitMasks[bitpos];
+
+ int sample = data.getElem(offset);
+ sample |= s;
+ data.setElem(offset, sample);
+ }
+
+ /**
+ * Tests this sample model for equality with an arbitrary object. This
+ * method returns <code>true</code> if and only if:
+ * <ul>
+ * <li><code>obj</code> is not <code>null</code>;
+ * <li><code>obj</code> is an instance of
+ * <code>MultiPixelPackedSampleModel</code>;
+ * <li>both models have the same:
+ * <ul>
+ * <li><code>dataType</code>;
+ * <li><code>width</code>;
+ * <li><code>height</code>;
+ * <li><code>numberOfBits</code>;
+ * <li><code>scanlineStride</code>;
+ * <li><code>dataBitOffsets</code>.
+ * </ul>
+ * </li>
+ * </ul>
+ *
+ * @param obj the object (<code>null</code> permitted)
+ *
+ * @return <code>true</code> if this model is equal to <code>obj</code>, and
+ * <code>false</code> otherwise.
+ */
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ return true;
+ if (! (obj instanceof MultiPixelPackedSampleModel))
+ return false;
+ MultiPixelPackedSampleModel that = (MultiPixelPackedSampleModel) obj;
+ if (this.dataType != that.dataType)
+ return false;
+ if (this.width != that.width)
+ return false;
+ if (this.height != that.height)
+ return false;
+ if (this.numberOfBits != that.numberOfBits)
+ return false;
+ if (this.scanlineStride != that.scanlineStride)
+ return false;
+ if (this.dataBitOffset != that.dataBitOffset)
+ return false;
+ return true;
+ }
+
+ /**
+ * Returns a hash code for this <code>MultiPixelPackedSampleModel</code>.
+ *
+ * @return A hash code.
+ */
+ public int hashCode()
+ {
+ // this hash code won't match Sun's, but that shouldn't matter...
+ int result = 193;
+ result = 37 * result + dataType;
+ result = 37 * result + width;
+ result = 37 * result + height;
+ result = 37 * result + numberOfBits;
+ result = 37 * result + scanlineStride;
+ result = 37 * result + dataBitOffset;
+ return result;
+ }
+
+ /**
+ * Creates a String with some information about this SampleModel.
+ * @return A String describing this SampleModel.
+ * @see java.lang.Object#toString()
+ */
+ public String toString()
+ {
+ CPStringBuilder result = new CPStringBuilder();
+ result.append(getClass().getName());
+ result.append("[");
+ result.append("scanlineStride=").append(scanlineStride);
+ for(int i=0; i < bitMasks.length; i+=1)
+ {
+ result.append(", mask[").append(i).append("]=0x").append(Integer.toHexString(bitMasks[i]));
+ }
+
+ result.append("]");
+ return result.toString();
+ }
+}
diff --git a/libjava/classpath/java/awt/image/PackedColorModel.java b/libjava/classpath/java/awt/image/PackedColorModel.java
new file mode 100644
index 000000000..a89d73b8c
--- /dev/null
+++ b/libjava/classpath/java/awt/image/PackedColorModel.java
@@ -0,0 +1,188 @@
+/* Copyright (C) 2000, 2002, 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import gnu.java.awt.BitMaskExtent;
+
+import java.awt.Point;
+import java.awt.color.ColorSpace;
+
+/**
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public abstract class PackedColorModel extends ColorModel
+{
+ private int masks[];
+
+ /* Package accessibility, the DirectColorModel needs this array */
+ int shifts[];
+
+ public PackedColorModel(ColorSpace cspace, int pixelBits,
+ int[] colorMaskArray, int alphaMask,
+ boolean isAlphaPremultiplied,
+ int transparency,
+ int transferType)
+ {
+ super(pixelBits, calcBitsPerComponent(colorMaskArray, alphaMask),
+ cspace, (alphaMask != 0), isAlphaPremultiplied, transparency,
+ transferType);
+ initMasks(colorMaskArray, alphaMask);
+ if ((pixelBits<1) || (pixelBits>32)) {
+ throw new IllegalArgumentException("pixels per bits must be " +
+ "in the range [1, 32]");
+ }
+ }
+
+ private static int[] calcBitsPerComponent(int[] colorMaskArray,
+ int alphaMask)
+ {
+ int numComponents = colorMaskArray.length;
+ if (alphaMask != 0) numComponents++;
+
+ int[] bitsPerComponent = new int[numComponents];
+
+ BitMaskExtent extent = new BitMaskExtent();
+ for (int b=0; b<colorMaskArray.length; b++)
+ {
+ extent.setMask(colorMaskArray[b]);
+ bitsPerComponent[b] = extent.bitWidth;
+ }
+ if (alphaMask != 0)
+ {
+ extent.setMask(alphaMask);
+ bitsPerComponent[numComponents-1] = extent.bitWidth;
+ }
+ return bitsPerComponent;
+ }
+
+ /** Initializes the masks. */
+ private void initMasks(int[] colorMaskArray, int alphaMask)
+ {
+ int numComponents = colorMaskArray.length;
+ if (alphaMask == 0)
+ {
+ masks = colorMaskArray;
+ }
+ else
+ {
+ masks = new int[numComponents+1];
+ System.arraycopy(colorMaskArray, 0,
+ masks, 0,
+ numComponents);
+ masks[numComponents++] = alphaMask;
+ }
+
+ shifts = new int[numComponents];
+
+ // Bit field handling have been moved to a utility class
+ BitMaskExtent extent = new BitMaskExtent();
+ for (int b=0; b<numComponents; b++)
+ {
+ extent.setMask(masks[b]);
+ shifts[b] = extent.leastSignificantBit;
+ }
+ }
+
+ public PackedColorModel(ColorSpace cspace, int pixelBits,
+ int rmask, int gmask, int bmask,
+ int amask, boolean isAlphaPremultiplied,
+ int transparency,
+ int transferType)
+ {
+ this(cspace, pixelBits, makeColorMaskArray(rmask, gmask, bmask),
+ amask, isAlphaPremultiplied, transparency, transferType);
+ }
+
+ /* TODO: If there is a alpha mask, it is inefficient to create a
+ color mask array that will be discarded when the alpha mask is
+ appended. We should probably create a private constructor that
+ takes a complete array of masks (color+alpha) as an
+ argument. */
+
+ private static int[] makeColorMaskArray(int rmask, int gmask, int bmask)
+ {
+ int[] colorMaskArray = { rmask, gmask, bmask };
+ return colorMaskArray;
+ }
+
+ public final int getMask(int index)
+ {
+ return masks[index];
+ }
+
+ public final int[] getMasks()
+ {
+ return masks;
+ }
+
+ public SampleModel createCompatibleSampleModel(int w, int h)
+ {
+ return new SinglePixelPackedSampleModel(transferType, w, h, masks);
+ }
+
+ public boolean isCompatibleSampleModel(SampleModel sm)
+ {
+ if (!super.isCompatibleSampleModel(sm)) return false;
+ if (!(sm instanceof SinglePixelPackedSampleModel)) return false;
+
+ SinglePixelPackedSampleModel sppsm =
+ (SinglePixelPackedSampleModel) sm;
+ return java.util.Arrays.equals(sppsm.getBitMasks(), masks);
+ }
+
+ public WritableRaster getAlphaRaster(WritableRaster raster) {
+ if (!hasAlpha()) return null;
+
+ SampleModel sm = raster.getSampleModel();
+ int[] alphaBand = { sm.getNumBands() - 1 };
+ SampleModel alphaModel = sm.createSubsetSampleModel(alphaBand);
+ DataBuffer buffer = raster.getDataBuffer();
+ Point origin = new Point(0, 0);
+ return Raster.createWritableRaster(alphaModel, buffer, origin);
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (!super.equals(obj)) return false;
+ if (!(obj instanceof PackedColorModel)) return false;
+
+ PackedColorModel other = (PackedColorModel) obj;
+
+ return java.util.Arrays.equals(masks, other.masks);
+ }
+}
diff --git a/libjava/classpath/java/awt/image/PixelGrabber.java b/libjava/classpath/java/awt/image/PixelGrabber.java
new file mode 100644
index 000000000..b83fab571
--- /dev/null
+++ b/libjava/classpath/java/awt/image/PixelGrabber.java
@@ -0,0 +1,631 @@
+/* PixelGrabber.java -- retrieve a subset of an image's data
+ Copyright (C) 1999, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.Image;
+import java.util.Hashtable;
+
+/**
+ * PixelGrabber is an ImageConsumer that extracts a rectangular region
+ * of pixels from an Image.
+ */
+public class PixelGrabber implements ImageConsumer
+{
+ int x, y, offset;
+ int width = -1;
+ int height = -1;
+ int scansize = -1;
+ boolean forceRGB = true;
+
+ ColorModel model = ColorModel.getRGBdefault();
+ int hints;
+ Hashtable<?,?> props;
+
+ int int_pixel_buffer[];
+ boolean ints_delivered = false;
+ byte byte_pixel_buffer[];
+ boolean bytes_delivered = false;
+
+ ImageProducer ip;
+ int observerStatus;
+ int consumerStatus;
+
+ private Thread grabberThread;
+ boolean grabbing = false;
+
+ /**
+ * Construct a PixelGrabber that will retrieve RGB data from a given
+ * Image.
+ *
+ * The RGB data will be retrieved from a rectangular region
+ * <code>(x, y, w, h)</code> within the image. The data will be
+ * stored in the provided <code>pix</code> array, which must have
+ * been initialized to a size of at least <code>w * h</code>. The
+ * data for a pixel (m, n) in the grab rectangle will be stored at
+ * <code>pix[(n - y) * scansize + (m - x) + off]</code>.
+ *
+ * @param img the Image from which to grab pixels
+ * @param x the x coordinate, relative to <code>img</code>'s
+ * top-left corner, of the grab rectangle's top-left pixel
+ * @param y the y coordinate, relative to <code>img</code>'s
+ * top-left corner, of the grab rectangle's top-left pixel
+ * @param w the width of the grab rectangle, in pixels
+ * @param h the height of the grab rectangle, in pixels
+ * @param pix the array in which to store grabbed RGB pixel data
+ * @param off the offset into the <code>pix</code> array at which to
+ * start storing RGB data
+ * @param scansize a set of <code>scansize</code> consecutive
+ * elements in the <code>pix</code> array represents one row of
+ * pixels in the grab rectangle
+ */
+ public PixelGrabber(Image img, int x, int y, int w, int h,
+ int pix[], int off, int scansize)
+ {
+ this (img.getSource(), x, y, w, h, pix, off, scansize);
+ }
+
+ /**
+ * Construct a PixelGrabber that will retrieve RGB data from a given
+ * ImageProducer.
+ *
+ * The RGB data will be retrieved from a rectangular region
+ * <code>(x, y, w, h)</code> within the image produced by
+ * <code>ip</code>. The data will be stored in the provided
+ * <code>pix</code> array, which must have been initialized to a
+ * size of at least <code>w * h</code>. The data for a pixel (m, n)
+ * in the grab rectangle will be stored at
+ * <code>pix[(n - y) * scansize + (m - x) + off]</code>.
+ *
+ * @param ip the ImageProducer from which to grab pixels. This can
+ * be null.
+ * @param x the x coordinate of the grab rectangle's top-left pixel,
+ * specified relative to the top-left corner of the image produced
+ * by <code>ip</code>
+ * @param y the y coordinate of the grab rectangle's top-left pixel,
+ * specified relative to the top-left corner of the image produced
+ * by <code>ip</code>
+ * @param w the width of the grab rectangle, in pixels
+ * @param h the height of the grab rectangle, in pixels
+ * @param pix the array in which to store grabbed RGB pixel data
+ * @param off the offset into the <code>pix</code> array at which to
+ * start storing RGB data
+ * @param scansize a set of <code>scansize</code> consecutive
+ * elements in the <code>pix</code> array represents one row of
+ * pixels in the grab rectangle
+ */
+ public PixelGrabber(ImageProducer ip, int x, int y, int w, int h,
+ int pix[], int off, int scansize)
+ {
+ this.ip = ip;
+ this.x = x;
+ this.y = y;
+ this.width = w;
+ this.height = h;
+ this.offset = off;
+ this.scansize = scansize;
+
+ int_pixel_buffer = pix;
+ // Initialize the byte array in case ip sends us byte-formatted
+ // pixel data.
+ byte_pixel_buffer = new byte[pix.length * 4];
+ }
+
+ /**
+ * Construct a PixelGrabber that will retrieve data from a given
+ * Image.
+ *
+ * The RGB data will be retrieved from a rectangular region
+ * <code>(x, y, w, h)</code> within the image. The data will be
+ * stored in an internal array which can be accessed by calling
+ * <code>getPixels</code>. The data for a pixel (m, n) in the grab
+ * rectangle will be stored in the returned array at index
+ * <code>(n - y) * scansize + (m - x) + off</code>.
+ * If forceRGB is false, then the returned data will be not be
+ * converted to RGB from its format in <code>img</code>.
+ *
+ * If <code>w</code> is negative, the width of the grab region will
+ * be from x to the right edge of the image. Likewise, if
+ * <code>h</code> is negative, the height of the grab region will be
+ * from y to the bottom edge of the image.
+ *
+ * @param img the Image from which to grab pixels
+ * @param x the x coordinate, relative to <code>img</code>'s
+ * top-left corner, of the grab rectangle's top-left pixel
+ * @param y the y coordinate, relative to <code>img</code>'s
+ * top-left corner, of the grab rectangle's top-left pixel
+ * @param w the width of the grab rectangle, in pixels
+ * @param h the height of the grab rectangle, in pixels
+ * @param forceRGB true to force conversion of the rectangular
+ * region's pixel data to RGB
+ */
+ public PixelGrabber(Image img,
+ int x, int y,
+ int w, int h,
+ boolean forceRGB)
+ {
+ this.ip = img.getSource();
+
+ if (this.ip == null)
+ throw new NullPointerException("The ImageProducer must not be null.");
+
+ this.x = x;
+ this.y = y;
+ width = w;
+ height = h;
+ // If width or height is negative, postpone pixel buffer
+ // initialization until setDimensions is called back by ip.
+ if (width >= 0 && height >= 0)
+ {
+ int_pixel_buffer = new int[width * height];
+ byte_pixel_buffer = new byte[width * height];
+ }
+ this.forceRGB = forceRGB;
+ }
+
+ /**
+ * Start grabbing pixels.
+ *
+ * Spawns an image production thread that calls back to this
+ * PixelGrabber's ImageConsumer methods.
+ */
+ public synchronized void startGrabbing()
+ {
+ // Make sure we're not already grabbing.
+ if (grabbing == false)
+ {
+ grabbing = true;
+ grabberThread = new Thread ()
+ {
+ public void run ()
+ {
+ try
+ {
+ ip.startProduction (PixelGrabber.this);
+ }
+ catch (Exception ex)
+ {
+ imageComplete(ImageConsumer.IMAGEABORTED);
+ }
+ }
+ };
+ grabberThread.start ();
+ }
+ }
+
+ /**
+ * Abort pixel grabbing.
+ */
+ public synchronized void abortGrabbing()
+ {
+ if (grabbing)
+ {
+ // Interrupt the grabbing thread.
+ Thread moribund = grabberThread;
+ grabberThread = null;
+ moribund.interrupt();
+
+ imageComplete (ImageConsumer.IMAGEABORTED);
+ }
+ }
+
+ /**
+ * Have our Image or ImageProducer start sending us pixels via our
+ * ImageConsumer methods and wait for all pixels in the grab
+ * rectangle to be delivered.
+ *
+ * @return true if successful, false on abort or error
+ *
+ * @throws InterruptedException if interrupted by another thread.
+ */
+ public synchronized boolean grabPixels() throws InterruptedException
+ {
+ return grabPixels(0);
+ }
+
+ /**
+ * grabPixels's behavior depends on the value of <code>ms</code>.
+ *
+ * If ms < 0, return true if all pixels from the source image have
+ * been delivered, false otherwise. Do not wait.
+ *
+ * If ms >= 0 then we request that our Image or ImageProducer start
+ * delivering pixels to us via our ImageConsumer methods.
+ *
+ * If ms > 0, wait at most <code>ms</code> milliseconds for
+ * delivery of all pixels within the grab rectangle.
+ *
+ * If ms == 0, wait until all pixels have been delivered.
+ *
+ * @return true if all pixels from the source image have been
+ * delivered, false otherwise
+ *
+ * @throws InterruptedException if this thread is interrupted while
+ * we are waiting for pixels to be delivered
+ */
+ public synchronized boolean grabPixels(long ms) throws InterruptedException
+ {
+ if (ms < 0)
+ return ((observerStatus & (ImageObserver.FRAMEBITS
+ | ImageObserver.ALLBITS)) != 0);
+
+ // Spawn a new ImageProducer thread to send us the image data via
+ // our ImageConsumer methods.
+ startGrabbing();
+
+ if (ms > 0)
+ {
+ long stop_time = System.currentTimeMillis() + ms;
+ long time_remaining;
+ while (grabbing)
+ {
+ time_remaining = stop_time - System.currentTimeMillis();
+ if (time_remaining <= 0)
+ break;
+ wait (time_remaining);
+ }
+ abortGrabbing ();
+ }
+ else
+ wait ();
+
+ // If consumerStatus is non-zero then the image is done loading or
+ // an error has occurred.
+ if (consumerStatus != 0)
+ return setObserverStatus ();
+
+ return ((observerStatus & (ImageObserver.FRAMEBITS
+ | ImageObserver.ALLBITS)) != 0);
+ }
+
+ // Set observer status flags based on the current consumer status
+ // flags. Return true if the consumer flags indicate that the
+ // image was loaded successfully, or false otherwise.
+ private synchronized boolean setObserverStatus ()
+ {
+ boolean retval = false;
+
+ if ((consumerStatus & IMAGEERROR) != 0)
+ observerStatus |= ImageObserver.ERROR;
+
+ if ((consumerStatus & IMAGEABORTED) != 0)
+ observerStatus |= ImageObserver.ABORT;
+
+ if ((consumerStatus & STATICIMAGEDONE) != 0)
+ {
+ observerStatus |= ImageObserver.ALLBITS;
+ retval = true;
+ }
+
+ if ((consumerStatus & SINGLEFRAMEDONE) != 0)
+ {
+ observerStatus |= ImageObserver.FRAMEBITS;
+ retval = true;
+ }
+
+ return retval;
+ }
+
+ /**
+ * @return the status of the pixel grabbing thread, represented by a
+ * bitwise OR of ImageObserver flags
+ */
+ public synchronized int getStatus()
+ {
+ return observerStatus;
+ }
+
+ /**
+ * @return the width of the grab rectangle in pixels, or a negative
+ * number if the ImageProducer has not yet called our setDimensions
+ * method
+ */
+ public synchronized int getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * @return the height of the grab rectangle in pixels, or a negative
+ * number if the ImageProducer has not yet called our setDimensions
+ * method
+ */
+ public synchronized int getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * @return a byte array of pixel data if ImageProducer delivered
+ * pixel data using the byte[] variant of setPixels, or an int array
+ * otherwise
+ */
+ public synchronized Object getPixels()
+ {
+ if (ints_delivered)
+ return int_pixel_buffer;
+ else if (bytes_delivered)
+ return byte_pixel_buffer;
+ else
+ return null;
+ }
+
+ /**
+ * @return the ColorModel currently being used for the majority of
+ * pixel data conversions
+ */
+ public synchronized ColorModel getColorModel()
+ {
+ return model;
+ }
+
+ /**
+ * Our <code>ImageProducer</code> calls this method to indicate the
+ * size of the image being produced.
+ *
+ * setDimensions is an ImageConsumer method. None of PixelGrabber's
+ * ImageConsumer methods should be called by code that instantiates
+ * a PixelGrabber. They are only made public so they can be called
+ * by the PixelGrabber's ImageProducer.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ */
+ public synchronized void setDimensions(int width, int height)
+ {
+ // Our width wasn't set when we were constructed. Set our width
+ // so that the grab region includes all pixels from x to the right
+ // edge of the source image.
+ if (this.width < 0)
+ this.width = width - x;
+
+ // Our height wasn't set when we were constructed. Set our height
+ // so that the grab region includes all pixels from y to the
+ // bottom edge of the source image.
+ if (this.height < 0)
+ this.height = height - y;
+
+ if (scansize < 0)
+ scansize = this.width;
+
+ if (int_pixel_buffer == null)
+ int_pixel_buffer = new int[this.width * this.height];
+
+ if (byte_pixel_buffer == null)
+ byte_pixel_buffer = new byte[this.width * this.height];
+ }
+
+ /**
+ * Our <code>ImageProducer</code> may call this method to send us a
+ * list of its image's properties.
+ *
+ * setProperties is an ImageConsumer method. None of PixelGrabber's
+ * ImageConsumer methods should be called by code that instantiates
+ * a PixelGrabber. They are only made public so they can be called
+ * by the PixelGrabber's ImageProducer.
+ *
+ * @param props a list of properties associated with the image being
+ * produced
+ */
+ public synchronized void setProperties(Hashtable<?,?> props)
+ {
+ this.props = props;
+ }
+
+ /**
+ * Our ImageProducer will call <code>setColorModel</code> to
+ * indicate the model used by the majority of calls to
+ * <code>setPixels</code>. Each call to <code>setPixels</code>
+ * could however indicate a different <code>ColorModel</code>.
+ *
+ * setColorModel is an ImageConsumer method. None of PixelGrabber's
+ * ImageConsumer methods should be called by code that instantiates
+ * a PixelGrabber. They are only made public so they can be called
+ * by the PixelGrabber's ImageProducer.
+ *
+ * @param model the color model to be used most often by setPixels
+ *
+ * @see ColorModel
+ */
+ public synchronized void setColorModel(ColorModel model)
+ {
+ this.model = model;
+ }
+
+ /**
+ * Our <code>ImageProducer</code> may call this method with a
+ * bit mask of hints from any of <code>RANDOMPIXELORDER</code>,
+ * <code>TOPDOWNLEFTRIGHT</code>, <code>COMPLETESCANLINES</code>,
+ * <code>SINGLEPASS</code>, <code>SINGLEFRAME</code>.
+ *
+ * setHints is an ImageConsumer method. None of PixelGrabber's
+ * ImageConsumer methods should be called by code that instantiates
+ * a PixelGrabber. They are only made public so they can be called
+ * by the PixelGrabber's ImageProducer.
+ *
+ * @param flags a bit mask of hints
+ */
+ public synchronized void setHints(int flags)
+ {
+ hints = flags;
+ }
+
+ /**
+ * Our ImageProducer calls setPixels to deliver a subset of its
+ * pixels.
+ *
+ * Each element of the pixels array represents one pixel. The
+ * pixel data is formatted according to the color model model.
+ * The x and y parameters are the coordinates of the rectangular
+ * region of pixels being delivered to this ImageConsumer,
+ * specified relative to the top left corner of the image being
+ * produced. Likewise, w and h are the pixel region's dimensions.
+ *
+ * @param x x coordinate of pixel block
+ * @param y y coordinate of pixel block
+ * @param w width of pixel block
+ * @param h height of pixel block
+ * @param model color model used to interpret pixel data
+ * @param pixels pixel block data
+ * @param offset offset into pixels array
+ * @param scansize width of one row in the pixel block
+ */
+ public synchronized void setPixels(int x, int y, int w, int h,
+ ColorModel model, byte[] pixels,
+ int offset, int scansize)
+ {
+ ColorModel currentModel;
+ if (model != null)
+ currentModel = model;
+ else
+ currentModel = this.model;
+
+ for(int yp = y; yp < (y + h); yp++)
+ {
+ for(int xp = x; xp < (x + w); xp++)
+ {
+ // Check if the coordinates (xp, yp) are within the
+ // pixel block that we are grabbing.
+ if(xp >= this.x
+ && yp >= this.y
+ && xp < (this.x + this.width)
+ && yp < (this.y + this.height))
+ {
+ int i = (yp - this.y) * this.scansize + (xp - this.x) + this.offset;
+ int p = (yp - y) * scansize + (xp - x) + offset;
+ if (forceRGB)
+ {
+ ints_delivered = true;
+
+ int_pixel_buffer[i] = currentModel.getRGB (pixels[p] & 0xFF);
+ }
+ else
+ {
+ bytes_delivered = true;
+
+ byte_pixel_buffer[i] = pixels[p];
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Our ImageProducer calls setPixels to deliver a subset of its
+ * pixels.
+ *
+ * Each element of the pixels array represents one pixel. The
+ * pixel data is formatted according to the color model model.
+ * The x and y parameters are the coordinates of the rectangular
+ * region of pixels being delivered to this ImageConsumer,
+ * specified relative to the top left corner of the image being
+ * produced. Likewise, w and h are the pixel region's dimensions.
+ *
+ * @param x x coordinate of pixel block
+ * @param y y coordinate of pixel block
+ * @param w width of pixel block
+ * @param h height of pixel block
+ * @param model color model used to interpret pixel data
+ * @param pixels pixel block data
+ * @param offset offset into pixels array
+ * @param scansize width of one row in the pixel block
+ */
+ public synchronized void setPixels(int x, int y, int w, int h,
+ ColorModel model, int[] pixels,
+ int offset, int scansize)
+ {
+ ColorModel currentModel;
+ if (model != null)
+ currentModel = model;
+ else
+ currentModel = this.model;
+
+ ints_delivered = true;
+
+ for(int yp = y; yp < (y + h); yp++)
+ {
+ for(int xp = x; xp < (x + w); xp++)
+ {
+ // Check if the coordinates (xp, yp) are within the
+ // pixel block that we are grabbing.
+ if(xp >= this.x
+ && yp >= this.y
+ && xp < (this.x + this.width)
+ && yp < (this.y + this.height))
+ {
+ int i = (yp - this.y) * this.scansize + (xp - this.x) + this.offset;
+ int p = (yp - y) * scansize + (xp - x) + offset;
+ if (forceRGB)
+ int_pixel_buffer[i] = currentModel.getRGB (pixels[p]);
+ else
+ int_pixel_buffer[i] = pixels[p];
+ }
+ }
+ }
+ }
+
+ /**
+ * Our <code>ImageProducer</code> calls this method to inform us
+ * that a single frame or the entire image is complete. The method
+ * is also used to inform us of an error in loading or producing the
+ * image.
+ *
+ * @param status the status of image production, represented by a
+ * bitwise OR of ImageConsumer flags
+ */
+ public synchronized void imageComplete(int status)
+ {
+ consumerStatus = status;
+ setObserverStatus ();
+ grabbing = false;
+ if (ip != null)
+ ip.removeConsumer (this);
+
+ notifyAll ();
+ }
+
+ /**
+ * @return the return value of getStatus
+ *
+ * @specnote The newer getStatus should be used in place of status.
+ */
+ public synchronized int status()
+ {
+ return getStatus();
+ }
+}
diff --git a/libjava/classpath/java/awt/image/PixelInterleavedSampleModel.java b/libjava/classpath/java/awt/image/PixelInterleavedSampleModel.java
new file mode 100644
index 000000000..13134b413
--- /dev/null
+++ b/libjava/classpath/java/awt/image/PixelInterleavedSampleModel.java
@@ -0,0 +1,123 @@
+/* PixelInterleavedSampleModel.java
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+
+/**
+ * A <code>SampleModel</code> that uses exactly one element of the
+ * raster&#x2019;s {@link DataBuffer} per pixel, holds all bands in a
+ * single bank, and stores band data in pixel-interleaved manner.
+ *
+ * @since 1.2
+ *
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ */
+public class PixelInterleavedSampleModel
+ extends ComponentSampleModel
+{
+ public PixelInterleavedSampleModel(int dataType, int width, int height,
+ int pixelStride, int scanlineStride,
+ int[] bandOffsets)
+ {
+ super(dataType, width, height, pixelStride, scanlineStride,
+ bandOffsets);
+ }
+
+
+ /**
+ * Creates a new <code>SampleModel</code> that is like this one, but
+ * uses the specified width and height.
+ *
+ * @param width the number of pixels in the horizontal direction.
+ *
+ * @param height the number of pixels in the vertical direction.
+ */
+ public SampleModel createCompatibleSampleModel(int width, int height)
+ {
+ // Find minimum band offset.
+ int minBandoff = bandOffsets[0];
+ int numBands = bandOffsets.length;
+ for (int i = 1; i < numBands; i++)
+ {
+ if (bandOffsets[i] < minBandoff)
+ {
+ minBandoff = bandOffsets[i];
+ }
+ }
+ // Adjust band offsets so that minimum offset is at 0.
+ int[] bandOff;
+ if (minBandoff > 0)
+ {
+ bandOff = new int[numBands];
+ for (int i = 0; i < numBands; i++)
+ {
+ bandOff[i] = bandOffsets[i] - minBandoff;
+ }
+ }
+ else
+ {
+ bandOff = bandOffsets;
+ }
+ // Adjust scanline stride for new width.
+ return new PixelInterleavedSampleModel(dataType, width, height,
+ pixelStride, pixelStride * width,
+ bandOff);
+ }
+
+
+ /**
+ * Creates a new <code>SampleModel</code> that is like this one, but
+ * uses only a subset of its bands.
+ *
+ * @param bands an array whose elements indicate which bands shall
+ * be part of the subset. For example, <code>[0, 2, 3]</code> would
+ * create a SampleModel containing bands #0, #2 and #3.
+ */
+ public SampleModel createSubsetSampleModel(int[] bands)
+ {
+ int[] subOffsets;
+
+ subOffsets = new int[bands.length];
+ for (int i = 0; i < bands.length; i++)
+ subOffsets[i] = bandOffsets[bands[i]];
+
+ return new PixelInterleavedSampleModel(dataType, width, height,
+ pixelStride, scanlineStride,
+ subOffsets);
+ }
+}
diff --git a/libjava/classpath/java/awt/image/RGBImageFilter.java b/libjava/classpath/java/awt/image/RGBImageFilter.java
new file mode 100644
index 000000000..1354c3a80
--- /dev/null
+++ b/libjava/classpath/java/awt/image/RGBImageFilter.java
@@ -0,0 +1,265 @@
+/* RGBImageFilter.java -- Java class for filtering Pixels by RGB values
+ Copyright (C) 1999, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+/**
+ * A filter designed to filter images in the default RGBColorModel regardless of
+ * the ImageProducer's ColorModel.
+ *
+ * @author Mark Benvenuto (mcb54@columbia.edu)
+ */
+public abstract class RGBImageFilter extends ImageFilter
+{
+ protected ColorModel origmodel;
+
+ protected ColorModel newmodel;
+
+ /**
+ * Specifies whether to apply the filter to the index entries of the
+ * IndexColorModel. Subclasses should set this to true if the filter
+ * does not depend on the pixel's coordinate.
+ */
+ protected boolean canFilterIndexColorModel = false;
+
+ /**
+ * Construct new RGBImageFilter.
+ */
+ public RGBImageFilter()
+ {
+ }
+
+ /**
+ * Sets the ColorModel used to filter with. If the specified ColorModel is
+ * IndexColorModel and canFilterIndexColorModel is true, we subsitute the
+ * ColorModel for a filtered one here and in setPixels whenever the original
+ * one appears. Otherwise overrides the default ColorModel of ImageProducer
+ * and specifies the default RGBColorModel
+ *
+ * @param model the color model to be used most often by setPixels
+ *
+ * @see ColorModel
+ */
+ public void setColorModel(ColorModel model)
+ {
+ if ((model instanceof IndexColorModel) && canFilterIndexColorModel)
+ {
+ ColorModel newCM = filterIndexColorModel((IndexColorModel) model);
+ substituteColorModel(model, newCM);
+ consumer.setColorModel(newmodel);
+ }
+ else
+ {
+ consumer.setColorModel(ColorModel.getRGBdefault());
+ }
+ }
+
+ /**
+ * Registers a new ColorModel to subsitute for the old ColorModel when
+ * setPixels encounters the a pixel with the old ColorModel. The pixel
+ * remains unchanged except for a new ColorModel.
+ *
+ * @param oldcm the old ColorModel
+ * @param newcm the new ColorModel
+ */
+ public void substituteColorModel(ColorModel oldcm, ColorModel newcm)
+ {
+ origmodel = oldcm;
+ newmodel = newcm;
+ }
+
+ /**
+ * Filters an IndexColorModel through the filterRGB function. Uses
+ * coordinates of -1 to indicate its filtering an index and not a pixel.
+ *
+ * @param icm an IndexColorModel to filter
+ */
+ public IndexColorModel filterIndexColorModel(IndexColorModel icm)
+ {
+ int len = icm.getMapSize();
+ byte[] reds = new byte[len];
+ byte[] greens = new byte[len];
+ byte[] blues = new byte[len];
+ byte[] alphas = new byte[len];
+
+ icm.getAlphas( alphas );
+ icm.getReds( reds );
+ icm.getGreens( greens );
+ icm.getBlues( blues );
+
+ int transparent = icm.getTransparentPixel();
+ boolean needAlpha = false;
+ for( int i = 0; i < len; i++ )
+ {
+ int rgb = filterRGB(-1, -1, icm.getRGB(i));
+ alphas[i] = (byte) (rgb >> 24);
+ if (alphas[i] != ((byte) 0xff) && i != transparent)
+ needAlpha = true;
+ reds[i] = (byte) (rgb >> 16);
+ greens[i] = (byte) (rgb >> 8);
+ blues[i] = (byte) (rgb);
+ }
+ IndexColorModel newIcm;
+ if (needAlpha)
+ newIcm = new IndexColorModel(icm.getPixelSize(), len, reds, greens,
+ blues, alphas);
+ else
+ newIcm = new IndexColorModel(icm.getPixelSize(), len, reds, greens,
+ blues, transparent);
+ return newIcm;
+ }
+
+ /**
+ * This functions filters a set of RGB pixels through filterRGB.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the
+ * <code>pixels</code> array
+ * @param scansize the width to use in extracting pixels from the
+ * <code>pixels</code> array
+ */
+ public void filterRGBPixels(int x, int y, int w, int h, int[] pixels,
+ int offset, int scansize)
+ {
+ int index = offset;
+ for (int yp = 0; yp < h; yp++)
+ {
+ for (int xp = 0; xp < w; xp++)
+ {
+ pixels[index] = filterRGB(xp + x, yp + y, pixels[index]);
+ index++;
+ }
+ index += scansize - w;
+ }
+ consumer.setPixels(x, y, w, h, ColorModel.getRGBdefault(), pixels, offset,
+ scansize);
+ }
+
+ /**
+ * If the ColorModel is the same ColorModel which as already converted
+ * then it converts it the converted ColorModel. Otherwise it passes the
+ * array of pixels through filterRGBpixels.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param model the <code>ColorModel</code> used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the <code>pixels</code>
+ * array
+ * @param scansize the width to use in extracting pixels from the
+ * <code>pixels</code> array
+ */
+ public void setPixels(int x, int y, int w, int h, ColorModel model,
+ byte[] pixels, int offset, int scansize)
+ {
+ if (model == origmodel)
+ {
+ consumer.setPixels(x, y, w, h, newmodel, pixels, offset, scansize);
+ }
+ else
+ {
+ int[] filtered = new int[w];
+ int index = offset;
+ for (int yp = 0; yp < h; yp++)
+ {
+ for (int xp = 0; xp < w; xp++)
+ {
+ filtered[xp] = model.getRGB((pixels[index] & 0xff));
+ index++;
+ }
+ index += scansize - w;
+ filterRGBPixels(x, y + yp, w, 1, filtered, 0, w);
+ }
+ }
+ }
+
+ /**
+ * This function delivers a rectangle of pixels where any
+ * pixel(m,n) is stored in the array as an <code>int</code> at
+ * index (n * scansize + m + offset).
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param model the <code>ColorModel</code> used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the <code>pixels</code>
+ * array
+ * @param scansize the width to use in extracting pixels from the
+ * <code>pixels</code> array
+ */
+ public void setPixels(int x, int y, int w, int h, ColorModel model,
+ int[] pixels, int offset, int scansize)
+ {
+ if (model == origmodel)
+ {
+ consumer.setPixels(x, y, w, h, newmodel, pixels, offset, scansize);
+ }
+ else
+ {
+ int[] filtered = new int[w];
+ int index = offset;
+ for (int yp = 0; yp < h; yp++)
+ {
+ for (int xp = 0; xp < w; xp++)
+ {
+ filtered[xp] = model.getRGB((pixels[index]));
+ index++;
+ }
+ index += scansize - w;
+ filterRGBPixels(x, y + yp, w, 1, filtered, 0, w);
+ }
+ }
+ }
+
+ /**
+ * Filters a single pixel from the default ColorModel.
+ *
+ * @param x x-coordinate
+ * @param y y-coordinate
+ * @param rgb color
+ */
+ public abstract int filterRGB(int x, int y, int rgb);
+}
diff --git a/libjava/classpath/java/awt/image/Raster.java b/libjava/classpath/java/awt/image/Raster.java
new file mode 100644
index 000000000..6d99c3683
--- /dev/null
+++ b/libjava/classpath/java/awt/image/Raster.java
@@ -0,0 +1,973 @@
+/* Copyright (C) 2000, 2002, 2003, 2006, Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+
+/**
+ * A rectangular collection of pixels composed from a {@link DataBuffer} which
+ * stores the pixel values, and a {@link SampleModel} which is used to retrieve
+ * the pixel values.
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public class Raster
+{
+ /** The sample model used to access the pixel values. */
+ protected SampleModel sampleModel;
+
+ /** The data buffer used to store the pixel values. */
+ protected DataBuffer dataBuffer;
+
+ /** The x-coordinate of the top left corner of the raster. */
+ protected int minX;
+
+ /** The y-coordinate of the top left corner of the raster. */
+ protected int minY;
+
+ /** The width of the raster. */
+ protected int width;
+
+ /** The height of the raster. */
+ protected int height;
+
+ protected int sampleModelTranslateX;
+
+ protected int sampleModelTranslateY;
+
+ /** The number of bands. */
+ protected int numBands;
+
+ protected int numDataElements;
+
+ /** The raster's parent. */
+ protected Raster parent;
+
+ /**
+ * Creates a new raster.
+ *
+ * @param sampleModel the sample model.
+ * @param origin the origin.
+ */
+ protected Raster(SampleModel sampleModel, Point origin)
+ {
+ this(sampleModel, sampleModel.createDataBuffer(), origin);
+ }
+
+ /**
+ * Creates a new raster.
+ *
+ * @param sampleModel the sample model.
+ * @param dataBuffer the data buffer.
+ * @param origin the origin.
+ */
+ protected Raster(SampleModel sampleModel, DataBuffer dataBuffer,
+ Point origin)
+ {
+ this(sampleModel, dataBuffer, new Rectangle(origin.x, origin.y,
+ sampleModel.getWidth(), sampleModel.getHeight()), origin, null);
+ }
+
+ /**
+ * Creates a new raster.
+ *
+ * @param sampleModel the sample model.
+ * @param dataBuffer the data buffer.
+ * @param aRegion the raster's bounds.
+ * @param sampleModelTranslate the translation (<code>null</code> permitted).
+ * @param parent the raster's parent.
+ */
+ protected Raster(SampleModel sampleModel, DataBuffer dataBuffer,
+ Rectangle aRegion, Point sampleModelTranslate, Raster parent)
+ {
+ this.sampleModel = sampleModel;
+ this.dataBuffer = dataBuffer;
+ this.minX = aRegion.x;
+ this.minY = aRegion.y;
+ this.width = aRegion.width;
+ this.height = aRegion.height;
+
+ // If sampleModelTranslate is null, use (0,0). Methods such as
+ // Raster.createRaster are specified to allow for a null argument.
+ if (sampleModelTranslate != null)
+ {
+ this.sampleModelTranslateX = sampleModelTranslate.x;
+ this.sampleModelTranslateY = sampleModelTranslate.y;
+ }
+
+ this.numBands = sampleModel.getNumBands();
+ this.numDataElements = sampleModel.getNumDataElements();
+ this.parent = parent;
+ }
+
+ /**
+ * Creates an interleaved raster using the specified data type.
+ *
+ * @param dataType the data type.
+ * @param w the width.
+ * @param h the height.
+ * @param bands the number of bands.
+ * @param location
+ *
+ * @return The new raster.
+ */
+ public static WritableRaster createInterleavedRaster(int dataType,
+ int w, int h, int bands, Point location)
+ {
+ int[] bandOffsets = new int[bands];
+ // TODO: Maybe not generate this every time.
+ for (int b = 0; b < bands; b++)
+ bandOffsets[b] = b;
+
+ int scanlineStride = bands * w;
+ return createInterleavedRaster(dataType, w, h, scanlineStride, bands,
+ bandOffsets, location);
+ }
+
+ /**
+ * Creates an interleaved raster.
+ *
+ * @param dataType the data type.
+ * @param w the width.
+ * @param h the height.
+ * @param scanlineStride the number of data elements from a sample on one
+ * row to the corresponding sample on the next row.
+ * @param pixelStride the number of elements from a sample in one pixel to
+ * the corresponding sample in the next pixel.
+ * @param bandOffsets the band offsets.
+ * @param location
+ *
+ * @return The new raster.
+ */
+ public static WritableRaster createInterleavedRaster(int dataType,
+ int w, int h, int scanlineStride, int pixelStride, int[] bandOffsets,
+ Point location)
+ {
+ SampleModel sm = new ComponentSampleModel(dataType, w, h, pixelStride,
+ scanlineStride, bandOffsets);
+ return createWritableRaster(sm, location);
+ }
+
+ /**
+ * Creates a new banded raster.
+ *
+ * @param dataType the data type.
+ * @param w the width.
+ * @param h the height.
+ * @param bands the number of bands.
+ * @param location
+ *
+ * @return The new raster.
+ */
+ public static WritableRaster createBandedRaster(int dataType, int w, int h,
+ int bands, Point location)
+ {
+ SampleModel sm = new BandedSampleModel(dataType, w, h, bands);
+ return createWritableRaster(sm, location);
+ }
+
+ /**
+ * Creates a new banded raster.
+ *
+ * @param dataType the data type.
+ * @param w the width.
+ * @param h the height.
+ * @param scanlineStride the number of data elements from a sample on one
+ * row to the corresponding sample on the next row.
+ * @param bankIndices the index for each bank.
+ * @param bandOffsets the offset for each band.
+ * @param location
+ *
+ * @return The new raster.
+ */
+ public static WritableRaster createBandedRaster(int dataType, int w, int h,
+ int scanlineStride, int[] bankIndices, int[] bandOffsets, Point location)
+ {
+ SampleModel sm = new BandedSampleModel(dataType, w, h, scanlineStride,
+ bankIndices, bandOffsets);
+ return createWritableRaster(sm, location);
+ }
+
+ /**
+ * Creates a new packed raster.
+ *
+ * @param dataType the data type.
+ * @param w the width.
+ * @param h the height.
+ * @param bandMasks the bit mask for each band.
+ * @param location
+ *
+ * @return The new raster.
+ */
+ public static WritableRaster createPackedRaster(int dataType, int w, int h,
+ int[] bandMasks, Point location)
+ {
+ SampleModel sm = new SinglePixelPackedSampleModel(dataType, w, h,
+ bandMasks);
+ return createWritableRaster(sm, location);
+ }
+
+ /**
+ * Creates a new raster.
+ *
+ * @param dataType the data type.
+ * @param w the width.
+ * @param h the height.
+ * @param bands the number of bands.
+ * @param bitsPerBand the number of bits per band.
+ * @param location
+ *
+ * @return The new raster.
+ */
+ public static WritableRaster createPackedRaster(int dataType,
+ int w, int h, int bands, int bitsPerBand, Point location)
+ {
+ if (bands <= 0 || (bands * bitsPerBand > getTypeBits(dataType)))
+ throw new IllegalArgumentException();
+
+ SampleModel sm;
+
+ if (bands == 1)
+ sm = new MultiPixelPackedSampleModel(dataType, w, h, bitsPerBand);
+ else
+ {
+ int[] bandMasks = new int[bands];
+ int mask = 0x1;
+ for (int bits = bitsPerBand; --bits != 0;)
+ mask = (mask << 1) | 0x1;
+ for (int i = 0; i < bands; i++)
+ {
+ bandMasks[i] = mask;
+ mask <<= bitsPerBand;
+ }
+
+ sm = new SinglePixelPackedSampleModel(dataType, w, h, bandMasks);
+ }
+ return createWritableRaster(sm, location);
+ }
+
+ /**
+ * Creates a new interleaved raster.
+ *
+ * @param dataBuffer the data buffer.
+ * @param w the width.
+ * @param h the height.
+ * @param scanlineStride the number of data elements from a sample on one
+ * row to the corresponding sample on the next row.
+ * @param pixelStride the number of elements from a sample in one pixel to
+ * the corresponding sample in the next pixel.
+ * @param bandOffsets the offset for each band.
+ * @param location
+ *
+ * @return The new raster.
+ */
+ public static WritableRaster createInterleavedRaster(DataBuffer dataBuffer,
+ int w, int h, int scanlineStride, int pixelStride, int[] bandOffsets,
+ Point location)
+ {
+ SampleModel sm = new ComponentSampleModel(dataBuffer.getDataType(),
+ w, h, pixelStride, scanlineStride, bandOffsets);
+ return createWritableRaster(sm, dataBuffer, location);
+ }
+
+ /**
+ * Creates a new banded raster.
+ *
+ * @param dataBuffer the data buffer.
+ * @param w the width.
+ * @param h the height.
+ * @param scanlineStride the number of data elements from a sample on one
+ * row to the corresponding sample on the next row.
+ * @param bankIndices the index for each bank.
+ * @param bandOffsets the band offsets.
+ * @param location
+ *
+ * @return The new raster.
+ */
+ public static WritableRaster createBandedRaster(DataBuffer dataBuffer,
+ int w, int h, int scanlineStride, int[] bankIndices, int[] bandOffsets,
+ Point location)
+ {
+ SampleModel sm = new BandedSampleModel(dataBuffer.getDataType(),
+ w, h, scanlineStride, bankIndices, bandOffsets);
+ return createWritableRaster(sm, dataBuffer, location);
+ }
+
+ /**
+ * Creates a new packed raster.
+ *
+ * @param dataBuffer the data buffer.
+ * @param w the width.
+ * @param h the height.
+ * @param scanlineStride the number of data elements from a sample on one
+ * row to the corresponding sample on the next row.
+ * @param bandMasks the bit mask for each band.
+ * @param location
+ *
+ * @return The new raster.
+ */
+ public static WritableRaster createPackedRaster(DataBuffer dataBuffer,
+ int w, int h, int scanlineStride, int[] bandMasks, Point location)
+ {
+ SampleModel sm = new SinglePixelPackedSampleModel(dataBuffer.getDataType(),
+ w, h, scanlineStride, bandMasks);
+ return createWritableRaster(sm, dataBuffer, location);
+ }
+
+ /**
+ * Creates a new packed raster.
+ *
+ * @param dataBuffer the data buffer.
+ * @param w the width.
+ * @param h the height.
+ * @param bitsPerPixel the number of bits per pixel.
+ * @param location
+ *
+ * @return The new raster.
+ */
+ public static WritableRaster createPackedRaster(DataBuffer dataBuffer,
+ int w, int h, int bitsPerPixel, Point location)
+ {
+ SampleModel sm = new MultiPixelPackedSampleModel(dataBuffer.getDataType(),
+ w, h, bitsPerPixel);
+ return createWritableRaster(sm, dataBuffer, location);
+ }
+
+ /**
+ * Creates a new raster.
+ *
+ * @param sm the sample model.
+ * @param db the data buffer.
+ * @param location
+ *
+ * @return The new raster.
+ */
+ public static Raster createRaster(SampleModel sm, DataBuffer db,
+ Point location)
+ {
+ return new Raster(sm, db, location);
+ }
+
+ /**
+ * Creates a new writable raster.
+ *
+ * @param sm the sample model.
+ * @param location
+ *
+ * @return The new writable raster.
+ */
+ public static WritableRaster createWritableRaster(SampleModel sm,
+ Point location)
+ {
+ return new WritableRaster(sm, location);
+ }
+
+ /**
+ * Creates a new writable raster.
+ *
+ * @param sm the sample model.
+ * @param db the data buffer.
+ * @param location
+ *
+ * @return The new writable raster.
+ */
+ public static WritableRaster createWritableRaster(SampleModel sm,
+ DataBuffer db, Point location)
+ {
+ return new WritableRaster(sm, db, location);
+ }
+
+ /**
+ * Returns the raster's parent.
+ *
+ * @return The raster's parent.
+ */
+ public Raster getParent()
+ {
+ return parent;
+ }
+
+ /**
+ * Returns the x-translation.
+ *
+ * @return The x-translation.
+ */
+ public final int getSampleModelTranslateX()
+ {
+ return sampleModelTranslateX;
+ }
+
+ /**
+ * Returns the y-translation.
+ *
+ * @return The y-translation.
+ */
+ public final int getSampleModelTranslateY()
+ {
+ return sampleModelTranslateY;
+ }
+
+ /**
+ * Creates a new writable raster that is compatible with this raster.
+ *
+ * @return A new writable raster.
+ */
+ public WritableRaster createCompatibleWritableRaster()
+ {
+ return new WritableRaster(getSampleModel(), new Point(minX, minY));
+ }
+
+ /**
+ * Creates a new writable raster that is compatible with this raster.
+ *
+ * @param w the width.
+ * @param h the height.
+ *
+ * @return A new writable raster.
+ */
+ public WritableRaster createCompatibleWritableRaster(int w, int h)
+ {
+ return createCompatibleWritableRaster(minX, minY, w, h);
+ }
+
+ /**
+ * Creates a new writable raster that is compatible with this raster, with
+ * the specified bounds.
+ *
+ * @param rect the raster bounds.
+ *
+ * @return A new writable raster.
+ */
+ public WritableRaster createCompatibleWritableRaster(Rectangle rect)
+ {
+ return createCompatibleWritableRaster(rect.x, rect.y,
+ rect.width, rect.height);
+ }
+
+ /**
+ * Creates a new writable raster that is compatible with this raster, with
+ * the specified bounds.
+ *
+ * @param x the x-coordinate of the top-left corner of the raster.
+ * @param y the y-coordinate of the top-left corner of the raster.
+ * @param w the raster width.
+ * @param h the raster height.
+ *
+ * @return A new writable raster.
+ */
+ public WritableRaster createCompatibleWritableRaster(int x, int y,
+ int w, int h)
+ {
+ SampleModel sm = getSampleModel().createCompatibleSampleModel(w, h);
+ return new WritableRaster(sm, sm.createDataBuffer(), new Point(x, y));
+ }
+
+ public Raster createTranslatedChild(int childMinX, int childMinY) {
+ int tcx = sampleModelTranslateX - minX + childMinX;
+ int tcy = sampleModelTranslateY - minY + childMinY;
+
+ return new Raster(sampleModel, dataBuffer,
+ new Rectangle(childMinX, childMinY, width, height),
+ new Point(tcx, tcy), this);
+ }
+
+ public Raster createChild(int parentX, int parentY, int width,
+ int height, int childMinX, int childMinY,
+ int[] bandList)
+ {
+ if (parentX < minX || parentX + width > minX + this.width
+ || parentY < minY || parentY + height > minY + this.height)
+ throw new RasterFormatException("Child raster extends beyond parent");
+
+ SampleModel sm = (bandList == null) ?
+ sampleModel :
+ sampleModel.createSubsetSampleModel(bandList);
+
+ /*
+ data origin
+ /
+ +-------------------------
+ |\. __ parent trans
+ | \`.
+ | \ `. parent origin
+ | \ `. /
+ | /\ +-------- - -
+ |trans\ /<\-- deltaTrans
+ |child +-+-\---- - -
+ | /|`| \__ parent [x, y]
+ |child | |`. \
+ |origin| : `.\
+ | | / `\
+ | : / +
+ | child [x, y]
+
+ parent_xy - parent_trans = child_xy - child_trans
+
+ child_trans = parent_trans + child_xy - parent_xy
+ */
+
+ return new Raster(sm, dataBuffer,
+ new Rectangle(childMinX, childMinY, width, height),
+ new Point(sampleModelTranslateX + childMinX - parentX,
+ sampleModelTranslateY + childMinY - parentY),
+ this);
+ }
+
+ /**
+ * Returns a new rectangle containing the bounds of this raster.
+ *
+ * @return A new rectangle containing the bounds of this raster.
+ */
+ public Rectangle getBounds()
+ {
+ return new Rectangle(minX, minY, width, height);
+ }
+
+ /**
+ * Returns the x-coordinate of the top left corner of the raster.
+ *
+ * @return The x-coordinate of the top left corner of the raster.
+ */
+ public final int getMinX()
+ {
+ return minX;
+ }
+
+ /**
+ * Returns the t-coordinate of the top left corner of the raster.
+ *
+ * @return The t-coordinate of the top left corner of the raster.
+ */
+ public final int getMinY()
+ {
+ return minY;
+ }
+
+ /**
+ * Returns the width of the raster.
+ *
+ * @return The width of the raster.
+ */
+ public final int getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Returns the height of the raster.
+ *
+ * @return The height of the raster.
+ */
+ public final int getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * Returns the number of bands for this raster.
+ *
+ * @return The number of bands.
+ */
+ public final int getNumBands()
+ {
+ return numBands;
+ }
+
+ public final int getNumDataElements()
+ {
+ return numDataElements;
+ }
+
+ /**
+ * Returns the transfer type for the raster (this is determined by the
+ * raster's sample model).
+ *
+ * @return The transfer type.
+ */
+ public final int getTransferType()
+ {
+ return sampleModel.getTransferType();
+ }
+
+ /**
+ * Returns the data buffer that stores the pixel data for this raster.
+ *
+ * @return The data buffer.
+ */
+ public DataBuffer getDataBuffer()
+ {
+ return dataBuffer;
+ }
+
+ /**
+ * Returns the sample model that accesses the data buffer (to extract pixel
+ * data) for this raster.
+ *
+ * @return The sample model.
+ */
+ public SampleModel getSampleModel()
+ {
+ return sampleModel;
+ }
+
+ public Object getDataElements(int x, int y, Object outData)
+ {
+ return sampleModel.getDataElements(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, outData, dataBuffer);
+ }
+
+ public Object getDataElements(int x, int y, int w, int h, Object outData)
+ {
+ return sampleModel.getDataElements(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, w, h, outData, dataBuffer);
+ }
+
+ /**
+ * Returns an array containing the samples for the pixel at (x, y) in the
+ * raster. If <code>iArray</code> is not <code>null</code>, it will be
+ * populated with the sample values and returned as the result of
+ * this function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param iArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ *
+ * @return The pixel sample values.
+ */
+ public int[] getPixel(int x, int y, int[] iArray)
+ {
+ return sampleModel.getPixel(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, iArray, dataBuffer);
+ }
+
+ /**
+ * Returns an array containing the samples for the pixel at (x, y) in the
+ * raster. If <code>fArray</code> is not <code>null</code>, it will be
+ * populated with the sample values and returned as the result of
+ * this function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param fArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ *
+ * @return The pixel sample values.
+ */
+ public float[] getPixel(int x, int y, float[] fArray)
+ {
+ return sampleModel.getPixel(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, fArray, dataBuffer);
+ }
+
+ /**
+ * Returns an array containing the samples for the pixel at (x, y) in the
+ * raster. If <code>dArray</code> is not <code>null</code>, it will be
+ * populated with the sample values and returned as the result of
+ * this function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param dArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ *
+ * @return The pixel sample values.
+ */
+ public double[] getPixel(int x, int y, double[] dArray)
+ {
+ return sampleModel.getPixel(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, dArray, dataBuffer);
+ }
+
+ /**
+ * Returns an array containing the samples for the pixels in the region
+ * specified by (x, y, w, h) in the raster. The array is ordered by pixels
+ * (that is, all the samples for the first pixel are grouped together,
+ * followed by all the samples for the second pixel, and so on).
+ * If <code>iArray</code> is not <code>null</code>, it will be populated
+ * with the sample values and returned as the result of this function (this
+ * avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param iArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ *
+ * @return The pixel sample values.
+ */
+ public int[] getPixels(int x, int y, int w, int h, int[] iArray)
+ {
+ return sampleModel.getPixels(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, w, h, iArray, dataBuffer);
+ }
+
+ /**
+ * Returns an array containing the samples for the pixels in the region
+ * specified by (x, y, w, h) in the raster. The array is ordered by pixels
+ * (that is, all the samples for the first pixel are grouped together,
+ * followed by all the samples for the second pixel, and so on).
+ * If <code>fArray</code> is not <code>null</code>, it will be populated
+ * with the sample values and returned as the result of this function (this
+ * avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param fArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ *
+ * @return The pixel sample values.
+ */
+ public float[] getPixels(int x, int y, int w, int h, float[] fArray)
+ {
+ return sampleModel.getPixels(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, w, h, fArray, dataBuffer);
+ }
+
+ /**
+ * Returns an array containing the samples for the pixels in the region
+ * specified by (x, y, w, h) in the raster. The array is ordered by pixels
+ * (that is, all the samples for the first pixel are grouped together,
+ * followed by all the samples for the second pixel, and so on).
+ * If <code>dArray</code> is not <code>null</code>, it will be populated
+ * with the sample values and returned as the result of this function (this
+ * avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param dArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ *
+ * @return The pixel sample values.
+ */
+ public double[] getPixels(int x, int y, int w, int h, double[] dArray)
+ {
+ return sampleModel.getPixels(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, w, h, dArray, dataBuffer);
+ }
+
+ /**
+ * Returns the sample value for the pixel at (x, y) in the raster.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ *
+ * @return The sample value.
+ */
+ public int getSample(int x, int y, int b)
+ {
+ return sampleModel.getSample(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, b, dataBuffer);
+ }
+
+ /**
+ * Returns the sample value for the pixel at (x, y) in the raster.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ *
+ * @return The sample value.
+ *
+ * @see #getSample(int, int, int)
+ */
+ public float getSampleFloat(int x, int y, int b)
+ {
+ return sampleModel.getSampleFloat(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, b, dataBuffer);
+ }
+
+ /**
+ * Returns the sample value for the pixel at (x, y) in the raster.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ *
+ * @return The sample value.
+ *
+ * @see #getSample(int, int, int)
+ */
+ public double getSampleDouble(int x, int y, int b)
+ {
+ return sampleModel.getSampleDouble(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, b, dataBuffer);
+ }
+
+ /**
+ * Returns an array containing the samples from one band for the pixels in
+ * the region specified by (x, y, w, h) in the raster. If
+ * <code>iArray</code> is not <code>null</code>, it will be
+ * populated with the sample values and returned as the result of this
+ * function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param b the band (in the range <code>0</code> to
+ * </code>getNumBands() - 1</code>).
+ * @param iArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ *
+ * @return The sample values.
+ */
+ public int[] getSamples(int x, int y, int w, int h, int b,
+ int[] iArray)
+ {
+ return sampleModel.getSamples(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, w, h, b, iArray, dataBuffer);
+ }
+
+ /**
+ * Returns an array containing the samples from one band for the pixels in
+ * the region specified by (x, y, w, h) in the raster. If
+ * <code>fArray</code> is not <code>null</code>, it will be
+ * populated with the sample values and returned as the result of this
+ * function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param b the band (in the range <code>0</code> to
+ * </code>getNumBands() - 1</code>).
+ * @param fArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ *
+ * @return The sample values.
+ */
+ public float[] getSamples(int x, int y, int w, int h, int b, float[] fArray)
+ {
+ return sampleModel.getSamples(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, w, h, b, fArray, dataBuffer);
+ }
+
+ /**
+ * Returns an array containing the samples from one band for the pixels in
+ * the region specified by (x, y, w, h) in the raster. If
+ * <code>dArray</code> is not <code>null</code>, it will be
+ * populated with the sample values and returned as the result of this
+ * function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param b the band (in the range <code>0</code> to
+ * </code>getNumBands() - 1</code>).
+ * @param dArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ *
+ * @return The sample values.
+ */
+ public double[] getSamples(int x, int y, int w, int h, int b,
+ double[] dArray)
+ {
+ return sampleModel.getSamples(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, w, h, b, dArray, dataBuffer);
+ }
+
+ /**
+ * Create a String representing the state of this Raster.
+ *
+ * @return A String representing the stat of this Raster.
+ */
+ public String toString()
+ {
+ CPStringBuilder result = new CPStringBuilder();
+
+ result.append(getClass().getName());
+ result.append("[(");
+ result.append(minX).append(",").append(minY).append("), ");
+ result.append(width).append(" x ").append(height).append(",");
+ result.append(sampleModel).append(",");
+ result.append(dataBuffer);
+ result.append("]");
+
+ return result.toString();
+ }
+
+ /**
+ * Returns the number of bits used to represent the specified data type.
+ * Valid types are:
+ * <ul>
+ * <li>{@link DataBuffer#TYPE_BYTE};</li>
+ * <li>{@link DataBuffer#TYPE_USHORT};</li>
+ * <li>{@link DataBuffer#TYPE_SHORT};</li>
+ * <li>{@link DataBuffer#TYPE_INT};</li>
+ * <li>{@link DataBuffer#TYPE_FLOAT};</li>
+ * <li>{@link DataBuffer#TYPE_DOUBLE};</li>
+ * </ul>
+ * This method returns 0 for invalid data types.
+ *
+ * @param dataType the data type.
+ *
+ * @return The number of bits used to represent the specified data type.
+ */
+ private static int getTypeBits(int dataType)
+ {
+ switch (dataType)
+ {
+ case DataBuffer.TYPE_BYTE:
+ return 8;
+ case DataBuffer.TYPE_USHORT:
+ case DataBuffer.TYPE_SHORT:
+ return 16;
+ case DataBuffer.TYPE_INT:
+ case DataBuffer.TYPE_FLOAT:
+ return 32;
+ case DataBuffer.TYPE_DOUBLE:
+ return 64;
+ default:
+ return 0;
+ }
+ }
+}
diff --git a/libjava/classpath/java/awt/image/RasterFormatException.java b/libjava/classpath/java/awt/image/RasterFormatException.java
new file mode 100644
index 000000000..582c2ae5a
--- /dev/null
+++ b/libjava/classpath/java/awt/image/RasterFormatException.java
@@ -0,0 +1,65 @@
+/* RasterFormatException.java -- indicates invalid layout in Raster
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+/**
+ * This exception is thrown when there is invalid layout information in
+ * <code>Raster</code>
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Raster
+ * @status updated to 1.4
+ */
+public class RasterFormatException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = 96598996116164315L;
+
+ /**
+ * Create a new instance with a descriptive error message.
+ *
+ * @param message the descriptive error message
+ */
+ public RasterFormatException(String message)
+ {
+ super(message);
+ }
+} // class RasterFormatException
diff --git a/libjava/classpath/java/awt/image/RasterOp.java b/libjava/classpath/java/awt/image/RasterOp.java
new file mode 100644
index 000000000..2b2c0731f
--- /dev/null
+++ b/libjava/classpath/java/awt/image/RasterOp.java
@@ -0,0 +1,104 @@
+/* RasterOp.java --
+ Copyright (C) 2000, 2002, 2004, 2005, 2006, Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.RenderingHints;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * An operation that is performed on one raster (the source) producing a new
+ * raster (the destination).
+ */
+public interface RasterOp
+{
+ /**
+ * Performs an operation on the source raster, returning the result in a
+ * writable raster. If <code>dest</code> is <code>null</code>, a new
+ * <code>WritableRaster</code> will be created by calling the
+ * {@link #createCompatibleDestRaster(Raster)} method. If <code>dest</code>
+ * is not <code>null</code>, the result is written to <code>dest</code> then
+ * returned (this avoids creating a new <code>WritableRaster</code> each
+ * time this method is called).
+ *
+ * @param src the source raster.
+ * @param dest the destination raster (<code>null</code> permitted).
+ *
+ * @return The filtered raster.
+ */
+ WritableRaster filter(Raster src, WritableRaster dest);
+
+ /**
+ * Returns the bounds of the destination raster on the basis of this
+ * <code>RasterOp</code> being applied to the specified source raster.
+ *
+ * @param src the source raster.
+ *
+ * @return The destination bounds.
+ */
+ Rectangle2D getBounds2D(Raster src);
+
+ /**
+ * Returns a raster that can be used by this <code>RasterOp</code> as the
+ * destination raster when operating on the specified source raster.
+ *
+ * @param src the source raster.
+ *
+ * @return A new writable raster that can be used as the destination raster.
+ */
+ WritableRaster createCompatibleDestRaster(Raster src);
+
+ /**
+ * Returns the point on the destination raster that corresponds to the given
+ * point on the source raster.
+ *
+ * @param srcPoint the source point.
+ * @param destPoint the destination point (<code>null</code> permitted).
+ *
+ * @return The destination point.
+ */
+ Point2D getPoint2D(Point2D srcPoint, Point2D destPoint);
+
+ /**
+ * Returns the rendering hints for this operation.
+ *
+ * @return The rendering hints.
+ */
+ RenderingHints getRenderingHints();
+}
diff --git a/libjava/classpath/java/awt/image/RenderedImage.java b/libjava/classpath/java/awt/image/RenderedImage.java
new file mode 100644
index 000000000..fd18871a9
--- /dev/null
+++ b/libjava/classpath/java/awt/image/RenderedImage.java
@@ -0,0 +1,70 @@
+/* RenderedImage.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.Rectangle;
+import java.util.Vector;
+
+/**
+ * NEEDS DOCUMENTATION
+ */
+public interface RenderedImage
+{
+ Vector<RenderedImage> getSources();
+ Object getProperty(String name);
+ String[] getPropertyNames();
+ ColorModel getColorModel();
+ SampleModel getSampleModel();
+ int getWidth();
+ int getHeight();
+ int getMinX();
+ int getMinY();
+ int getNumXTiles();
+ int getNumYTiles();
+ int getMinTileX();
+ int getMinTileY();
+ int getTileWidth();
+ int getTileHeight();
+ int getTileGridXOffset();
+ int getTileGridYOffset();
+ Raster getTile(int x, int y);
+ Raster getData();
+ Raster getData(Rectangle r);
+ WritableRaster copyData(WritableRaster raster);
+} // interface RenderedImage
diff --git a/libjava/classpath/java/awt/image/ReplicateScaleFilter.java b/libjava/classpath/java/awt/image/ReplicateScaleFilter.java
new file mode 100644
index 000000000..94aad85dd
--- /dev/null
+++ b/libjava/classpath/java/awt/image/ReplicateScaleFilter.java
@@ -0,0 +1,257 @@
+/* ReplicateScaleFilter.java -- Java class for filtering images
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.util.Hashtable;
+
+/**
+ * This filter should be used for fast scaling of images where the result
+ * does not need to ensure straight lines are still straight, etc. The
+ * exact method is not defined by Sun but some sort of fast Box filter should
+ * probably be correct.
+ * <br>
+ * Currently this filter does nothing and needs to be implemented.
+ *
+ * @author C. Brian Jones (cbj@gnu.org)
+ */
+public class ReplicateScaleFilter extends ImageFilter
+{
+ public ReplicateScaleFilter(int width, int height) {
+ destHeight = height;
+ destWidth = width;
+ }
+
+ /**
+ * The height of the destination image.
+ */
+ protected int destHeight;
+
+ /**
+ * The width of the destination image.
+ */
+ protected int destWidth;
+
+ /**
+ * The height of the source image.
+ */
+ protected int srcHeight;
+
+ /**
+ * The width of the source image.
+ */
+ protected int srcWidth;
+
+ /**
+ *
+ */
+ protected int srcrows[];
+
+ /**
+ *
+ */
+ protected int srccols[];
+
+ /**
+ *
+ */
+ protected Object outpixbuf;
+
+ /**
+ * An <code>ImageProducer</code> indicates the size of the image
+ * being produced using this method. A filter can override this
+ * method to intercept these calls from the producer in order to
+ * change either the width or the height before in turn calling
+ * the consumer's <code>setDimensions</code> method.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ */
+ public void setDimensions(int width, int height)
+ {
+ srcWidth = width;
+ srcHeight = height;
+
+ /* If either destHeight or destWidth is < 0, the image should
+ maintain its original aspect ratio. When both are < 0,
+ just maintain the original width and height. */
+ if (destWidth < 0 && destHeight < 0)
+ {
+ destWidth = width;
+ destHeight = height;
+ }
+ else if (destWidth < 0)
+ {
+ destWidth = width * destHeight / srcHeight;
+ }
+ else if (destHeight < 0)
+ {
+ destHeight = height * destWidth / srcWidth;
+ }
+
+ if (consumer != null)
+ consumer.setDimensions(destWidth, destHeight);
+ }
+
+ /**
+ * An <code>ImageProducer</code> can set a list of properties
+ * associated with this image by using this method.
+ *
+ * @param props the list of properties associated with this image
+ */
+ public void setProperties(Hashtable<?, ?> props)
+ {
+ Hashtable<Object, Object> prop2 = (Hashtable<Object, Object>) props;
+ prop2.put("filters", "ReplicateScaleFilter");
+ if (consumer != null)
+ consumer.setProperties(prop2);
+ }
+
+ /**
+ * This function delivers a rectangle of pixels where any
+ * pixel(m,n) is stored in the array as a <code>byte</code> at
+ * index (n * scansize + m + offset).
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param model the <code>ColorModel</code> used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the <code>pixels</code> array
+ * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
+ */
+ public void setPixels(int x, int y, int w, int h,
+ ColorModel model, byte[] pixels, int offset, int scansize)
+ {
+ if (srcrows == null || srccols == null)
+ setupSources();
+ int dx1 = (2 * x * destWidth + srcWidth - 1) / (2 * destWidth);
+ int dy1 = (2 * y * destHeight + srcHeight - 1) / (2 * destHeight);
+ byte[] pix;
+ if (outpixbuf != null && outpixbuf instanceof byte[])
+ {
+ pix = (byte[]) outpixbuf;
+ }
+ else
+ {
+ pix = new byte[destWidth];
+ outpixbuf = pix;
+ }
+ int sy, sx;
+ for (int yy = dy1; (sy = srcrows[yy]) < y + h; yy++)
+ {
+ int offs = offset + scansize * (sy - y);
+ int xx;
+ for (xx = dx1; (sx = srccols[xx]) < x + w; xx++)
+ {
+ pix[xx] = pixels[offs + sx - x];
+ }
+ if (xx > dx1)
+ {
+ consumer.setPixels(dx1, yy, xx - dx1, 1, model, pix, dx1,
+ destWidth);
+ }
+ }
+ }
+
+ /**
+ * This function delivers a rectangle of pixels where any
+ * pixel(m,n) is stored in the array as an <code>int</code> at
+ * index (n * scansize + m + offset).
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param model the <code>ColorModel</code> used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the <code>pixels</code> array
+ * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
+ */
+ public void setPixels(int x, int y, int w, int h,
+ ColorModel model, int[] pixels, int offset, int scansize)
+ {
+ if (srcrows == null || srccols == null)
+ setupSources();
+ int dx1 = (2 * x * destWidth + srcWidth - 1) / (2 * destWidth);
+ int dy1 = (2 * y * destHeight + srcHeight - 1) / (2 * destHeight);
+ int[] pix;
+ if (outpixbuf != null && outpixbuf instanceof int[])
+ {
+ pix = (int[]) outpixbuf;
+ }
+ else
+ {
+ pix = new int[destWidth];
+ outpixbuf = pix;
+ }
+ int sy, sx;
+ for (int yy = dy1; (sy = srcrows[yy]) < y + h; yy++)
+ {
+ int offs = offset + scansize * (sy - y);
+ int xx;
+ for (xx = dx1; (sx = srccols[xx]) < x + w; xx++)
+ {
+ pix[xx] = pixels[offs + sx - x];
+ }
+ if (xx > dx1)
+ {
+ consumer.setPixels(dx1, yy, xx - dx1, 1, model, pix, dx1,
+ destWidth);
+ }
+ }
+ }
+
+ /**
+ * Sets up the srcrows and srccols arrays.
+ */
+ private void setupSources()
+ {
+ srcrows = new int[destHeight + 1];
+ for (int y = 0; y <= destHeight; y++)
+ {
+ srcrows[y] = (2 * y * srcHeight + srcHeight) / (2 * destHeight);
+ }
+ srccols = new int[destWidth + 1];
+ for (int x = 0; x <= destWidth; x++)
+ {
+ srccols[x] = (2 * x * srcWidth + srcWidth) / (2 * destWidth);
+ }
+ }
+}
diff --git a/libjava/classpath/java/awt/image/RescaleOp.java b/libjava/classpath/java/awt/image/RescaleOp.java
new file mode 100644
index 000000000..efab40b7e
--- /dev/null
+++ b/libjava/classpath/java/awt/image/RescaleOp.java
@@ -0,0 +1,385 @@
+/* Copyright (C) 2004, 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.RenderingHints;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.Arrays;
+
+/**
+ * RescaleOp is a filter that changes each pixel by a scaling factor and offset.
+ *
+ * For filtering Rasters, either one scaling factor and offset can be specified,
+ * which will be applied to all bands; or a scaling factor and offset can be
+ * specified for each band.
+ *
+ * For BufferedImages, the scaling may apply to both color and alpha components.
+ * If only one scaling factor is provided, or if the number of factors provided
+ * equals the number of color components, the scaling is performed on all color
+ * components. Otherwise, the scaling is performed on all components including
+ * alpha. Alpha premultiplication is ignored.
+ *
+ * After filtering, if color conversion is necessary, the conversion happens,
+ * taking alpha premultiplication into account.
+ *
+ * @author Jerry Quinn (jlquinn@optonline.net)
+ * @author Francis Kung (fkung@redhat.com)
+ */
+public class RescaleOp implements BufferedImageOp, RasterOp
+{
+ private float[] scale;
+ private float[] offsets;
+ private RenderingHints hints = null;
+
+ /**
+ * Create a new RescaleOp object using the given scale factors and offsets.
+ *
+ * The length of the arrays must be equal to the number of bands (or number of
+ * data or color components) of the raster/image that this Op will be used on,
+ * otherwise an IllegalArgumentException will be thrown when calling the
+ * filter method.
+ *
+ * @param scaleFactors an array of scale factors.
+ * @param offsets an array of offsets.
+ * @param hints any rendering hints to use (can be null).
+ * @throws NullPointerException if the scaleFactors or offsets array is null.
+ */
+ public RescaleOp(float[] scaleFactors,
+ float[] offsets,
+ RenderingHints hints)
+ {
+ int length = Math.min(scaleFactors.length, offsets.length);
+
+ scale = new float[length];
+ System.arraycopy(scaleFactors, 0, this.scale, 0, length);
+
+ this.offsets = new float[length];
+ System.arraycopy(offsets, 0, this.offsets, 0, length);
+
+ this.hints = hints;
+ }
+
+ /**
+ * Create a new RescaleOp object using the given scale factor and offset.
+ *
+ * The same scale factor and offset will be used on all bands/components.
+ *
+ * @param scaleFactor the scale factor to use.
+ * @param offset the offset to use.
+ * @param hints any rendering hints to use (can be null).
+ */
+ public RescaleOp(float scaleFactor,
+ float offset,
+ RenderingHints hints)
+ {
+ scale = new float[]{ scaleFactor };
+ offsets = new float[]{offset};
+ this.hints = hints;
+ }
+
+ /**
+ * Returns the scaling factors. This method accepts an optional array, which
+ * will be used to store the factors if not null (this avoids allocating a
+ * new array). If this array is too small to hold all the scaling factors,
+ * the array will be filled and the remaining factors discarded.
+ *
+ * @param scaleFactors array to store the scaling factors in (can be null).
+ * @return an array of scaling factors.
+ */
+ public final float[] getScaleFactors(float[] scaleFactors)
+ {
+ if (scaleFactors == null)
+ scaleFactors = new float[scale.length];
+ System.arraycopy(scale, 0, scaleFactors, 0, Math.min(scale.length,
+ scaleFactors.length));
+ return scaleFactors;
+ }
+
+ /**
+ * Returns the offsets. This method accepts an optional array, which
+ * will be used to store the offsets if not null (this avoids allocating a
+ * new array). If this array is too small to hold all the offsets, the array
+ * will be filled and the remaining factors discarded.
+ *
+ * @param offsets array to store the offsets in (can be null).
+ * @return an array of offsets.
+ */
+ public final float[] getOffsets(float[] offsets)
+ {
+ if (offsets == null)
+ offsets = new float[this.offsets.length];
+ System.arraycopy(this.offsets, 0, offsets, 0, Math.min(this.offsets.length,
+ offsets.length));
+ return offsets;
+ }
+
+ /**
+ * Returns the number of scaling factors / offsets.
+ *
+ * @return the number of scaling factors / offsets.
+ */
+ public final int getNumFactors()
+ {
+ return scale.length;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#getRenderingHints()
+ */
+ public final RenderingHints getRenderingHints()
+ {
+ return hints;
+ }
+
+ /**
+ * Converts the source image using the scale factors and offsets specified in
+ * the constructor. The resulting image is stored in the destination image if
+ * one is provided; otherwise a new BufferedImage is created and returned.
+ *
+ * The source image cannot use an IndexColorModel, and the destination image
+ * (if one is provided) must have the same size.
+ *
+ * If the final value of a sample is beyond the range of the color model, it
+ * will be clipped to the appropriate maximum / minimum.
+ *
+ * @param src The source image.
+ * @param dst The destination image.
+ * @throws IllegalArgumentException if the rasters and/or color spaces are
+ * incompatible.
+ * @return The rescaled image.
+ */
+ public final BufferedImage filter(BufferedImage src, BufferedImage dst)
+ {
+ // Initial checks
+ if (scale.length != 1
+ && scale.length != src.getColorModel().getNumComponents()
+ && (scale.length != src.getColorModel().getNumColorComponents()))
+ throw new IllegalArgumentException("Source image has wrong number of "
+ + "bands for these scaling factors.");
+
+ if (dst == null)
+ dst = createCompatibleDestImage(src, null);
+ else if (src.getHeight() != dst.getHeight()
+ || src.getWidth() != dst.getWidth())
+ throw new IllegalArgumentException("Source and destination images are "
+ + "different sizes.");
+
+ // Prepare for possible colorspace conversion
+ BufferedImage dst2 = dst;
+ if (dst.getColorModel().getColorSpace().getType() != src.getColorModel().getColorSpace().getType())
+ dst2 = createCompatibleDestImage(src, src.getColorModel());
+
+ // Figure out how many bands to scale
+ int numBands = scale.length;
+ if (scale.length == 1)
+ numBands = src.getColorModel().getNumColorComponents();
+ boolean[] bands = new boolean[numBands];
+ // this assumes the alpha, if present, is the last band
+ Arrays.fill(bands, true);
+
+ // Perform rescaling
+ filter(src.getRaster(), dst2.getRaster(), bands);
+
+ // Copy alpha band if needed (ie if it exists and wasn't scaled)
+ // NOTE: This assumes the alpha component is the last band!
+ if (src.getColorModel().hasAlpha()
+ && numBands == src.getColorModel().getNumColorComponents())
+ {
+
+ dst2.getRaster().setSamples(0, 0, src.getWidth(), src.getHeight(),
+ numBands,
+ src.getRaster().getSamples(0, 0,
+ src.getWidth(),
+ src.getHeight(),
+ numBands,
+ (int[]) null));
+ }
+
+ // Perform colorspace conversion if needed
+ if (dst != dst2)
+ new ColorConvertOp(hints).filter(dst2, dst);
+
+ return dst;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#filter(java.awt.image.Raster, java.awt.image.WritableRaster)
+ */
+ public final WritableRaster filter(Raster src, WritableRaster dest)
+ {
+ // Required sanity checks
+ if (scale.length != 1 && scale.length != src.numBands)
+ throw new IllegalArgumentException("Number of rasters is incompatible "
+ + "with the number of scaling "
+ + "factors provided.");
+
+ if (dest == null)
+ dest = src.createCompatibleWritableRaster();
+ else if (src.getHeight() != dest.getHeight()
+ || src.getWidth() != dest.getWidth())
+ throw new IllegalArgumentException("Source and destination rasters are "
+ + "different sizes.");
+ else if (src.numBands != dest.numBands)
+ throw new IllegalArgumentException("Source and destination rasters "
+ + "are incompatible.");
+
+ // Filter all bands
+ boolean[] bands = new boolean[src.getNumBands()];
+ Arrays.fill(bands, true);
+ return filter(src, dest, bands);
+ }
+
+ /**
+ * Perform raster-based filtering on a selected number of bands.
+ *
+ * The length of the bands array should equal the number of bands; a true
+ * element indicates filtering should happen on the corresponding band, while
+ * a false element will skip the band.
+ *
+ * The rasters are assumed to be compatible and non-null.
+ *
+ * @param src the source raster.
+ * @param dest the destination raster.
+ * @param bands an array indicating which bands to filter.
+ * @throws NullPointerException if any parameter is null.
+ * @throws ArrayIndexOutOfBoundsException if the bands array is too small.
+ * @return the destination raster.
+ */
+ private WritableRaster filter(Raster src, WritableRaster dest, boolean[] bands)
+ {
+ int[] values = new int[src.getHeight() * src.getWidth()];
+ float scaleFactor, offset;
+
+ // Find max sample value, to be used for clipping later
+ int[] maxValue = src.getSampleModel().getSampleSize();
+ for (int i = 0; i < maxValue.length; i++)
+ maxValue[i] = (int)Math.pow(2, maxValue[i]) - 1;
+
+ // TODO: can this be optimized further?
+ // Filter all samples of all requested bands
+ for (int band = 0; band < bands.length; band++)
+ if (bands[band])
+ {
+ values = src.getSamples(src.getMinX(), src.getMinY(), src.getWidth(),
+ src.getHeight(), band, values);
+
+ if (scale.length == 1)
+ {
+ scaleFactor = scale[0];
+ offset = offsets[0];
+ }
+ else
+ {
+ scaleFactor = scale[band];
+ offset = offsets[band];
+ }
+
+ for (int i = 0; i < values.length; i++)
+ {
+ values[i] = (int) (values[i] * scaleFactor + offset);
+
+ // Clip if needed
+ if (values[i] < 0)
+ values[i] = 0;
+ if (values[i] > maxValue[band])
+ values[i] = maxValue[band];
+ }
+
+ dest.setSamples(dest.getMinX(), dest.getMinY(), dest.getWidth(),
+ dest.getHeight(), band, values);
+ }
+
+ return dest;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.awt.image.BufferedImageOp#createCompatibleDestImage(java.awt.image.BufferedImage,
+ * java.awt.image.ColorModel)
+ */
+ public BufferedImage createCompatibleDestImage(BufferedImage src,
+ ColorModel dstCM)
+ {
+ if (dstCM == null)
+ return new BufferedImage(src.getWidth(), src.getHeight(), src.getType());
+
+ return new BufferedImage(dstCM,
+ src.getRaster().createCompatibleWritableRaster(),
+ src.isAlphaPremultiplied(), null);
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#createCompatibleDestRaster(java.awt.image.Raster)
+ */
+ public WritableRaster createCompatibleDestRaster(Raster src)
+ {
+ return src.createCompatibleWritableRaster();
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#getBounds2D(java.awt.image.BufferedImage)
+ */
+ public final Rectangle2D getBounds2D(BufferedImage src)
+ {
+ return src.getRaster().getBounds();
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.RasterOp#getBounds2D(java.awt.image.Raster)
+ */
+ public final Rectangle2D getBounds2D(Raster src)
+ {
+ return src.getBounds();
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.image.BufferedImageOp#getPoint2D(java.awt.geom.Point2D, java.awt.geom.Point2D)
+ */
+ public final Point2D getPoint2D(Point2D src, Point2D dst)
+ {
+ if (dst == null)
+ dst = (Point2D) src.clone();
+ else
+ dst.setLocation(src);
+
+ return dst;
+ }
+
+}
diff --git a/libjava/classpath/java/awt/image/SampleModel.java b/libjava/classpath/java/awt/image/SampleModel.java
new file mode 100644
index 000000000..7e0b18c55
--- /dev/null
+++ b/libjava/classpath/java/awt/image/SampleModel.java
@@ -0,0 +1,974 @@
+/* Copyright (C) 2000, 2001, 2002, 2005, 2006, Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+/**
+ * A <code>SampleModel</code> is used to access pixel data from a
+ * {@link DataBuffer}. This is used by the {@link Raster} class.
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public abstract class SampleModel
+{
+ /** Width of image described. */
+ protected int width;
+
+ /** Height of image described. */
+ protected int height;
+
+ /** Number of bands in the image described. Package-private here,
+ shadowed by ComponentSampleModel. */
+ protected int numBands;
+
+ /**
+ * The DataBuffer type that is used to store the data of the image
+ * described.
+ */
+ protected int dataType;
+
+ /**
+ * Creates a new sample model with the specified attributes.
+ *
+ * @param dataType the data type (one of {@link DataBuffer#TYPE_BYTE},
+ * {@link DataBuffer#TYPE_USHORT}, {@link DataBuffer#TYPE_SHORT},
+ * {@link DataBuffer#TYPE_INT}, {@link DataBuffer#TYPE_FLOAT},
+ * {@link DataBuffer#TYPE_DOUBLE} or {@link DataBuffer#TYPE_UNDEFINED}).
+ * @param w the width in pixels (must be greater than zero).
+ * @param h the height in pixels (must be greater than zero).
+ * @param numBands the number of bands (must be greater than zero).
+ *
+ * @throws IllegalArgumentException if <code>dataType</code> is not one of
+ * the listed values.
+ * @throws IllegalArgumentException if <code>w</code> is less than or equal
+ * to zero.
+ * @throws IllegalArgumentException if <code>h</code> is less than or equal
+ * to zero.
+ * @throws IllegalArgumentException if <code>w * h</code> is greater than
+ * {@link Integer#MAX_VALUE}.
+ */
+ public SampleModel(int dataType, int w, int h, int numBands)
+ {
+ if (dataType != DataBuffer.TYPE_UNDEFINED)
+ if (dataType < DataBuffer.TYPE_BYTE || dataType > DataBuffer.TYPE_DOUBLE)
+ throw new IllegalArgumentException("Unrecognised 'dataType' argument.");
+
+ if ((w <= 0) || (h <= 0))
+ throw new IllegalArgumentException((w <= 0 ? " width<=0" : " width is ok")
+ + (h <= 0 ? " height<=0" : " height is ok"));
+
+ long area = (long) w * (long) h;
+ if (area > Integer.MAX_VALUE)
+ throw new IllegalArgumentException("w * h exceeds Integer.MAX_VALUE.");
+
+ if (numBands <= 0)
+ throw new IllegalArgumentException("Requires numBands > 0.");
+
+ this.dataType = dataType;
+ this.width = w;
+ this.height = h;
+ this.numBands = numBands;
+ }
+
+ /**
+ * Returns the width of the pixel data accessible via this
+ * <code>SampleModel</code>.
+ *
+ * @return The width.
+ *
+ * @see #getHeight()
+ */
+ public final int getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Returns the height of the pixel data accessible via this
+ * <code>SampleModel</code>.
+ *
+ * @return The height.
+ *
+ * @see #getWidth()
+ */
+ public final int getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * Returns the number of bands for this <code>SampleModel</code>.
+ *
+ * @return The number of bands.
+ */
+ public final int getNumBands()
+ {
+ return numBands;
+ }
+
+ public abstract int getNumDataElements();
+
+ /**
+ * Returns the type of the {@link DataBuffer} that this
+ * <code>SampleModel</code> accesses.
+ *
+ * @return The data buffer type.
+ */
+ public final int getDataType()
+ {
+ return dataType;
+ }
+
+ public int getTransferType()
+ {
+ // FIXME: Is this a reasonable default implementation?
+ return dataType;
+ }
+
+ /**
+ * Returns an array containing the samples for the pixel at (x, y) in the
+ * specified data buffer. If <code>iArray</code> is not <code>null</code>,
+ * it will be populated with the sample values and returned as the result of
+ * this function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param iArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The pixel sample values.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
+ public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
+ {
+ if (iArray == null)
+ iArray = new int[numBands];
+ for (int b = 0; b < numBands; b++)
+ iArray[b] = getSample(x, y, b, data);
+ return iArray;
+ }
+
+ /**
+ *
+ * This method is provided as a faster alternative to getPixel(),
+ * that can be used when there is no need to decode the pixel into
+ * separate sample values.
+ *
+ * @param obj An array to return the pixel data in. If null, an
+ * array of the right type and size will be created.
+ *
+ * @return A single pixel as an array object of a primitive type,
+ * based on the transfer type. Eg. if transfer type is
+ * DataBuffer.TYPE_USHORT, then a short[] object is returned.
+ */
+ public abstract Object getDataElements(int x, int y, Object obj,
+ DataBuffer data);
+
+
+ public Object getDataElements(int x, int y, int w, int h, Object obj,
+ DataBuffer data)
+ {
+ int size = w * h;
+ int numDataElements = getNumDataElements();
+ int dataSize = numDataElements * size;
+
+ if (obj == null)
+ {
+ switch (getTransferType())
+ {
+ case DataBuffer.TYPE_BYTE:
+ obj = new byte[dataSize];
+ break;
+ case DataBuffer.TYPE_USHORT:
+ obj = new short[dataSize];
+ break;
+ case DataBuffer.TYPE_INT:
+ obj = new int[dataSize];
+ break;
+ default:
+ // Seems like the only sensible thing to do.
+ throw new ClassCastException();
+ }
+ }
+ Object pixelData = null;
+ int outOffset = 0;
+ for (int yy = y; yy < (y + h); yy++)
+ {
+ for (int xx = x; xx < (x + w); xx++)
+ {
+ pixelData = getDataElements(xx, yy, pixelData, data);
+ System.arraycopy(pixelData, 0, obj, outOffset,
+ numDataElements);
+ outOffset += numDataElements;
+ }
+ }
+ return obj;
+ }
+
+ public abstract void setDataElements(int x, int y, Object obj,
+ DataBuffer data);
+
+ public void setDataElements(int x, int y, int w, int h,
+ Object obj, DataBuffer data)
+ {
+ int numDataElements = getNumDataElements();
+
+ Object pixelData;
+ switch (getTransferType())
+ {
+ case DataBuffer.TYPE_BYTE:
+ pixelData = new byte[numDataElements];
+ break;
+ case DataBuffer.TYPE_USHORT:
+ case DataBuffer.TYPE_SHORT:
+ pixelData = new short[numDataElements];
+ break;
+ case DataBuffer.TYPE_INT:
+ pixelData = new int[numDataElements];
+ break;
+ case DataBuffer.TYPE_FLOAT:
+ pixelData = new float[numDataElements];
+ break;
+ case DataBuffer.TYPE_DOUBLE:
+ pixelData = new double[numDataElements];
+ break;
+ default:
+ // The RI silently igores invalid types.
+ pixelData = null;
+ }
+
+ int inOffset = 0;
+ if (pixelData != null)
+ {
+ for (int yy=y; yy<(y+h); yy++)
+ {
+ for (int xx=x; xx<(x+w); xx++)
+ {
+ System.arraycopy(obj, inOffset, pixelData, 0, numDataElements);
+ setDataElements(xx, yy, pixelData, data);
+ inOffset += numDataElements;
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns an array containing the samples for the pixel at (x, y) in the
+ * specified data buffer. If <code>fArray</code> is not <code>null</code>,
+ * it will be populated with the sample values and returned as the result of
+ * this function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param fArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The pixel sample values.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
+ public float[] getPixel(int x, int y, float[] fArray, DataBuffer data)
+ {
+ if (fArray == null)
+ fArray = new float[numBands];
+
+ for (int b = 0; b < numBands; b++)
+ {
+ fArray[b] = getSampleFloat(x, y, b, data);
+ }
+ return fArray;
+ }
+
+ /**
+ * Returns an array containing the samples for the pixel at (x, y) in the
+ * specified data buffer. If <code>dArray</code> is not <code>null</code>,
+ * it will be populated with the sample values and returned as the result of
+ * this function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param dArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The pixel sample values.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
+ public double[] getPixel(int x, int y, double[] dArray, DataBuffer data) {
+ if (dArray == null)
+ dArray = new double[numBands];
+ for (int b = 0; b < numBands; b++)
+ {
+ dArray[b] = getSampleDouble(x, y, b, data);
+ }
+ return dArray;
+ }
+
+ /**
+ * Returns an array containing the samples for the pixels in the region
+ * specified by (x, y, w, h) in the specified data buffer. The array is
+ * ordered by pixels (that is, all the samples for the first pixel are
+ * grouped together, followed by all the samples for the second pixel, and so
+ * on). If <code>iArray</code> is not <code>null</code>, it will be
+ * populated with the sample values and returned as the result of this
+ * function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param iArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The pixel sample values.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
+ public int[] getPixels(int x, int y, int w, int h, int[] iArray,
+ DataBuffer data)
+ {
+ int size = w * h;
+ int outOffset = 0;
+ int[] pixel = null;
+ if (iArray == null)
+ iArray = new int[w * h * numBands];
+ for (int yy = y; yy < (y + h); yy++)
+ {
+ for (int xx = x; xx < (x + w); xx++)
+ {
+ pixel = getPixel(xx, yy, pixel, data);
+ System.arraycopy(pixel, 0, iArray, outOffset, numBands);
+ outOffset += numBands;
+ }
+ }
+ return iArray;
+ }
+
+ /**
+ * Returns an array containing the samples for the pixels in the region
+ * specified by (x, y, w, h) in the specified data buffer. The array is
+ * ordered by pixels (that is, all the samples for the first pixel are
+ * grouped together, followed by all the samples for the second pixel, and so
+ * on). If <code>fArray</code> is not <code>null</code>, it will be
+ * populated with the sample values and returned as the result of this
+ * function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param fArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The pixel sample values.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
+ public float[] getPixels(int x, int y, int w, int h, float[] fArray,
+ DataBuffer data)
+ {
+ int size = w * h;
+ int outOffset = 0;
+ float[] pixel = null;
+ if (fArray == null) fArray = new float[w * h * numBands];
+ for (int yy = y; yy < (y + h); yy++)
+ {
+ for (int xx = x; xx < (x + w); xx++)
+ {
+ pixel = getPixel(xx, yy, pixel, data);
+ System.arraycopy(pixel, 0, fArray, outOffset, numBands);
+ outOffset += numBands;
+ }
+ }
+ return fArray;
+ }
+
+ /**
+ * Returns an array containing the samples for the pixels in the region
+ * specified by (x, y, w, h) in the specified data buffer. The array is
+ * ordered by pixels (that is, all the samples for the first pixel are
+ * grouped together, followed by all the samples for the second pixel, and so
+ * on). If <code>dArray</code> is not <code>null</code>, it will be
+ * populated with the sample values and returned as the result of this
+ * function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param dArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The pixel sample values.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
+ public double[] getPixels(int x, int y, int w, int h, double[] dArray,
+ DataBuffer data)
+ {
+ int size = w * h;
+ int outOffset = 0;
+ double[] pixel = null;
+ if (dArray == null)
+ dArray = new double[w * h * numBands];
+ for (int yy = y; yy < (y + h); yy++)
+ {
+ for (int xx = x; xx < (x + w); xx++)
+ {
+ pixel = getPixel(xx, yy, pixel, data);
+ System.arraycopy(pixel, 0, dArray, outOffset, numBands);
+ outOffset += numBands;
+ }
+ }
+ return dArray;
+ }
+
+ /**
+ * Returns the sample value for the pixel at (x, y) in the specified data
+ * buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The sample value.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
+ public abstract int getSample(int x, int y, int b, DataBuffer data);
+
+ /**
+ * Returns the sample value for the pixel at (x, y) in the specified data
+ * buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The sample value.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ *
+ * @see #getSample(int, int, int, DataBuffer)
+ */
+ public float getSampleFloat(int x, int y, int b, DataBuffer data)
+ {
+ return getSample(x, y, b, data);
+ }
+
+ /**
+ * Returns the sample value for the pixel at (x, y) in the specified data
+ * buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The sample value.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ *
+ * @see #getSample(int, int, int, DataBuffer)
+ */
+ public double getSampleDouble(int x, int y, int b, DataBuffer data)
+ {
+ return getSampleFloat(x, y, b, data);
+ }
+
+ /**
+ * Returns an array containing the samples from one band for the pixels in
+ * the region specified by (x, y, w, h) in the specified data buffer. If
+ * <code>iArray</code> is not <code>null</code>, it will be
+ * populated with the sample values and returned as the result of this
+ * function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param b the band (in the range <code>0</code> to
+ * </code>getNumBands() - 1</code>).
+ * @param iArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The sample values.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
+ public int[] getSamples(int x, int y, int w, int h, int b,
+ int[] iArray, DataBuffer data)
+ {
+ int size = w * h;
+ int outOffset = 0;
+ if (iArray == null)
+ iArray = new int[size];
+ for (int yy = y; yy < (y + h); yy++)
+ {
+ for (int xx = x; xx < (x + w); xx++)
+ {
+ iArray[outOffset++] = getSample(xx, yy, b, data);
+ }
+ }
+ return iArray;
+ }
+
+ /**
+ * Returns an array containing the samples from one band for the pixels in
+ * the region specified by (x, y, w, h) in the specified data buffer. If
+ * <code>fArray</code> is not <code>null</code>, it will be
+ * populated with the sample values and returned as the result of this
+ * function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param b the band (in the range <code>0</code> to
+ * </code>getNumBands() - 1</code>).
+ * @param fArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The sample values.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
+ public float[] getSamples(int x, int y, int w, int h, int b,
+ float[] fArray, DataBuffer data)
+ {
+ int size = w * h;
+ int outOffset = 0;
+ if (fArray == null)
+ fArray = new float[size];
+ for (int yy = y; yy < (y + h); yy++)
+ {
+ for (int xx = x; xx < (x + w); xx++)
+ {
+ fArray[outOffset++] = getSampleFloat(xx, yy, b, data);
+ }
+ }
+ return fArray;
+ }
+
+ /**
+ * Returns an array containing the samples from one band for the pixels in
+ * the region specified by (x, y, w, h) in the specified data buffer. If
+ * <code>dArray</code> is not <code>null</code>, it will be
+ * populated with the sample values and returned as the result of this
+ * function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param b the band (in the range <code>0</code> to
+ * </code>getNumBands() - 1</code>).
+ * @param dArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The sample values.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
+ public double[] getSamples(int x, int y, int w, int h, int b,
+ double[] dArray, DataBuffer data)
+ {
+ int size = w * h;
+ int outOffset = 0;
+ if (dArray == null)
+ dArray = new double[size];
+ for (int yy = y; yy < (y + h); yy++)
+ {
+ for (int xx = x; xx < (x + w); xx++)
+ {
+ dArray[outOffset++] = getSampleDouble(xx, yy, b, data);
+ }
+ }
+ return dArray;
+ }
+
+ /**
+ * Sets the samples for the pixel at (x, y) in the specified data buffer to
+ * the specified values.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param iArray the sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>iArray</code> or
+ * <code>data</code> is <code>null</code>.
+ */
+ public void setPixel(int x, int y, int[] iArray, DataBuffer data)
+ {
+ for (int b = 0; b < numBands; b++)
+ setSample(x, y, b, iArray[b], data);
+ }
+
+ /**
+ * Sets the samples for the pixel at (x, y) in the specified data buffer to
+ * the specified values.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param fArray the sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>fArray</code> or
+ * <code>data</code> is <code>null</code>.
+ */
+ public void setPixel(int x, int y, float[] fArray, DataBuffer data)
+ {
+ for (int b = 0; b < numBands; b++)
+ setSample(x, y, b, fArray[b], data);
+ }
+
+ /**
+ * Sets the samples for the pixel at (x, y) in the specified data buffer to
+ * the specified values.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param dArray the sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>dArray</code> or
+ * <code>data</code> is <code>null</code>.
+ */
+ public void setPixel(int x, int y, double[] dArray, DataBuffer data)
+ {
+ for (int b = 0; b < numBands; b++)
+ setSample(x, y, b, dArray[b], data);
+ }
+
+ /**
+ * Sets the sample values for the pixels in the region specified by
+ * (x, y, w, h) in the specified data buffer. The array is
+ * ordered by pixels (that is, all the samples for the first pixel are
+ * grouped together, followed by all the samples for the second pixel, and so
+ * on).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param iArray the pixel sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>iArray</code> or
+ * <code>data</code> is <code>null</code>.
+ */
+ public void setPixels(int x, int y, int w, int h, int[] iArray,
+ DataBuffer data)
+ {
+ int inOffset = 0;
+ int[] pixel = new int[numBands];
+ for (int yy = y; yy < (y + h); yy++)
+ {
+ for (int xx = x; xx < (x + w); xx++)
+ {
+ System.arraycopy(iArray, inOffset, pixel, 0, numBands);
+ setPixel(xx, yy, pixel, data);
+ inOffset += numBands;
+ }
+ }
+ }
+
+ /**
+ * Sets the sample values for the pixels in the region specified by
+ * (x, y, w, h) in the specified data buffer. The array is
+ * ordered by pixels (that is, all the samples for the first pixel are
+ * grouped together, followed by all the samples for the second pixel, and so
+ * on).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param fArray the pixel sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>fArray</code> or
+ * <code>data</code> is <code>null</code>.
+ */
+ public void setPixels(int x, int y, int w, int h, float[] fArray,
+ DataBuffer data)
+ {
+ int inOffset = 0;
+ float[] pixel = new float[numBands];
+ for (int yy = y; yy < (y + h); yy++)
+ {
+ for (int xx = x; xx < (x + w); xx++)
+ {
+ System.arraycopy(fArray, inOffset, pixel, 0, numBands);
+ setPixel(xx, yy, pixel, data);
+ inOffset += numBands;
+ }
+ }
+ }
+
+ /**
+ * Sets the sample values for the pixels in the region specified by
+ * (x, y, w, h) in the specified data buffer. The array is
+ * ordered by pixels (that is, all the samples for the first pixel are
+ * grouped together, followed by all the samples for the second pixel, and so
+ * on).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param dArray the pixel sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>dArray</code> or
+ * <code>data</code> is <code>null</code>.
+ */
+ public void setPixels(int x, int y, int w, int h, double[] dArray,
+ DataBuffer data)
+ {
+ int inOffset = 0;
+ double[] pixel = new double[numBands];
+ for (int yy = y; yy < (y + h); yy++)
+ {
+ for (int xx = x; xx < (x + w); xx++)
+ {
+ System.arraycopy(dArray, inOffset, pixel, 0, numBands);
+ setPixel(xx, yy, pixel, data);
+ inOffset += numBands;
+ }
+ }
+ }
+
+ /**
+ * Sets the sample value for a band for the pixel at (x, y) in the
+ * specified data buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param s the sample value.
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
+ public abstract void setSample(int x, int y, int b, int s,
+ DataBuffer data);
+
+ /**
+ * Sets the sample value for a band for the pixel at (x, y) in the
+ * specified data buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param s the sample value.
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
+ public void setSample(int x, int y, int b, float s,
+ DataBuffer data)
+ {
+ setSample(x, y, b, (int) s, data);
+ }
+
+ /**
+ * Sets the sample value for a band for the pixel at (x, y) in the
+ * specified data buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param s the sample value.
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
+ public void setSample(int x, int y, int b, double s,
+ DataBuffer data)
+ {
+ setSample(x, y, b, (float) s, data);
+ }
+
+ /**
+ * Sets the sample values for one band for the pixels in the region
+ * specified by (x, y, w, h) in the specified data buffer.
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param b the band (in the range <code>0</code> to
+ * </code>getNumBands() - 1</code>).
+ * @param iArray the sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>iArray</code> or
+ * <code>data</code> is <code>null</code>.
+ */
+ public void setSamples(int x, int y, int w, int h, int b,
+ int[] iArray, DataBuffer data)
+ {
+ int size = w * h;
+ int inOffset = 0;
+ for (int yy = y; yy < (y + h); yy++)
+ for (int xx = x; xx < (x + w); xx++)
+ setSample(xx, yy, b, iArray[inOffset++], data);
+ }
+
+ /**
+ * Sets the sample values for one band for the pixels in the region
+ * specified by (x, y, w, h) in the specified data buffer.
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param b the band (in the range <code>0</code> to
+ * </code>getNumBands() - 1</code>).
+ * @param fArray the sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>iArray</code> or
+ * <code>data</code> is <code>null</code>.
+ */
+ public void setSamples(int x, int y, int w, int h, int b,
+ float[] fArray, DataBuffer data)
+ {
+ int size = w * h;
+ int inOffset = 0;
+ for (int yy = y; yy < (y + h); yy++)
+ for (int xx = x; xx < (x + w); xx++)
+ setSample(xx, yy, b, fArray[inOffset++], data);
+
+ }
+
+ /**
+ * Sets the sample values for one band for the pixels in the region
+ * specified by (x, y, w, h) in the specified data buffer.
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param b the band (in the range <code>0</code> to
+ * </code>getNumBands() - 1</code>).
+ * @param dArray the sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>iArray</code> or
+ * <code>data</code> is <code>null</code>.
+ */
+ public void setSamples(int x, int y, int w, int h, int b,
+ double[] dArray, DataBuffer data) {
+ int size = w * h;
+ int inOffset = 0;
+ for (int yy = y; yy < (y + h); yy++)
+ for (int xx = x; xx < (x + w); xx++)
+ setSample(xx, yy, b, dArray[inOffset++], data);
+ }
+
+ /**
+ * Creates a new <code>SampleModel</code> that is compatible with this
+ * model and has the specified width and height.
+ *
+ * @param w the width (in pixels).
+ * @param h the height (in pixels).
+ *
+ * @return The new sample model.
+ */
+ public abstract SampleModel createCompatibleSampleModel(int w, int h);
+
+ /**
+ * Return a SampleModel with a subset of the bands in this model.
+ *
+ * Selects bands.length bands from this sample model. The bands chosen
+ * are specified in the indices of bands[]. This also permits permuting
+ * the bands as well as taking a subset. Thus, giving an array with
+ * 1, 2, 3, ..., numbands, will give an identical sample model.
+ *
+ * @param bands Array with band indices to include.
+ * @return A new sample model
+ */
+ public abstract SampleModel createSubsetSampleModel(int[] bands);
+
+ /**
+ * Creates a new {@link DataBuffer} of the correct type and size for this
+ * <code>SampleModel</code>.
+ *
+ * @return The data buffer.
+ */
+ public abstract DataBuffer createDataBuffer();
+
+ /**
+ * Returns an array containing the size (in bits) for each band accessed by
+ * the <code>SampleModel</code>.
+ *
+ * @return An array.
+ *
+ * @see #getSampleSize(int)
+ */
+ public abstract int[] getSampleSize();
+
+ /**
+ * Returns the size (in bits) of the samples for the specified band.
+ *
+ * @param band the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ *
+ * @return The sample size (in bits).
+ */
+ public abstract int getSampleSize(int band);
+}
diff --git a/libjava/classpath/java/awt/image/ShortLookupTable.java b/libjava/classpath/java/awt/image/ShortLookupTable.java
new file mode 100644
index 000000000..3e276fe9f
--- /dev/null
+++ b/libjava/classpath/java/awt/image/ShortLookupTable.java
@@ -0,0 +1,177 @@
+/* ShortLookupTable.java -- Java class for a pixel translation table.
+ Copyright (C) 2004, 2005, 2006, Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+/**
+ * ShortLookupTable represents translation arrays for pixel values. It wraps
+ * one or more data arrays for each layer (or component) in an image, such as
+ * Alpha, R, G, and B. When doing translation, the offset is subtracted from
+ * the pixel values to allow a subset of an array to be used.
+ *
+ * @author Jerry Quinn (jlquinn@optonline.net)
+ * @version 1.0
+ */
+public class ShortLookupTable extends LookupTable
+{
+ // Array of translation tables.
+ private short data[][];
+
+ /**
+ * Creates a new <code>ShortLookupTable</code> instance.
+ *
+ * Offset is subtracted from pixel values when looking up in the translation
+ * tables. If data.length is one, the same table is applied to all pixel
+ * components.
+ *
+ * @param offset Offset to be subtracted.
+ * @param data Array of lookup tables.
+ * @exception IllegalArgumentException if offset &lt; 0 or data.length &lt; 1.
+ */
+ public ShortLookupTable(int offset, short[][] data)
+ throws IllegalArgumentException
+ {
+ super(offset, data.length);
+
+ // tests show that Sun's implementation creates a new array to store the
+ // references from the incoming 'data' array - not sure why, but we'll
+ // match that behaviour just in case it matters...
+ this.data = new short[data.length][];
+ for (int i = 0; i < data.length; i++)
+ this.data[i] = data[i];
+ }
+
+ /**
+ * Creates a new <code>ShortLookupTable</code> instance.
+ *
+ * Offset is subtracted from pixel values when looking up in the translation
+ * table. The same table is applied to all pixel components.
+ *
+ * @param offset Offset to be subtracted.
+ * @param data Lookup table for all components (<code>null</code> not
+ * permitted).
+ * @exception IllegalArgumentException if offset &lt; 0.
+ */
+ public ShortLookupTable(int offset, short[] data)
+ throws IllegalArgumentException
+ {
+ super(offset, 1);
+ if (data == null)
+ throw new NullPointerException("Null 'data' argument.");
+ this.data = new short[][] {data};
+ }
+
+ /**
+ * Return the lookup tables. This is a reference to the actual table, so
+ * modifying the contents of the returned array will modify the lookup table.
+ *
+ * @return The lookup table.
+ */
+ public final short[][] getTable()
+ {
+ return data;
+ }
+
+ /**
+ * Return translated values for a pixel.
+ *
+ * For each value in the pixel src, use the value minus offset as an index
+ * in the component array and copy the value there to the output for the
+ * component. If dest is null, the output is a new array, otherwise the
+ * translated values are written to dest. Dest can be the same array as
+ * src.
+ *
+ * For example, if the pixel src is [2, 4, 3], and offset is 1, the output
+ * is [comp1[1], comp2[3], comp3[2]], where comp1, comp2, and comp3 are the
+ * translation arrays.
+ *
+ * @param src Component values of a pixel.
+ * @param dst Destination array for values, or null.
+ * @return Translated values for the pixel.
+ */
+ public int[] lookupPixel(int[] src, int[] dst)
+ throws ArrayIndexOutOfBoundsException
+ {
+ if (dst == null)
+ dst = new int[src.length];
+
+ if (data.length == 1)
+ for (int i = 0; i < src.length; i++)
+ dst[i] = data[0][src[i] - offset];
+ else
+ for (int i = 0; i < src.length; i++)
+ dst[i] = data[i][src[i] - offset];
+
+ return dst;
+ }
+
+ /**
+ * Return translated values for a pixel.
+ *
+ * For each value in the pixel src, use the value minus offset as an index
+ * in the component array and copy the value there to the output for the
+ * component. If dest is null, the output is a new array, otherwise the
+ * translated values are written to dest. Dest can be the same array as
+ * src.
+ *
+ * For example, if the pixel src is [2, 4, 3], and offset is 1, the output
+ * is [comp1[1], comp2[3], comp3[2]], where comp1, comp2, and comp3 are the
+ * translation arrays.
+ *
+ * @param src Component values of a pixel.
+ * @param dst Destination array for values, or null.
+ * @return Translated values for the pixel.
+ *
+ */
+ public short[] lookupPixel(short[] src, short[] dst)
+ throws ArrayIndexOutOfBoundsException
+ {
+ if (dst == null)
+ dst = new short[src.length];
+
+ if (data.length == 1)
+ for (int i = 0; i < src.length; i++)
+ dst[i] = data[0][((int) src[i]) - offset];
+ else
+ for (int i = 0; i < src.length; i++)
+ dst[i] = data[i][((int) src[i]) - offset];
+
+ return dst;
+
+ }
+}
diff --git a/libjava/classpath/java/awt/image/SinglePixelPackedSampleModel.java b/libjava/classpath/java/awt/image/SinglePixelPackedSampleModel.java
new file mode 100644
index 000000000..143581db9
--- /dev/null
+++ b/libjava/classpath/java/awt/image/SinglePixelPackedSampleModel.java
@@ -0,0 +1,586 @@
+/* Copyright (C) 2000, 2002, 2003, 2004, 2006, Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.image;
+
+import java.util.Arrays;
+
+import gnu.java.awt.BitMaskExtent;
+import gnu.java.lang.CPStringBuilder;
+
+/**
+ * A <code>SampleModel</code> used when all samples are stored in a single
+ * data element in the {@link DataBuffer}, and each data element contains
+ * samples for one pixel only.
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public class SinglePixelPackedSampleModel extends SampleModel
+{
+ private int scanlineStride;
+ private int[] bitMasks;
+ private int[] bitOffsets;
+ private int[] sampleSize;
+
+ /**
+ * Creates a new <code>SinglePixelPackedSampleModel</code>.
+ *
+ * @param dataType the data buffer type.
+ * @param w the width (in pixels).
+ * @param h the height (in pixels).
+ * @param bitMasks an array containing the bit mask used to extract the
+ * sample value for each band.
+ */
+ public SinglePixelPackedSampleModel(int dataType, int w, int h,
+ int[] bitMasks)
+ {
+ this(dataType, w, h, w, bitMasks);
+ }
+
+ /**
+ * Creates a new <code>SinglePixelPackedSampleModel</code>.
+ *
+ * @param dataType the data buffer type.
+ * @param w the width (in pixels).
+ * @param h the height (in pixels).
+ * @param scanlineStride the number of data elements between a pixel on one
+ * row and the corresponding pixel on the next row.
+ * @param bitMasks an array containing the bit mask used to extract the
+ * sample value for each band.
+ */
+ public SinglePixelPackedSampleModel(int dataType, int w, int h,
+ int scanlineStride, int[] bitMasks)
+ {
+ super(dataType, w, h, bitMasks.length);
+
+ switch (dataType)
+ {
+ case DataBuffer.TYPE_BYTE:
+ case DataBuffer.TYPE_USHORT:
+ case DataBuffer.TYPE_INT:
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "SinglePixelPackedSampleModel unsupported dataType");
+ }
+
+ this.scanlineStride = scanlineStride;
+ this.bitMasks = bitMasks;
+
+ bitOffsets = new int[numBands];
+ sampleSize = new int[numBands];
+
+ BitMaskExtent extent = new BitMaskExtent();
+ for (int b = 0; b < numBands; b++)
+ {
+ // the mask is an unsigned integer
+ long mask = bitMasks[b] & 0xFFFFFFFFL;
+ extent.setMask(mask);
+ sampleSize[b] = extent.bitWidth;
+ bitOffsets[b] = extent.leastSignificantBit;
+ }
+ }
+
+ /**
+ * Returns the number of data elements.
+ *
+ * @return <code>1</code>.
+ */
+ public int getNumDataElements()
+ {
+ return 1;
+ }
+
+ /**
+ * Creates a new <code>SampleModel</code> that is compatible with this
+ * model and has the specified width and height.
+ *
+ * @param w the width (in pixels).
+ * @param h the height (in pixels).
+ *
+ * @return The new sample model.
+ */
+ public SampleModel createCompatibleSampleModel(int w, int h)
+ {
+ /* FIXME: We can avoid recalculation of bit offsets and sample
+ sizes here by passing these from the current instance to a
+ special private constructor. */
+ return new SinglePixelPackedSampleModel(dataType, w, h, bitMasks);
+ }
+
+
+ /**
+ * Creates a DataBuffer for holding pixel data in the format and
+ * layout described by this SampleModel. The returned buffer will
+ * consist of one single bank.
+ *
+ * @return The data buffer.
+ */
+ public DataBuffer createDataBuffer()
+ {
+ // We can save (scanlineStride - width) pixels at the very end of
+ // the buffer. The Sun reference implementation (J2SE 1.3.1 and
+ // 1.4.1_01) seems to do this; tested with Mauve test code.
+ int size = scanlineStride * (height - 1) + width;
+
+ DataBuffer buffer = null;
+ switch (getTransferType())
+ {
+ case DataBuffer.TYPE_BYTE:
+ buffer = new DataBufferByte(size);
+ break;
+ case DataBuffer.TYPE_USHORT:
+ buffer = new DataBufferUShort(size);
+ break;
+ case DataBuffer.TYPE_INT:
+ buffer = new DataBufferInt(size);
+ break;
+ }
+ return buffer;
+ }
+
+ /**
+ * Returns an array containing the size (in bits) for each band accessed by
+ * the <code>SampleModel</code>.
+ *
+ * @return An array.
+ *
+ * @see #getSampleSize(int)
+ */
+ public int[] getSampleSize()
+ {
+ return (int[]) sampleSize.clone();
+ }
+
+ /**
+ * Returns the size (in bits) of the samples for the specified band.
+ *
+ * @param band the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ *
+ * @return The sample size (in bits).
+ */
+ public int getSampleSize(int band)
+ {
+ return sampleSize[band];
+ }
+
+ /**
+ * Returns the index in the data buffer that stores the pixel at (x, y).
+ *
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ *
+ * @return The index in the data buffer that stores the pixel at (x, y).
+ */
+ public int getOffset(int x, int y)
+ {
+ return scanlineStride*y + x;
+ }
+
+ public int[] getBitOffsets()
+ {
+ return bitOffsets;
+ }
+
+ public int[] getBitMasks()
+ {
+ return bitMasks;
+ }
+
+ /**
+ * Returns the number of data elements from a pixel in one row to the
+ * corresponding pixel in the next row.
+ *
+ * @return The scanline stride.
+ */
+ public int getScanlineStride()
+ {
+ return scanlineStride;
+ }
+
+ /**
+ * Creates a new <code>SinglePixelPackedSampleModel</code> that accesses
+ * the specified subset of bands.
+ *
+ * @param bands an array containing band indices (<code>null</code> not
+ * permitted).
+ *
+ * @return A new sample model.
+ *
+ * @throws NullPointerException if <code>bands</code> is <code>null</code>.
+ * @throws RasterFormatException if <code>bands.length</code> is greater
+ * than the number of bands in this model.
+ */
+ public SampleModel createSubsetSampleModel(int[] bands)
+ {
+ if (bands.length > numBands)
+ throw new RasterFormatException("Too many bands.");
+
+ int numBands = bands.length;
+
+ int[] bitMasks = new int[numBands];
+
+ for (int b = 0; b < numBands; b++)
+ bitMasks[b] = this.bitMasks[bands[b]];
+
+ return new SinglePixelPackedSampleModel(dataType, width, height,
+ scanlineStride, bitMasks);
+ }
+
+ public Object getDataElements(int x, int y, Object obj,
+ DataBuffer data)
+ {
+ int type = getTransferType();
+ Object ret = null;
+ switch (type)
+ {
+ case DataBuffer.TYPE_BYTE:
+ {
+ byte[] in = (byte[]) obj;
+ if (in == null)
+ in = new byte[1];
+ in[0] = (byte) data.getElem(x + y * scanlineStride);
+ ret = in;
+ }
+ break;
+ case DataBuffer.TYPE_USHORT:
+ {
+ short[] in = (short[]) obj;
+ if (in == null)
+ in = new short[1];
+ in[0] = (short) data.getElem(x + y * scanlineStride);
+ ret = in;
+ }
+ break;
+ case DataBuffer.TYPE_INT:
+ {
+ int[] in = (int[]) obj;
+ if (in == null)
+ in = new int[1];
+ in[0] = data.getElem(x + y * scanlineStride);
+ ret = in;
+ }
+ break;
+ }
+ return ret;
+ }
+
+ /**
+ * Returns an array containing the samples for the pixel at (x, y) in the
+ * specified data buffer. If <code>iArray</code> is not <code>null</code>,
+ * it will be populated with the sample values and returned as the result of
+ * this function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param iArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The pixel sample values.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
+ public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
+ {
+ int offset = scanlineStride*y + x;
+ if (iArray == null) iArray = new int[numBands];
+ int samples = data.getElem(offset);
+
+ for (int b = 0; b < numBands; b++)
+ iArray[b] = (samples & bitMasks[b]) >>> bitOffsets[b];
+
+ return iArray;
+ }
+
+ /**
+ * Returns an array containing the samples for the pixels in the region
+ * specified by (x, y, w, h) in the specified data buffer. The array is
+ * ordered by pixels (that is, all the samples for the first pixel are
+ * grouped together, followed by all the samples for the second pixel, and so
+ * on). If <code>iArray</code> is not <code>null</code>, it will be
+ * populated with the sample values and returned as the result of this
+ * function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param iArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The pixel sample values.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
+ public int[] getPixels(int x, int y, int w, int h, int[] iArray,
+ DataBuffer data)
+ {
+ int offset = scanlineStride*y + x;
+ if (iArray == null) iArray = new int[numBands*w*h];
+ int outOffset = 0;
+ for (y = 0; y < h; y++)
+ {
+ int lineOffset = offset;
+ for (x = 0; x < w; x++)
+ {
+ int samples = data.getElem(lineOffset++);
+ for (int b = 0; b < numBands; b++)
+ iArray[outOffset++] = (samples & bitMasks[b]) >>> bitOffsets[b];
+ }
+ offset += scanlineStride;
+ }
+ return iArray;
+ }
+
+ /**
+ * Returns the sample value for the pixel at (x, y) in the specified data
+ * buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The sample value.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
+ public int getSample(int x, int y, int b, DataBuffer data)
+ {
+ int offset = scanlineStride*y + x;
+ int samples = data.getElem(offset);
+ return (samples & bitMasks[b]) >>> bitOffsets[b];
+ }
+
+ public void setDataElements(int x, int y, Object obj, DataBuffer data)
+ {
+ int transferType = getTransferType();
+ switch (transferType)
+ {
+ case DataBuffer.TYPE_BYTE:
+ {
+ byte[] in = (byte[]) obj;
+ data.setElem(y * scanlineStride + x, ((int) in[0]) & 0xff);
+ }
+ break;
+ case DataBuffer.TYPE_USHORT:
+ {
+ short[] in = (short[]) obj;
+ data.setElem(y * scanlineStride + x, ((int) in[0]) & 0xffff);
+ }
+ break;
+ case DataBuffer.TYPE_INT:
+ {
+ int[] in = (int[]) obj;
+ data.setElem(y * scanlineStride + x, in[0]);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Sets the samples for the pixel at (x, y) in the specified data buffer to
+ * the specified values.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param iArray the sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>iArray</code> or
+ * <code>data</code> is <code>null</code>.
+ */
+ public void setPixel(int x, int y, int[] iArray, DataBuffer data)
+ {
+ int offset = scanlineStride*y + x;
+
+ int samples = 0;
+ for (int b = 0; b < numBands; b++)
+ samples |= (iArray[b] << bitOffsets[b]) & bitMasks[b];
+
+ data.setElem(offset, samples);
+ }
+
+ /**
+ * This method implements a more efficient way to set pixels than the default
+ * implementation of the super class. It copies the pixel components directly
+ * from the input array instead of creating a intermediate buffer.
+ * @param x The x-coordinate of the pixel rectangle in <code>obj</code>.
+ * @param y The y-coordinate of the pixel rectangle in <code>obj</code>.
+ * @param w The width of the pixel rectangle in <code>obj</code>.
+ * @param h The height of the pixel rectangle in <code>obj</code>.
+ * @param iArray The primitive array containing the pixels to set.
+ * @param data The DataBuffer to store the pixels into.
+ * @see java.awt.image.SampleModel#setPixels(int, int, int, int, int[],
+ * java.awt.image.DataBuffer)
+ */
+ public void setPixels(int x, int y, int w, int h, int[] iArray,
+ DataBuffer data)
+ {
+ int inOffset = 0;
+ for (int yy=y; yy<(y+h); yy++)
+ {
+ int offset = scanlineStride*yy + x;
+ for (int xx=x; xx<(x+w); xx++)
+ {
+ int samples = 0;
+ for (int b = 0; b < numBands; b++)
+ samples |= (iArray[inOffset+b] << bitOffsets[b]) & bitMasks[b];
+ data.setElem(0, offset, samples);
+ inOffset += numBands;
+ offset += 1;
+ }
+ }
+ }
+
+ /**
+ * Sets the sample value for a band for the pixel at (x, y) in the
+ * specified data buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param s the sample value.
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
+ public void setSample(int x, int y, int b, int s, DataBuffer data)
+ {
+ int offset = scanlineStride*y + x;
+ int samples = data.getElem(offset);
+ int bitMask = bitMasks[b];
+ samples &= ~bitMask;
+ samples |= (s << bitOffsets[b]) & bitMask;
+ data.setElem(offset, samples);
+ }
+
+ /**
+ * Tests this sample model for equality with an arbitrary object. This
+ * method returns <code>true</code> if and only if:
+ * <ul>
+ * <li><code>obj</code> is not <code>null</code>;
+ * <li><code>obj</code> is an instance of
+ * <code>SinglePixelPackedSampleModel</code>;
+ * <li>both models have the same:
+ * <ul>
+ * <li><code>dataType</code>;
+ * <li><code>width</code>;
+ * <li><code>height</code>;
+ * <li><code>numBands</code>;
+ * <li><code>scanlineStride</code>;
+ * <li><code>bitMasks</code>;
+ * <li><code>bitOffsets</code>.
+ * </ul>
+ * </li>
+ * </ul>
+ *
+ * @param obj the object (<code>null</code> permitted)
+ *
+ * @return <code>true</code> if this model is equal to <code>obj</code>, and
+ * <code>false</code> otherwise.
+ */
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ return true;
+ if (! (obj instanceof SinglePixelPackedSampleModel))
+ return false;
+ SinglePixelPackedSampleModel that = (SinglePixelPackedSampleModel) obj;
+ if (this.dataType != that.dataType)
+ return false;
+ if (this.width != that.width)
+ return false;
+ if (this.height != that.height)
+ return false;
+ if (this.numBands != that.numBands)
+ return false;
+ if (this.scanlineStride != that.scanlineStride)
+ return false;
+ if (!Arrays.equals(this.bitMasks, that.bitMasks))
+ return false;
+ if (!Arrays.equals(this.bitOffsets, that.bitOffsets))
+ return false;
+ return true;
+ }
+
+ /**
+ * Returns a hash code for this <code>SinglePixelPackedSampleModel</code>.
+ *
+ * @return A hash code.
+ */
+ public int hashCode()
+ {
+ // this hash code won't match Sun's, but that shouldn't matter...
+ int result = 193;
+ result = 37 * result + dataType;
+ result = 37 * result + width;
+ result = 37 * result + height;
+ result = 37 * result + numBands;
+ result = 37 * result + scanlineStride;
+ for (int i = 0; i < bitMasks.length; i++)
+ result = 37 * result + bitMasks[i];
+ for (int i = 0; i < bitOffsets.length; i++)
+ result = 37 * result + bitOffsets[i];
+ return result;
+ }
+
+ /**
+ * Creates a String with some information about this SampleModel.
+ * @return A String describing this SampleModel.
+ * @see java.lang.Object#toString()
+ */
+ public String toString()
+ {
+ CPStringBuilder result = new CPStringBuilder();
+ result.append(getClass().getName());
+ result.append("[");
+ result.append("scanlineStride=").append(scanlineStride);
+ for(int i = 0; i < bitMasks.length; i+=1)
+ {
+ result.append(", mask[").append(i).append("]=0x").append(
+ Integer.toHexString(bitMasks[i]));
+ }
+
+ result.append("]");
+ return result.toString();
+ }
+}
diff --git a/libjava/classpath/java/awt/image/TileObserver.java b/libjava/classpath/java/awt/image/TileObserver.java
new file mode 100644
index 000000000..769888e40
--- /dev/null
+++ b/libjava/classpath/java/awt/image/TileObserver.java
@@ -0,0 +1,47 @@
+/* TileObserver.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+/**
+ * NEEDS DOCUMENTATION
+ */
+public interface TileObserver
+{
+ void tileUpdate(WritableRenderedImage src, int x, int y, boolean writable);
+} // interface TileObserver
diff --git a/libjava/classpath/java/awt/image/VolatileImage.java b/libjava/classpath/java/awt/image/VolatileImage.java
new file mode 100644
index 000000000..308654162
--- /dev/null
+++ b/libjava/classpath/java/awt/image/VolatileImage.java
@@ -0,0 +1,253 @@
+/* VolatileImage.java -- a hardware-accelerated image buffer
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.Image;
+import java.awt.Transparency;
+import java.awt.ImageCapabilities;
+
+/**
+ * VolatileImage represents a hardware-accelerated graphics buffer.
+ * The native graphics system may free or damage the resources
+ * occupied by a VolatileImage at any time. As such, one must
+ * frequently check the "validity" of the image buffer's resources.
+ *
+ * A volatile image's "validity" depends on multiple factors. Its
+ * resources may have become unavailble in which case you must
+ * reallocate them. If you move the image from one output device to
+ * another, you may need to recreate the image's resources if the new
+ * output device's capabilities don't match the old one's. Finally,
+ * if the contents of the image's buffer have been damaged you must
+ * re-render the image.
+ *
+ * VolatileImages should always be created using either
+ * Component.createVolatileImage or
+ * GraphicsConfiguration.createCompatibleVolatileImage.
+ */
+public abstract class VolatileImage extends Image
+ implements Transparency
+{
+ /**
+ * One of validate's possible return values. Indicates that the
+ * image buffer matches its graphics configuration's capabilities
+ * and that its resources are initialized and ready to be drawn
+ * into. Also implies that any existing image rendered to the
+ * buffer is intact and need not be re-rendered.
+ */
+ public static final int IMAGE_OK = 0;
+
+ /**
+ * One of validate's possible return values. Indicates that the
+ * image buffer has been restored, meaning that it is valid and
+ * ready-to-use but that its previous contents have been lost. This
+ * return value implies that the image needs to be re-rendered.
+ */
+ public static final int IMAGE_RESTORED = 1;
+
+ /**
+ * One of validate's possible return values. Indicates that the
+ * image buffer type is unsupported by the current graphics
+ * configuration. The graphics configuration may have changed, for
+ * example if the image moved from one output device to another.
+ * This return value implies that the image buffer's resources
+ * should be re-acquired.
+ */
+ public static final int IMAGE_INCOMPATIBLE = 2;
+
+ /**
+ * This image's transparency type. One of Transparency.BITMASK,
+ * Transparency.OPAQUE or Transparency.TRANSLUCENT.
+ *
+ * @since 1.5
+ */
+ protected int transparency;
+
+ /**
+ * Default constructor. VolatileImages should not be created
+ * directly. Rather, you should use Component.createVolatileImage
+ * or GraphicsConfiguration.createCompatibleVolatileImage.
+ */
+ public VolatileImage()
+ {
+ }
+
+ /**
+ * Returns an image representing the current state of the volatile
+ * image buffer. The returned image is static meaning that it is
+ * not updated after being created. It is a snapshot of the
+ * volatile image buffer at the time getSnapshot is called.
+ *
+ * This method, which reads pixels from the volatile image buffer,
+ * may be less-performant than methods that write pixels since
+ * VolatileImages are typically optimized for writing.
+ *
+ * @return a BufferedImage representing this VolatileImage
+ */
+ public abstract BufferedImage getSnapshot();
+
+ /**
+ * Returns the width of this image buffer.
+ *
+ * @return the width of this VolatileImage
+ */
+ public abstract int getWidth();
+
+ /**
+ * Returns the height of this image buffer.
+ *
+ * @return the height of this VolatileImage
+ */
+ public abstract int getHeight();
+
+ /**
+ * Calling this method is equivalent to calling
+ * getSnapshot().getSource(). The ImageProducer produces pixels
+ * from the BufferedImage snapshot and not from the VolatileImage
+ * itself. Thus, changes to the VolatileImage that occur after this
+ * ImageProducer has been retrieved will not be reflected in the
+ * produced pixels.
+ *
+ * This method, which reads pixels from the volatile image buffer,
+ * may be less-performant than methods that write pixels since
+ * VolatileImages are typically optimized for writing.
+ *
+ * @return an ImageProducer for a static BufferedImage snapshot of
+ * this image buffer
+ */
+ public ImageProducer getSource()
+ {
+ return getSnapshot().getSource();
+ }
+
+ /**
+ * Releases the system resources taken by this image.
+ */
+ public void flush()
+ {
+ }
+
+ /**
+ * Returns a Graphics2D object that can be used to draw onto this
+ * image. This method is present for backwards-compatibility. It
+ * simply returns the result of createGraphics.
+ *
+ * @return a Graphics2D object that can be used to draw onto this
+ * image
+ */
+ public Graphics getGraphics()
+ {
+ return createGraphics();
+ }
+
+ /**
+ * Returns a Graphics2D object that can be used to draw onto this
+ * image.
+ *
+ * @return a Graphics2D object that can be used to draw onto this
+ * image
+ */
+ public abstract Graphics2D createGraphics();
+
+ /**
+ * Validates and restores this image. If the image buffer has
+ * become unavailable for further use since the last call to
+ * validate, validate will allocate a new image buffer. The image
+ * is also "validated" against the GraphicsConfiguration parameter.
+ *
+ * "Validating" the image means checking that the capabilities it
+ * requires of the output device are indeed supported by the given
+ * output device. If the image's characteristics, which can be
+ * highly output device-specific, are not supported by the graphics
+ * configuration, then IMAGE_INCOMPATIBLE will be returned. This
+ * can happen, for example, if this image was created on one output
+ * device, then validated against a different output device with
+ * different capabilities. Calling validate with a NULL gc argument
+ * causes validate to skip the validation test.
+ *
+ * @param gc graphics configuration against which to validate or
+ * NULL
+ *
+ * @return a code indicating the result of validation. One of:
+ * <ul>
+ * <li><code>IMAGE_OK</code> if the image did not need to be
+ * validated and didn't need to be restored</li>
+ * <li><code>IMAGE_RESTORED</code> if the image may need to be
+ * re-rendered.</li>
+ * <li><code>IMAGE_INCOMPATIBLE</code> if this image's
+ * requirements are not fulfilled by the graphics configuration
+ * parameter. This implies that you need to create a new
+ * VolatileImage for the different GraphicsConfiguration or
+ * Component. This return value implies nothing about whether the
+ * image is valid or needs to be re-rendered.</li>
+ * </ul>
+ */
+ public abstract int validate(GraphicsConfiguration gc);
+
+ /**
+ * Returns true if the contents of the image buffer have been
+ * damaged or if the image buffer's resources have been reclaimed by
+ * the graphics system. You should call this method after a series
+ * of rendering operations to or from the image, to see if the image
+ * buffer needs to be revalidated or the image re-rendered.
+ *
+ * @return true if the validate should be called, false otherwise
+ */
+ public abstract boolean contentsLost();
+
+ /**
+ * Returns the capabilities of this image buffer.
+ *
+ * @return the capabilities of this image buffer
+ */
+ public abstract ImageCapabilities getCapabilities();
+
+ /**
+ * Returns the transparency type of this image.
+ *
+ * @return Transparency.OPAQUE, Transparency.BITMASK or
+ * Transparency.TRANSLUCENT
+ */
+ public int getTransparency()
+ {
+ return transparency;
+ }
+}
diff --git a/libjava/classpath/java/awt/image/WritableRaster.java b/libjava/classpath/java/awt/image/WritableRaster.java
new file mode 100644
index 000000000..68774f785
--- /dev/null
+++ b/libjava/classpath/java/awt/image/WritableRaster.java
@@ -0,0 +1,448 @@
+/* Copyright (C) 2000, 2002, 2003, 2006, Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+
+/**
+ * A raster with methods to support updating pixel values.
+ *
+ * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
+ */
+public class WritableRaster extends Raster
+{
+ /**
+ * Creates a new <code>WritableRaster</code>.
+ *
+ * @param sampleModel the sample model.
+ * @param origin the origin.
+ */
+ protected WritableRaster(SampleModel sampleModel, Point origin)
+ {
+ this(sampleModel, sampleModel.createDataBuffer(), origin);
+ }
+
+ /**
+ * Creates a new <code>WritableRaster</code> instance.
+ *
+ * @param sampleModel the sample model.
+ * @param dataBuffer the data buffer.
+ * @param origin the origin.
+ */
+ protected WritableRaster(SampleModel sampleModel, DataBuffer dataBuffer,
+ Point origin)
+ {
+ this(sampleModel, dataBuffer,
+ new Rectangle(origin != null ? origin.x : 0,
+ origin != null ? origin.y : 0,
+ sampleModel.getWidth(), sampleModel.getHeight()),
+ origin, null);
+ }
+
+ /**
+ * Creates a new <code>WritableRaster</code> instance.
+ *
+ * @param sampleModel the sample model.
+ * @param dataBuffer the data buffer.
+ * @param aRegion the raster's bounds.
+ * @param sampleModelTranslate the translation.
+ * @param parent the parent.
+ */
+ protected WritableRaster(SampleModel sampleModel,
+ DataBuffer dataBuffer,
+ Rectangle aRegion,
+ Point sampleModelTranslate,
+ WritableRaster parent)
+ {
+ super(sampleModel, dataBuffer, aRegion, sampleModelTranslate, parent);
+ }
+
+ /**
+ * Returns the raster's parent, cast as a {@link WritableRaster}.
+ *
+ * @return The raster's parent.
+ */
+ public WritableRaster getWritableParent()
+ {
+ return (WritableRaster) getParent();
+ }
+
+ /**
+ * @param childMinX
+ * @param childMinY
+ * @return
+ */
+ public WritableRaster createWritableTranslatedChild(int childMinX,
+ int childMinY)
+ {
+ return createWritableChild(minX, minY, width, height,
+ childMinX, childMinY, null);
+ }
+
+ /**
+ *
+ * @param parentX
+ * @param parentY
+ * @param w
+ * @param h
+ * @param childMinX
+ * @param childMinY
+ * @param bandList
+ * @return
+ */
+ public WritableRaster createWritableChild(int parentX, int parentY,
+ int w, int h, int childMinX, int childMinY, int[] bandList)
+ {
+ // This mirrors the code from the super class
+
+ if (parentX < minX || parentX + w > minX + width
+ || parentY < minY || parentY + h > minY + height)
+ throw new RasterFormatException("Child raster extends beyond parent");
+
+ SampleModel sm = (bandList == null) ?
+ sampleModel :
+ sampleModel.createSubsetSampleModel(bandList);
+
+ return new WritableRaster(sm, getDataBuffer(),
+ new Rectangle(childMinX, childMinY, w, h),
+ new Point(sampleModelTranslateX + childMinX -
+ parentX,
+ sampleModelTranslateY + childMinY -
+ parentY),
+ this);
+ }
+
+ public Raster createChild(int parentX, int parentY, int width,
+ int height, int childMinX, int childMinY,
+ int[] bandList)
+ {
+ if (parentX < minX || parentX + width > minX + this.width
+ || parentY < minY || parentY + height > minY + this.height)
+ throw new RasterFormatException("Child raster extends beyond parent");
+
+ SampleModel sm = (bandList == null) ?
+ sampleModel :
+ sampleModel.createSubsetSampleModel(bandList);
+
+ return new WritableRaster(sm, dataBuffer,
+ new Rectangle(childMinX, childMinY, width, height),
+ new Point(sampleModelTranslateX + childMinX - parentX,
+ sampleModelTranslateY + childMinY - parentY),
+ this);
+ }
+
+ public void setDataElements(int x, int y, Object inData)
+ {
+ sampleModel.setDataElements(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, inData, dataBuffer);
+ }
+
+ public void setDataElements(int x, int y, Raster inRaster)
+ {
+ Object dataElements = getDataElements(0, 0, inRaster.getWidth(),
+ inRaster.getHeight(), null);
+ setDataElements(x, y, dataElements);
+ }
+
+ public void setDataElements(int x, int y, int w, int h, Object inData)
+ {
+ sampleModel.setDataElements(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, w, h, inData, dataBuffer);
+ }
+
+ /**
+ *
+ * @param srcRaster
+ */
+ public void setRect(Raster srcRaster)
+ {
+ setRect(0, 0, srcRaster);
+ }
+
+ /**
+ *
+ * @param dx
+ * @param dy
+ * @param srcRaster
+ */
+ public void setRect(int dx, int dy, Raster srcRaster)
+ {
+ Rectangle targetUnclipped = new Rectangle(srcRaster.getMinX() + dx,
+ srcRaster.getMinY() + dy, srcRaster.getWidth(), srcRaster.getHeight());
+
+ Rectangle target = getBounds().intersection(targetUnclipped);
+
+ if (target.isEmpty()) return;
+
+ int sx = target.x - dx;
+ int sy = target.y - dy;
+
+ // FIXME: Do tests on rasters and use get/set data instead.
+
+ /* The JDK documentation seems to imply this implementation.
+ (the trucation of higher bits), but an implementation using
+ get/setDataElements would be more efficient. None of the
+ implementations would do anything sensible when the sample
+ models don't match.
+
+ But this is probably not the place to consider such
+ optimizations.*/
+
+ int[] pixels = srcRaster.getPixels(sx, sy, target.width, target.height,
+ (int[]) null);
+
+ setPixels(target.x, target.y, target.width, target.height, pixels);
+ }
+
+ /**
+ * Sets the samples for the pixel at (x, y) in the raster to the specified
+ * values.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param iArray the sample values (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>iArray</code> is <code>null</code>.
+ */
+ public void setPixel(int x, int y, int[] iArray)
+ {
+ sampleModel.setPixel(x - sampleModelTranslateX, y - sampleModelTranslateY,
+ iArray, dataBuffer);
+ }
+
+ /**
+ * Sets the samples for the pixel at (x, y) in the raster to the specified
+ * values.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param fArray the sample values (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>fArray</code> is <code>null</code>.
+ */
+ public void setPixel(int x, int y, float[] fArray)
+ {
+ sampleModel.setPixel(x - sampleModelTranslateX, y - sampleModelTranslateY,
+ fArray, dataBuffer);
+ }
+
+ /**
+ * Sets the samples for the pixel at (x, y) in the raster to the specified
+ * values.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param dArray the sample values (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>dArray</code> is <code>null</code>.
+ */
+ public void setPixel(int x, int y, double[] dArray)
+ {
+ sampleModel.setPixel(x - sampleModelTranslateX, y - sampleModelTranslateY,
+ dArray, dataBuffer);
+ }
+
+ /**
+ * Sets the sample values for the pixels in the region specified by
+ * (x, y, w, h) in the raster. The array is ordered by pixels (that is, all
+ * the samples for the first pixel are grouped together, followed by all the
+ * samples for the second pixel, and so on).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param iArray the pixel sample values (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>iArray</code> is <code>null</code>.
+ */
+ public void setPixels(int x, int y, int w, int h, int[] iArray)
+ {
+ sampleModel.setPixels(x - sampleModelTranslateX, y - sampleModelTranslateY,
+ w, h, iArray, dataBuffer);
+ }
+
+ /**
+ * Sets the sample values for the pixels in the region specified by
+ * (x, y, w, h) in the raster. The array is ordered by pixels (that is, all
+ * the samples for the first pixel are grouped together, followed by all the
+ * samples for the second pixel, and so on).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param fArray the pixel sample values (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>fArray</code> is <code>null</code>.
+ */
+ public void setPixels(int x, int y, int w, int h, float[] fArray)
+ {
+ sampleModel.setPixels(x - sampleModelTranslateX, y - sampleModelTranslateY,
+ w, h, fArray, dataBuffer);
+ }
+
+ /**
+ * Sets the sample values for the pixels in the region specified by
+ * (x, y, w, h) in the raster. The array is ordered by pixels (that is, all
+ * the samples for the first pixel are grouped together, followed by all the
+ * samples for the second pixel, and so on).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param dArray the pixel sample values (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>dArray</code> is <code>null</code>.
+ */
+ public void setPixels(int x, int y, int w, int h, double[] dArray)
+ {
+ sampleModel.setPixels(x - sampleModelTranslateX, y - sampleModelTranslateY,
+ w, h, dArray, dataBuffer);
+ }
+
+ /**
+ * Sets the sample value for a band for the pixel at (x, y) in the raster.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param s the sample value.
+ */
+ public void setSample(int x, int y, int b, int s)
+ {
+ sampleModel.setSample(x - sampleModelTranslateX, y - sampleModelTranslateY,
+ b, s, dataBuffer);
+ }
+
+ /**
+ * Sets the sample value for a band for the pixel at (x, y) in the raster.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param s the sample value.
+ */
+ public void setSample(int x, int y, int b, float s)
+ {
+ sampleModel.setSample(x - sampleModelTranslateX, y - sampleModelTranslateY,
+ b, s, dataBuffer);
+ }
+
+ /**
+ * Sets the sample value for a band for the pixel at (x, y) in the raster.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param s the sample value.
+ */
+ public void setSample(int x, int y, int b, double s)
+ {
+ sampleModel.setSample(x - sampleModelTranslateX, y - sampleModelTranslateY,
+ b, s, dataBuffer);
+ }
+
+ /**
+ * Sets the sample values for one band for the pixels in the region
+ * specified by (x, y, w, h) in the raster.
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param b the band (in the range <code>0</code> to
+ * </code>getNumBands() - 1</code>).
+ * @param iArray the sample values (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>iArray</code> is <code>null</code>.
+ */
+ public void setSamples(int x, int y, int w, int h, int b,
+ int[] iArray)
+ {
+ sampleModel.setSamples(x - sampleModelTranslateX, y - sampleModelTranslateY,
+ w, h, b, iArray, dataBuffer);
+ }
+
+ /**
+ * Sets the sample values for one band for the pixels in the region
+ * specified by (x, y, w, h) in the raster.
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param b the band (in the range <code>0</code> to
+ * </code>getNumBands() - 1</code>).
+ * @param fArray the sample values (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>fArray</code> is <code>null</code>.
+ */
+ public void setSamples(int x, int y, int w, int h, int b,
+ float[] fArray)
+ {
+ sampleModel.setSamples(x - sampleModelTranslateX, y - sampleModelTranslateY,
+ w, h, b, fArray, dataBuffer);
+ }
+
+ /**
+ * Sets the sample values for one band for the pixels in the region
+ * specified by (x, y, w, h) in the raster.
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param b the band (in the range <code>0</code> to
+ * </code>getNumBands() - 1</code>).
+ * @param dArray the sample values (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>dArray</code> is <code>null</code>.
+ */
+ public void setSamples(int x, int y, int w, int h, int b,
+ double[] dArray)
+ {
+ sampleModel.setSamples(x - sampleModelTranslateX, y - sampleModelTranslateY,
+ w, h, b, dArray, dataBuffer);
+ }
+}
diff --git a/libjava/classpath/java/awt/image/WritableRenderedImage.java b/libjava/classpath/java/awt/image/WritableRenderedImage.java
new file mode 100644
index 000000000..9142fe004
--- /dev/null
+++ b/libjava/classpath/java/awt/image/WritableRenderedImage.java
@@ -0,0 +1,56 @@
+/* WritableRenderedImage.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image;
+
+import java.awt.Point;
+
+/**
+ * NEEDS DOCUMENTATION
+ */
+public interface WritableRenderedImage extends RenderedImage
+{
+ void addTileObserver(TileObserver to);
+ void removeTileObserver(TileObserver to);
+ WritableRaster getWritableTile(int x, int y);
+ void releaseWritableTile(int x, int y);
+ boolean isTileWritable(int x, int y);
+ Point[] getWritableTileIndices();
+ boolean hasTileWriters();
+ void setData(Raster r);
+} // interface WritableRenderedImage
diff --git a/libjava/classpath/java/awt/image/package.html b/libjava/classpath/java/awt/image/package.html
new file mode 100644
index 000000000..50fa99d13
--- /dev/null
+++ b/libjava/classpath/java/awt/image/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt.image package.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - java.awt.image</title></head>
+
+<body>
+<p>Image consumers, producers and filters.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/image/renderable/ContextualRenderedImageFactory.java b/libjava/classpath/java/awt/image/renderable/ContextualRenderedImageFactory.java
new file mode 100644
index 000000000..8852bef1c
--- /dev/null
+++ b/libjava/classpath/java/awt/image/renderable/ContextualRenderedImageFactory.java
@@ -0,0 +1,56 @@
+/* ContextualRenderedImageFactory.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image.renderable;
+
+import java.awt.geom.Rectangle2D;
+import java.awt.image.RenderedImage;
+
+/**
+ * STUBBED
+ */
+public interface ContextualRenderedImageFactory extends RenderedImageFactory
+{
+ RenderContext mapRenderContext(int i, RenderContext context,
+ ParameterBlock block, RenderableImage image);
+ RenderedImage create(RenderContext context, ParameterBlock block);
+ Rectangle2D getBounds2D(ParameterBlock block);
+ Object getProperty(ParameterBlock block, String name);
+ String[] getPropertyNames();
+ boolean isDynamic();
+} // interface ContextualRenderedImageFactory
diff --git a/libjava/classpath/java/awt/image/renderable/ParameterBlock.java b/libjava/classpath/java/awt/image/renderable/ParameterBlock.java
new file mode 100644
index 000000000..f38077816
--- /dev/null
+++ b/libjava/classpath/java/awt/image/renderable/ParameterBlock.java
@@ -0,0 +1,308 @@
+/* ParameterBlock.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image.renderable;
+
+import java.awt.image.RenderedImage;
+import java.io.Serializable;
+import java.util.Vector;
+
+public class ParameterBlock implements Cloneable, Serializable
+{
+ private static final long serialVersionUID = -7577115551785240750L;
+ protected Vector<Object> sources;
+ protected Vector<Object> parameters;
+
+ public ParameterBlock()
+ {
+ this(new Vector<Object>(), new Vector<Object>());
+ }
+
+ public ParameterBlock(Vector<Object> sources)
+ {
+ this(sources, new Vector<Object>());
+ }
+
+ public ParameterBlock(Vector<Object> sources, Vector<Object> parameters)
+ {
+ this.sources = sources;
+ this.parameters = parameters;
+ }
+
+ public Object shallowClone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // impossible
+ }
+ }
+
+ public Object clone()
+ {
+ ParameterBlock pb = (ParameterBlock) shallowClone();
+ if (sources != null)
+ pb.sources = (Vector<Object>) sources.clone();
+ if (parameters != null)
+ pb.parameters = (Vector<Object>) parameters.clone();
+ return pb;
+ }
+
+ public ParameterBlock addSource(Object source)
+ {
+ sources.add(source);
+ return this;
+ }
+
+ public Object getSource(int index)
+ {
+ return sources.get(index);
+ }
+
+ public ParameterBlock setSource(Object source, int index)
+ {
+ sources.ensureCapacity(index);
+ sources.set(index, source);
+ return this;
+ }
+
+ public RenderedImage getRenderedSource(int index)
+ {
+ return (RenderedImage) sources.get(index);
+ }
+
+ public RenderableImage getRenderableSource(int index)
+ {
+ return (RenderableImage) sources.get(index);
+ }
+
+ public int getNumSources()
+ {
+ return sources.size();
+ }
+
+ public Vector<Object> getSources()
+ {
+ return sources;
+ }
+
+ public void setSources(Vector<Object> sources)
+ {
+ this.sources = sources;
+ }
+
+ public void removeSources()
+ {
+ if (sources != null)
+ sources.clear();
+ }
+
+ public int getNumParameters()
+ {
+ return parameters.size();
+ }
+
+ public Vector<Object> getParameters()
+ {
+ return parameters;
+ }
+
+ public void setParameters(Vector<Object> parameters)
+ {
+ this.parameters = parameters;
+ }
+
+ public void removeParameters()
+ {
+ if (parameters != null)
+ parameters.clear();
+ }
+
+ public ParameterBlock add(Object o)
+ {
+ parameters.add(o);
+ return this;
+ }
+
+ public ParameterBlock add(byte b)
+ {
+ return add(new Byte(b));
+ }
+
+ public ParameterBlock add(char c)
+ {
+ return add(new Character(c));
+ }
+
+ public ParameterBlock add(short s)
+ {
+ return add(new Short(s));
+ }
+
+ public ParameterBlock add(int i)
+ {
+ return add(new Integer(i));
+ }
+
+ public ParameterBlock add(long l)
+ {
+ return add(new Long(l));
+ }
+
+ public ParameterBlock add(float f)
+ {
+ return add(new Float(f));
+ }
+
+ public ParameterBlock add(double d)
+ {
+ return add(new Double(d));
+ }
+
+ public ParameterBlock set(Object o, int index)
+ {
+ parameters.ensureCapacity(index);
+ parameters.set(index, o);
+ return this;
+ }
+
+ public ParameterBlock set(byte b, int index)
+ {
+ return set(new Byte(b), index);
+ }
+
+ public ParameterBlock set(char c, int index)
+ {
+ return set(new Character(c), index);
+ }
+
+ public ParameterBlock set(short s, int index)
+ {
+ return set(new Short(s), index);
+ }
+
+ public ParameterBlock set(int i, int index)
+ {
+ return set(new Integer(i), index);
+ }
+
+ public ParameterBlock set(long l, int index)
+ {
+ return set(new Long(l), index);
+ }
+
+ public ParameterBlock set(float f, int index)
+ {
+ return set(new Float(f), index);
+ }
+
+ public ParameterBlock set(double d, int index)
+ {
+ return set(new Double(d), index);
+ }
+
+ public Object getObjectParameter(int index)
+ {
+ return parameters.get(index);
+ }
+
+ public byte getByteParameter(int index)
+ {
+ return ((Byte) parameters.get(index)).byteValue();
+ }
+
+ public char getCharParameter(int index)
+ {
+ return ((Character) parameters.get(index)).charValue();
+ }
+
+ public short getShortParameter(int index)
+ {
+ return ((Short) parameters.get(index)).shortValue();
+ }
+
+ public int getIntParameter(int index)
+ {
+ return ((Integer) parameters.get(index)).intValue();
+ }
+
+ public long getLongParameter(int index)
+ {
+ return ((Long) parameters.get(index)).longValue();
+ }
+
+ public float getFloatParameter(int index)
+ {
+ return ((Float) parameters.get(index)).floatValue();
+ }
+
+ public double getDoubleParameter(int index)
+ {
+ return ((Double) parameters.get(index)).doubleValue();
+ }
+
+ public Class[] getParamClasses()
+ {
+ int i = parameters.size();
+ Class[] result = new Class[i];
+ while (--i >= 0)
+ {
+ Class c = parameters.get(i).getClass();
+ if (c == Byte.class)
+ result[i] = byte.class;
+ else if (c == Character.class)
+ result[i] = char.class;
+ else if (c == Short.class)
+ result[i] = short.class;
+ else if (c == Integer.class)
+ result[i] = int.class;
+ else if (c == Long.class)
+ result[i] = long.class;
+ else if (c == Float.class)
+ result[i] = float.class;
+ else if (c == Double.class)
+ result[i] = double.class;
+ else
+ result[i] = c;
+ }
+ return result;
+ }
+} // class ParameterBlock
diff --git a/libjava/classpath/java/awt/image/renderable/RenderContext.java b/libjava/classpath/java/awt/image/renderable/RenderContext.java
new file mode 100644
index 000000000..8017c1acf
--- /dev/null
+++ b/libjava/classpath/java/awt/image/renderable/RenderContext.java
@@ -0,0 +1,141 @@
+/* RenderContext.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image.renderable;
+
+import java.awt.RenderingHints;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+
+public class RenderContext implements Cloneable
+{
+ private AffineTransform xform;
+ private Shape aoi;
+ private RenderingHints hints;
+
+ public RenderContext(AffineTransform xform, Shape aoi, RenderingHints hints)
+ {
+ this.xform = xform;
+ this.aoi = aoi;
+ this.hints = hints;
+ }
+
+ public RenderContext(AffineTransform xform)
+ {
+ this(xform, null, null);
+ }
+
+ public RenderContext(AffineTransform xform, RenderingHints hints)
+ {
+ this(xform, null, hints);
+ }
+
+ public RenderContext(AffineTransform xform, Shape aoi)
+ {
+ this(xform, aoi, null);
+ }
+
+ public RenderingHints getRenderingHints()
+ {
+ return hints;
+ }
+
+ public void setRenderingHints(RenderingHints hints)
+ {
+ this.hints = hints;
+ }
+
+ public void setTransform(AffineTransform xform)
+ {
+ this.xform = xform;
+ }
+
+ public void preConcatenateTransform(AffineTransform pre)
+ {
+ preConcetenateTransform (pre);
+ }
+
+ /** @deprecated */
+ public void preConcetenateTransform(AffineTransform pre)
+ {
+ xform.preConcatenate (pre);
+ }
+
+ public void concatenateTransform(AffineTransform post)
+ {
+ concetenateTransform (post);
+ }
+
+ /** @deprecated */
+ public void concetenateTransform(AffineTransform post)
+ {
+ xform.concatenate (post);
+ }
+
+ public AffineTransform getTransform()
+ {
+ return xform;
+ }
+
+ public void setAreaOfInterest(Shape aoi)
+ {
+ this.aoi = aoi;
+ }
+
+ public Shape getAreaOfInterest()
+ {
+ return aoi;
+ }
+
+ public Object clone()
+ {
+ try
+ {
+ RenderContext copy = (RenderContext) super.clone();
+ if (xform != null)
+ copy.xform = (AffineTransform) xform.clone();
+ if (hints != null)
+ copy.hints = (RenderingHints) hints.clone();
+ return copy;
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // impossible
+ }
+ }
+} // class RenderContext
diff --git a/libjava/classpath/java/awt/image/renderable/RenderableImage.java b/libjava/classpath/java/awt/image/renderable/RenderableImage.java
new file mode 100644
index 000000000..31767af2c
--- /dev/null
+++ b/libjava/classpath/java/awt/image/renderable/RenderableImage.java
@@ -0,0 +1,61 @@
+/* RenderableImage.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image.renderable;
+
+import java.awt.RenderingHints;
+import java.awt.image.RenderedImage;
+import java.util.Vector;
+
+public interface RenderableImage
+{
+ String HINTS_OBSERVED = "HINTS_OBSERVED";
+
+ Vector<RenderableImage> getSources();
+ Object getProperty(String name);
+ String[] getPropertyNames();
+ boolean isDynamic();
+ float getWidth();
+ float getHeight();
+ float getMinX();
+ float getMinY();
+ RenderedImage createScaledRendering(int w, int h, RenderingHints hints);
+ RenderedImage createDefaultRendering();
+ RenderedImage createRendering(RenderContext context);
+
+} // interface RenderableImage
diff --git a/libjava/classpath/java/awt/image/renderable/RenderableImageOp.java b/libjava/classpath/java/awt/image/renderable/RenderableImageOp.java
new file mode 100644
index 000000000..81e537cd5
--- /dev/null
+++ b/libjava/classpath/java/awt/image/renderable/RenderableImageOp.java
@@ -0,0 +1,157 @@
+/* RenderableImageOp.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image.renderable;
+
+import java.awt.RenderingHints;
+import java.awt.geom.AffineTransform;
+import java.awt.image.RenderedImage;
+import java.util.Vector;
+
+public class RenderableImageOp implements RenderableImage
+{
+ private final ContextualRenderedImageFactory crif;
+ private ParameterBlock block;
+
+ public RenderableImageOp(ContextualRenderedImageFactory crif,
+ ParameterBlock block)
+ {
+ this.crif = crif;
+ this.block = (ParameterBlock) block.clone();
+ }
+
+ public Vector<RenderableImage> getSources()
+ {
+ if (block.sources == null)
+ return null;
+ int size = block.sources.size();
+ Vector v = new Vector();
+ for (int i = 0; i < size; i++)
+ {
+ Object o = block.sources.get(i);
+ if (o instanceof RenderableImage)
+ v.add(o);
+ }
+ return v;
+ }
+
+ public Object getProperty(String name)
+ {
+ return crif.getProperty(block, name);
+ }
+
+ public String[] getPropertyNames()
+ {
+ return crif.getPropertyNames();
+ }
+
+ public boolean isDynamic()
+ {
+ return crif.isDynamic();
+ }
+
+ public float getWidth()
+ {
+ return (float) crif.getBounds2D(block).getWidth();
+ }
+
+ public float getHeight()
+ {
+ return (float) crif.getBounds2D(block).getHeight();
+ }
+
+ public float getMinX()
+ {
+ return (float) crif.getBounds2D(block).getX();
+ }
+
+ public float getMinY()
+ {
+ return (float) crif.getBounds2D(block).getY();
+ }
+
+ public ParameterBlock setParameterBlock(ParameterBlock block)
+ {
+ ParameterBlock result = this.block;
+ this.block = (ParameterBlock) block.clone();
+ return result;
+ }
+
+ public ParameterBlock getParameterBlock()
+ {
+ return block;
+ }
+
+ public RenderedImage createScaledRendering(int w, int h,
+ RenderingHints hints)
+ {
+ if (w == 0)
+ if (h == 0)
+ throw new IllegalArgumentException();
+ else
+ w = Math.round(h * getWidth() / getHeight());
+ if (h == 0)
+ h = Math.round(w * getHeight() / getWidth());
+ AffineTransform xform = AffineTransform.getScaleInstance(w * getWidth(),
+ h * getHeight());
+ return createRendering(new RenderContext(xform, hints));
+ }
+
+ public RenderedImage createDefaultRendering()
+ {
+ return createRendering(new RenderContext(new AffineTransform()));
+ }
+
+ public RenderedImage createRendering(RenderContext context)
+ {
+ ParameterBlock copy = (ParameterBlock) block.clone();
+ int i = block.sources.size();
+ while (--i >= 0)
+ {
+ Object o = block.sources.get(i);
+ if (o instanceof RenderableImage)
+ {
+ RenderableImage ri = (RenderableImage) o;
+ RenderContext rc = crif.mapRenderContext(i, context, block, ri);
+ copy.sources.set(i, ri.createRendering(rc));
+ }
+ }
+ // Now copy.sources should be only RenderedImages.
+ return crif.create(context, copy);
+ }
+} // class RenderableImageOp
diff --git a/libjava/classpath/java/awt/image/renderable/RenderableImageProducer.java b/libjava/classpath/java/awt/image/renderable/RenderableImageProducer.java
new file mode 100644
index 000000000..bd3b507cb
--- /dev/null
+++ b/libjava/classpath/java/awt/image/renderable/RenderableImageProducer.java
@@ -0,0 +1,166 @@
+/* RenderableImageProducer.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image.renderable;
+
+import java.awt.image.ColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.ImageConsumer;
+import java.awt.image.ImageProducer;
+import java.awt.image.Raster;
+import java.awt.image.RenderedImage;
+import java.awt.image.SampleModel;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+public class RenderableImageProducer implements ImageProducer, Runnable
+{
+ private RenderableImage image;
+ private RenderContext context;
+ private ArrayList consumers = new ArrayList();
+
+ public RenderableImageProducer(RenderableImage image, RenderContext context)
+ {
+ this.image = image;
+ this.context = context;
+ }
+
+ public void setRenderContext(RenderContext context)
+ {
+ this.context = context;
+ }
+
+ public void addConsumer(ImageConsumer consumer)
+ {
+ synchronized (consumers)
+ {
+ if (! consumers.contains(consumer))
+ consumers.add(consumer);
+ }
+ }
+
+ public boolean isConsumer(ImageConsumer consumer)
+ {
+ synchronized (consumers)
+ {
+ return consumers.contains(consumer);
+ }
+ }
+
+ public void removeConsumer(ImageConsumer consumer)
+ {
+ synchronized (consumers)
+ {
+ consumers.remove(consumer);
+ }
+ }
+
+ public void startProduction(ImageConsumer consumer)
+ {
+ addConsumer(consumer);
+ Thread t = new Thread(this, "RenderableImageProducerWorker");
+ t.start();
+ }
+
+ public void requestTopDownLeftRightResend(ImageConsumer consumer)
+ {
+ // Do nothing. The contract says we can ignore this call, so we do.
+ }
+
+ public void run()
+ {
+ // This isn't ideal but it avoids fail-fast problems.
+ // Alternatively, we could clone 'consumers' here.
+ synchronized (consumers)
+ {
+ RenderedImage newImage;
+ if (context == null)
+ newImage = image.createDefaultRendering();
+ else
+ newImage = image.createRendering(context);
+ Raster newData = newImage.getData();
+ ColorModel colorModel = newImage.getColorModel();
+ if (colorModel == null)
+ colorModel = ColorModel.getRGBdefault();
+ SampleModel sampleModel = newData.getSampleModel();
+ DataBuffer dataBuffer = newData.getDataBuffer();
+ int width = newData.getWidth();
+ int height = newData.getHeight();
+
+ // Initialize the consumers.
+ Iterator it = consumers.iterator();
+ while (it.hasNext())
+ {
+ ImageConsumer target = (ImageConsumer) it.next();
+ target.setHints(ImageConsumer.COMPLETESCANLINES
+ | ImageConsumer.SINGLEFRAME
+ | ImageConsumer.SINGLEPASS
+ | ImageConsumer.TOPDOWNLEFTRIGHT);
+ target.setDimensions(width, height);
+ }
+
+ // Work in scan-line order.
+ int[] newLine = new int[width];
+ int[] bands = new int[sampleModel.getNumBands()];
+ for (int y = 0; y < height; ++y)
+ {
+ for (int x = 0; x < width; ++x)
+ {
+ sampleModel.getPixel(x, y, bands, dataBuffer);
+ newLine[x] = colorModel.getDataElement(bands, 0);
+ }
+
+ // Tell the consumers about the new scan line.
+ it = consumers.iterator();
+ while (it.hasNext())
+ {
+ ImageConsumer target = (ImageConsumer) it.next();
+ target.setPixels(0, y, width, 1, colorModel, newLine, 0, width);
+ }
+ }
+
+ // Tell the consumers that we're done.
+ it = consumers.iterator();
+ while (it.hasNext())
+ {
+ ImageConsumer target = (ImageConsumer) it.next();
+ target.imageComplete(ImageConsumer.STATICIMAGEDONE);
+ }
+ }
+ }
+} // class RenderableImageProducer
diff --git a/libjava/classpath/java/awt/image/renderable/RenderedImageFactory.java b/libjava/classpath/java/awt/image/renderable/RenderedImageFactory.java
new file mode 100644
index 000000000..ea2bd69f7
--- /dev/null
+++ b/libjava/classpath/java/awt/image/renderable/RenderedImageFactory.java
@@ -0,0 +1,47 @@
+/* RenderedImageFactory.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.image.renderable;
+
+import java.awt.RenderingHints;
+import java.awt.image.RenderedImage;
+
+public interface RenderedImageFactory
+{
+ RenderedImage create(ParameterBlock block, RenderingHints hints);
+} // interface RenderedImageFactory
diff --git a/libjava/classpath/java/awt/image/renderable/package.html b/libjava/classpath/java/awt/image/renderable/package.html
new file mode 100644
index 000000000..a24237e72
--- /dev/null
+++ b/libjava/classpath/java/awt/image/renderable/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt.image.renderable package.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - java.awt.image.renderable</title></head>
+
+<body>
+<p></p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/package.html b/libjava/classpath/java/awt/package.html
new file mode 100644
index 000000000..c5ff9881a
--- /dev/null
+++ b/libjava/classpath/java/awt/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt package.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - java.awt</title></head>
+
+<body>
+<p>Abstract Window Toolkit classes.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/peer/ButtonPeer.java b/libjava/classpath/java/awt/peer/ButtonPeer.java
new file mode 100644
index 000000000..6e2510ff5
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/ButtonPeer.java
@@ -0,0 +1,45 @@
+/* ButtonPeer.java -- Peer interface for buttons
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+public interface ButtonPeer extends ComponentPeer
+{
+ void setLabel (String label);
+
+} // interface ButtonPeer
diff --git a/libjava/classpath/java/awt/peer/CanvasPeer.java b/libjava/classpath/java/awt/peer/CanvasPeer.java
new file mode 100644
index 000000000..241a0e4e3
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/CanvasPeer.java
@@ -0,0 +1,44 @@
+/* CanvasPeer.java -- Peer interface for a canvas
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+public interface CanvasPeer extends ComponentPeer
+{
+
+} // interface CanvasPeer
diff --git a/libjava/classpath/java/awt/peer/CheckboxMenuItemPeer.java b/libjava/classpath/java/awt/peer/CheckboxMenuItemPeer.java
new file mode 100644
index 000000000..3cc8f72a6
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/CheckboxMenuItemPeer.java
@@ -0,0 +1,45 @@
+/* CheckboxMenuItemPeer.java -- Peer interface for checkbox menu items
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+public interface CheckboxMenuItemPeer extends MenuItemPeer
+{
+ void setState (boolean state);
+
+} // interface CheckboxMenuItemPeer
diff --git a/libjava/classpath/java/awt/peer/CheckboxPeer.java b/libjava/classpath/java/awt/peer/CheckboxPeer.java
new file mode 100644
index 000000000..639614891
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/CheckboxPeer.java
@@ -0,0 +1,51 @@
+/* CheckboxPeer.java -- Interface for checkbox peer
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.awt.CheckboxGroup;
+
+public interface CheckboxPeer extends ComponentPeer
+{
+ void setCheckboxGroup (CheckboxGroup group);
+
+ void setLabel (String label);
+
+ void setState (boolean state);
+
+} // interface CheckboxPeer
diff --git a/libjava/classpath/java/awt/peer/ChoicePeer.java b/libjava/classpath/java/awt/peer/ChoicePeer.java
new file mode 100644
index 000000000..3605a97ef
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/ChoicePeer.java
@@ -0,0 +1,53 @@
+/* ChoicePeer.java -- Peer for choice box
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+public interface ChoicePeer extends ComponentPeer
+{
+ void add (String item, int index);
+
+ void addItem (String item, int index);
+
+ void remove (int index);
+
+ void removeAll();
+
+ void select (int index);
+
+} // interface ChoicePeer
diff --git a/libjava/classpath/java/awt/peer/ComponentPeer.java b/libjava/classpath/java/awt/peer/ComponentPeer.java
new file mode 100644
index 000000000..736cdf376
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/ComponentPeer.java
@@ -0,0 +1,532 @@
+/* ComponentPeer.java -- Toplevel component peer
+ Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.awt.AWTEvent;
+import java.awt.AWTException;
+import java.awt.BufferCapabilities;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.GraphicsConfiguration;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.event.PaintEvent;
+import java.awt.image.ColorModel;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.image.VolatileImage;
+
+import sun.awt.CausedFocusEvent;
+
+/**
+ * Defines the methods that a component peer is required to implement.
+ */
+public interface ComponentPeer
+{
+ /**
+ * Returns the construction status of the specified image. This is called
+ * by {@link Component#checkImage(Image, int, int, ImageObserver)}.
+ *
+ * @param img the image
+ * @param width the width of the image
+ * @param height the height of the image
+ * @param ob the image observer to be notified of updates of the status
+ *
+ * @return a bitwise ORed set of ImageObserver flags
+ */
+ int checkImage(Image img, int width, int height,
+ ImageObserver ob);
+
+ /**
+ * Creates an image by starting the specified image producer. This is called
+ * by {@link Component#createImage(ImageProducer)}.
+ *
+ * @param prod the image producer to be used to create the image
+ *
+ * @return the created image
+ */
+ Image createImage(ImageProducer prod);
+
+ /**
+ * Creates an empty image with the specified <code>width</code> and
+ * <code>height</code>.
+ *
+ * @param width the width of the image to be created
+ * @param height the height of the image to be created
+ *
+ * @return the created image
+ */
+ Image createImage(int width, int height);
+
+ /**
+ * Disables the component. This is called by {@link Component#disable()}.
+ */
+ void disable();
+
+ /**
+ * Disposes the component peer. This should release all resources held by the
+ * peer. This is called when the component is no longer in use.
+ */
+ void dispose();
+
+ /**
+ * Enables the component. This is called by {@link Component#enable()}.
+ */
+ void enable();
+
+ /**
+ * Returns the color model of the component. This is currently not used.
+ *
+ * @return the color model of the component
+ */
+ ColorModel getColorModel();
+
+ /**
+ * Returns the font metrics for the specified font. This is called by
+ * {@link Component#getFontMetrics(Font)}.
+ *
+ * @param f the font for which to query the font metrics
+ *
+ * @return the font metrics for the specified font
+ */
+ FontMetrics getFontMetrics(Font f);
+
+ /**
+ * Returns a {@link Graphics} object suitable for drawing on this component.
+ * This is called by {@link Component#getGraphics()}.
+ *
+ * @return a graphics object suitable for drawing on this component
+ */
+ Graphics getGraphics();
+
+ /**
+ * Returns the location of this component in screen coordinates. This is
+ * called by {@link Component#getLocationOnScreen()}.
+ *
+ * @return the location of this component in screen coordinates
+ */
+ Point getLocationOnScreen();
+
+ /**
+ * Returns the minimum size for the component. This is called by
+ * {@link Component#getMinimumSize()}.
+ *
+ * @return the minimum size for the component
+ *
+ * @specnote Presumably this method got added to replace minimumSize().
+ * However, testing shows that this is never called in the RI
+ * (tested with JDK5), but instead minimumSize() is called
+ * directly. It is advisable to implement this method to delegate
+ * to minimumSize() and put the real implementation in there.
+ */
+ Dimension getMinimumSize();
+
+ /**
+ * Returns the preferred size for the component. This is called by
+ * {@link Component#getPreferredSize()}.
+ *
+ * @return the preferred size for the component
+ *
+ * @specnote Presumably this method got added to replace preferredSize().
+ * However, testing shows that this is never called in the RI
+ * (tested with JDK5), but instead preferredSize() is called
+ * directly. It is advisable to implement this method to delegate
+ * to preferredSize() and put the real implementation in there.
+ */
+ Dimension getPreferredSize();
+
+ /**
+ * Returns the toolkit that created this peer.
+ *
+ * @return the toolkit that created this peer
+ */
+ Toolkit getToolkit();
+
+ /**
+ * Handles the given event. This is called from
+ * {@link Component#dispatchEvent(AWTEvent)} to give the peer a chance to
+ * react to events for the component.
+ *
+ * @param e the event
+ */
+ void handleEvent(AWTEvent e);
+
+ /**
+ * Makes the component invisible. This is called from
+ * {@link Component#hide()}.
+ */
+ void hide();
+
+ /**
+ * Returns <code>true</code> if the component can receive keyboard input
+ * focus. This is called from {@link Component#isFocusTraversable()}.
+ *
+ * @specnote Part of the earlier 1.1 API, replaced by isFocusable().
+ */
+ boolean isFocusTraversable();
+
+ /**
+ * Returns <code>true</code> if the component can receive keyboard input
+ * focus. This is called from {@link Component#isFocusable()}.
+ */
+ boolean isFocusable();
+
+ /**
+ * Returns the minimum size for the component. This is called by
+ * {@link Component#minimumSize()}.
+ *
+ * @return the minimum size for the component
+ */
+ Dimension minimumSize();
+
+ /**
+ * Returns the preferred size for the component. This is called by
+ * {@link Component#getPreferredSize()}.
+ *
+ * @return the preferred size for the component
+ */
+ Dimension preferredSize();
+
+ void paint(Graphics graphics);
+
+ /**
+ * Prepares an image for rendering on this component. This is called by
+ * {@link Component#prepareImage(Image, int, int, ImageObserver)}.
+ *
+ * @param img the image to prepare
+ * @param width the desired width of the rendered image
+ * @param height the desired height of the rendered image
+ * @param ob the image observer to be notified of updates in the preparation
+ * process
+ *
+ * @return <code>true</code> if the image has been fully prepared,
+ * <code>false</code> otherwise (in which case the image observer
+ * receives updates)
+ */
+ boolean prepareImage(Image img, int width, int height,
+ ImageObserver ob);
+
+ void print(Graphics graphics);
+
+ /**
+ * Repaints the specified rectangle of this component. This is called from
+ * {@link Component#repaint(long, int, int, int, int)}.
+ *
+ * @param tm number of milliseconds to wait with repainting
+ * @param x the X coordinate of the upper left corner of the damaged rectangle
+ * @param y the Y coordinate of the upper left corner of the damaged rectangle
+ * @param width the width of the damaged rectangle
+ * @param height the height of the damaged rectangle
+ */
+ void repaint(long tm, int x, int y, int width, int height);
+
+ /**
+ * Requests that this component receives the focus. This is called from
+ * {@link Component#requestFocus()}.
+ *
+ * @specnote Part of the earlier 1.1 API, apparently replaced by argument
+ * form of the same method.
+ */
+ void requestFocus();
+
+ /**
+ * Requests that this component receives the focus. This is called from
+ * {@link Component#requestFocus()}.
+ *
+ * This method is only called for heavyweight component's peers. Lightweight
+ * components ask their nearest heavyweight component to request focus.
+ * It's up to the heavyweight peer to decide if any of it's lightweight
+ * descendants are allowed to receive keyboard input focus or not. If the
+ * focus request is finally approved, then the peer must post a FOCUS_GAINED
+ * event for the requested component.
+ *
+ * @param request the component for which the focus is requested
+ * @param temporary indicates if the focus change is temporary (true) or
+ * permanent (false)
+ * @param allowWindowFocus indicates if it's allowed to change window focus
+ * @param time the timestamp
+ */
+ boolean requestFocus(Component request, boolean temporary,
+ boolean allowWindowFocus, long time);
+
+ /**
+ * Notifies the peer that the bounds of this component have changed. This
+ * is called by {@link Component#reshape(int, int, int, int)}.
+ *
+ * @param x the X coordinate of the upper left corner of the component
+ * @param y the Y coordinate of the upper left corner of the component
+ * @param width the width of the component
+ * @param height the height of the component
+ */
+ void reshape(int x, int y, int width, int height);
+
+ /**
+ * Sets the background color of the component. This is called by
+ * {@link Component#setBackground(Color)}.
+ *
+ * @param color the background color to set
+ */
+ void setBackground(Color color);
+
+ /**
+ * Notifies the peer that the bounds of this component have changed. This
+ * is called by {@link Component#setBounds(int, int, int, int)}.
+ *
+ * @param x the X coordinate of the upper left corner of the component
+ * @param y the Y coordinate of the upper left corner of the component
+ * @param width the width of the component
+ * @param height the height of the component
+ */
+ void setBounds(int x, int y, int width, int height);
+
+ /**
+ * Sets the cursor of the component. This is called by
+ * {@link Component#setCursor(Cursor)}.
+ *
+ * @specnote Part of the earlier 1.1 API, apparently no longer needed.
+ */
+ void setCursor(Cursor cursor);
+
+ /**
+ * Sets the enabled/disabled state of this component. This is called by
+ * {@link Component#setEnabled(boolean)}.
+ *
+ * @param enabled <code>true</code> to enable the component,
+ * <code>false</code> to disable it
+ */
+ void setEnabled(boolean enabled);
+
+ /**
+ * Sets the font of the component. This is called by
+ * {@link Component#setFont(Font)}.
+ *
+ * @param font the font to set
+ */
+ void setFont(Font font);
+
+ /**
+ * Sets the foreground color of the component. This is called by
+ * {@link Component#setForeground(Color)}.
+ *
+ * @param color the foreground color to set
+ */
+ void setForeground(Color color);
+
+ /**
+ * Sets the visibility state of the component. This is called by
+ * {@link Component#setVisible(boolean)}.
+ *
+ * @param visible <code>true</code> to make the component visible,
+ * <code>false</code> to make it invisible
+ */
+ void setVisible(boolean visible);
+
+ /**
+ * Makes the component visible. This is called by {@link Component#show()}.
+ */
+ void show();
+
+ /**
+ * Get the graphics configuration of the component. The color model
+ * of the component can be derived from the configuration.
+ *
+ * @return the graphics configuration of the component
+ */
+ GraphicsConfiguration getGraphicsConfiguration();
+
+ /**
+ * Part of an older API, no longer needed.
+ */
+ void setEventMask(long mask);
+
+ /**
+ * Returns <code>true</code> if this component has been obscured,
+ * <code>false</code> otherwise. This will only work if
+ * {@link #canDetermineObscurity()} also returns <code>true</code>.
+ *
+ * @return <code>true</code> if this component has been obscured,
+ * <code>false</code> otherwise.
+ */
+ boolean isObscured();
+
+ /**
+ * Returns <code>true</code> if this component peer can determine if the
+ * component has been obscured, <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if this component peer can determine if the
+ * component has been obscured, <code>false</code> otherwise
+ */
+ boolean canDetermineObscurity();
+
+ /**
+ * Coalesces the specified paint event.
+ *
+ * @param e the paint event
+ */
+ void coalescePaintEvent(PaintEvent e);
+
+ /**
+ * Updates the cursor.
+ */
+ void updateCursorImmediately();
+
+ /**
+ * Returns true, if this component can handle wheel scrolling,
+ * <code>false</code> otherwise.
+ *
+ * @return true, if this component can handle wheel scrolling,
+ * <code>false</code> otherwise
+ */
+ boolean handlesWheelScrolling();
+
+ /**
+ * A convenience method that creates a volatile image. The volatile
+ * image is created on the screen device on which this component is
+ * displayed, in the device's current graphics configuration.
+ *
+ * @param width width of the image
+ * @param height height of the image
+ *
+ * @see VolatileImage
+ *
+ * @since 1.2
+ */
+ VolatileImage createVolatileImage(int width, int height);
+
+ /**
+ * Create a number of image buffers that implement a buffering
+ * strategy according to the given capabilities.
+ *
+ * @param numBuffers the number of buffers
+ * @param caps the buffering capabilities
+ *
+ * @throws AWTException if the specified buffering strategy is not
+ * implemented
+ *
+ * @since 1.2
+ */
+ void createBuffers(int numBuffers, BufferCapabilities caps)
+ throws AWTException;
+
+ /**
+ * Return the back buffer of this component.
+ *
+ * @return the back buffer of this component.
+ *
+ * @since 1.2
+ */
+ Image getBackBuffer();
+
+ /**
+ * Perform a page flip, leaving the contents of the back buffer in
+ * the specified state.
+ *
+ * @param contents the state in which to leave the back buffer
+ *
+ * @since 1.2
+ */
+ void flip(BufferCapabilities.FlipContents contents);
+
+ /**
+ * Destroy the resources created by createBuffers.
+ *
+ * @since 1.2
+ */
+ void destroyBuffers();
+
+ /**
+ * Get the bounds of this component peer.
+ *
+ * @return component peer bounds
+ * @since 1.5
+ */
+ Rectangle getBounds();
+
+ /**
+ * Reparent this component under another container.
+ *
+ * @param parent
+ * @since 1.5
+ */
+ void reparent(ContainerPeer parent);
+
+ /**
+ * Set the bounds of this component peer.
+ *
+ * @param x the new x co-ordinate
+ * @param y the new y co-ordinate
+ * @param width the new width
+ * @param height the new height
+ * @param z the new stacking level
+ * @since 1.5
+ */
+ void setBounds (int x, int y, int width, int height, int z);
+
+ /**
+ * Check if this component supports being reparented.
+ *
+ * @return true if this component can be reparented,
+ * false otherwise.
+ * @since 1.5
+ */
+ boolean isReparentSupported();
+
+ /**
+ * Layout this component peer.
+ *
+ * @since 1.5
+ */
+ void layout();
+
+
+ /**
+ * Requests the focus on the component.
+ */
+ boolean requestFocus(Component lightweightChild, boolean temporary,
+ boolean focusedWindowChangeAllowed, long time,
+ CausedFocusEvent.Cause cause);
+
+}
diff --git a/libjava/classpath/java/awt/peer/ContainerPeer.java b/libjava/classpath/java/awt/peer/ContainerPeer.java
new file mode 100644
index 000000000..497abdc32
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/ContainerPeer.java
@@ -0,0 +1,83 @@
+/* ContainerPeer.java -- Interface for container peers
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.peer;
+
+import java.awt.Insets;
+
+public interface ContainerPeer extends ComponentPeer
+{
+ Insets insets();
+
+ Insets getInsets();
+
+ void beginValidate();
+
+ void endValidate();
+
+ void beginLayout();
+
+ void endLayout();
+
+ boolean isPaintPending();
+
+ /**
+ * Check if this container peer can be restacked.
+ *
+ * @return true if this container peer supports being restacked, false otherwise
+ * @since 1.5
+ */
+ boolean isRestackSupported();
+
+ /**
+ * Cancel a pending paint event on a region of this container.
+ *
+ * @param x the x co-ordinate of the region
+ * @param y the y co-ordinate of the region
+ * @param width the width of the region
+ * @param height the height of the region
+ * @since 1.5
+ */
+ void cancelPendingPaint(int x, int y, int width, int height);
+
+ /**
+ * Restack the component peers in this container peer.
+ *
+ * @since 1.5
+ */
+ void restack();
+} // interface ContainerPeer
diff --git a/libjava/classpath/java/awt/peer/DesktopPeer.java b/libjava/classpath/java/awt/peer/DesktopPeer.java
new file mode 100644
index 000000000..626ea840e
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/DesktopPeer.java
@@ -0,0 +1,64 @@
+/* DesktopPeer.java -- Interface to enable access to common applications
+ Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath 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 for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+package java.awt.peer;
+
+import java.awt.Desktop.Action;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+
+/**
+ * @author Mario Torre <neugens@limasoftware.net>
+ *
+ */
+public interface DesktopPeer
+{
+ public void browse(URI url) throws IOException;
+
+ public void edit(File file) throws IOException;
+
+ public boolean isSupported(Action action);
+
+ public void mail(URI mailtoURL) throws IOException;
+
+ public void mail() throws IOException;
+
+ public void open(File file) throws IOException;
+
+ public void print(File file) throws IOException;
+}
diff --git a/libjava/classpath/java/awt/peer/DialogPeer.java b/libjava/classpath/java/awt/peer/DialogPeer.java
new file mode 100644
index 000000000..b0963eceb
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/DialogPeer.java
@@ -0,0 +1,47 @@
+/* DialogPeer.java -- Interface for dialog box peer
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+public interface DialogPeer extends WindowPeer
+{
+ void setResizable (boolean resizeable);
+
+ void setTitle (String title);
+
+} // interface DialogPeer
diff --git a/libjava/classpath/java/awt/peer/FileDialogPeer.java b/libjava/classpath/java/awt/peer/FileDialogPeer.java
new file mode 100644
index 000000000..608b9c5d6
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/FileDialogPeer.java
@@ -0,0 +1,51 @@
+/* FileDialogPeer.java -- Interface for file selection dialog box peer
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.io.FilenameFilter;
+
+public interface FileDialogPeer extends DialogPeer
+{
+ void setFile (String file);
+
+ void setDirectory (String dir);
+
+ void setFilenameFilter (FilenameFilter ff);
+
+} // interface FileDialogPeer
diff --git a/libjava/classpath/java/awt/peer/FontPeer.java b/libjava/classpath/java/awt/peer/FontPeer.java
new file mode 100644
index 000000000..388e56175
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/FontPeer.java
@@ -0,0 +1,44 @@
+/* FontPeer.java -- Interface for font peers
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+public interface FontPeer
+{
+
+} // interface FontPeer
diff --git a/libjava/classpath/java/awt/peer/FramePeer.java b/libjava/classpath/java/awt/peer/FramePeer.java
new file mode 100644
index 000000000..f00236819
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/FramePeer.java
@@ -0,0 +1,77 @@
+/* FramePeer.java -- Interface for frame peers
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.awt.Image;
+import java.awt.MenuBar;
+import java.awt.Rectangle;
+
+public interface FramePeer extends WindowPeer
+{
+ void setIconImage(Image image);
+ void setMenuBar(MenuBar mb);
+ void setResizable(boolean resizable);
+ void setTitle(String title);
+ int getState();
+ void setState(int state);
+ void setMaximizedBounds(Rectangle r);
+
+ /**
+ * Check if this frame peer supports being restacked.
+ *
+ * @return true if this frame peer can be restacked,
+ * false otherwise
+ * @since 1.5
+ */
+ boolean isRestackSupported();
+
+ /**
+ * Sets the bounds of this frame peer.
+ *
+ * @param x the new x co-ordinate
+ * @param y the new y co-ordinate
+ * @param width the new width
+ * @param height the new height
+ * @since 1.5
+ */
+ void setBoundsPrivate(int x, int y, int width, int height);
+
+ Rectangle getBoundsPrivate();
+
+} // interface FramePeer
diff --git a/libjava/classpath/java/awt/peer/LabelPeer.java b/libjava/classpath/java/awt/peer/LabelPeer.java
new file mode 100644
index 000000000..b0c5c346d
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/LabelPeer.java
@@ -0,0 +1,45 @@
+/* LabelPeer.java -- Interface for simple text lable peer
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+public interface LabelPeer extends ComponentPeer
+{
+ void setAlignment(int alignment);
+ void setText(String text);
+} // interface LabelPeer
diff --git a/libjava/classpath/java/awt/peer/LightweightPeer.java b/libjava/classpath/java/awt/peer/LightweightPeer.java
new file mode 100644
index 000000000..38333b0aa
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/LightweightPeer.java
@@ -0,0 +1,44 @@
+/* LightweightPeer.java -- Interface for lightweight peers
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+public interface LightweightPeer extends ComponentPeer
+{
+
+} // interface LightweightPeer
diff --git a/libjava/classpath/java/awt/peer/ListPeer.java b/libjava/classpath/java/awt/peer/ListPeer.java
new file mode 100644
index 000000000..55ff92913
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/ListPeer.java
@@ -0,0 +1,60 @@
+/* ListPeer.java -- Interface for list box peer
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.awt.Dimension;
+
+public interface ListPeer extends ComponentPeer
+{
+ void add(String item, int index);
+ void addItem(String item, int index);
+ void clear();
+ void delItems(int start_index, int end_index);
+ void deselect(int index);
+ int[] getSelectedIndexes();
+ void makeVisible(int index);
+ Dimension minimumSize(int s);
+ Dimension preferredSize(int s);
+ void removeAll();
+ void select(int index);
+ void setMultipleMode(boolean multi);
+ void setMultipleSelections(boolean multi);
+ Dimension getPreferredSize(int s);
+ Dimension getMinimumSize(int s);
+} // interface ListPeer
diff --git a/libjava/classpath/java/awt/peer/MenuBarPeer.java b/libjava/classpath/java/awt/peer/MenuBarPeer.java
new file mode 100644
index 000000000..ae43af3cc
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/MenuBarPeer.java
@@ -0,0 +1,48 @@
+/* MenuBarPeer.java -- Interface for menu bar peer
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.awt.Menu;
+
+public interface MenuBarPeer extends MenuComponentPeer
+{
+ void addMenu(Menu m);
+ void addHelpMenu(Menu menu);
+ void delMenu(int index);
+} // interface MenuBarPeer
diff --git a/libjava/classpath/java/awt/peer/MenuComponentPeer.java b/libjava/classpath/java/awt/peer/MenuComponentPeer.java
new file mode 100644
index 000000000..7369aa52e
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/MenuComponentPeer.java
@@ -0,0 +1,54 @@
+/* MenuComponentPeer.java --
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.awt.Font;
+
+public interface MenuComponentPeer
+{
+ void dispose();
+
+ /**
+ * Set the font on this menu component peer.
+ *
+ * @param font the new font
+ * @since 1.5
+ */
+ void setFont (Font font);
+} // interface MenuComponentPeer
diff --git a/libjava/classpath/java/awt/peer/MenuItemPeer.java b/libjava/classpath/java/awt/peer/MenuItemPeer.java
new file mode 100644
index 000000000..bedbd9f9e
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/MenuItemPeer.java
@@ -0,0 +1,47 @@
+/* MenuItemPeer.java -- Interface for menu item peers
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+public interface MenuItemPeer extends MenuComponentPeer
+{
+ void disable();
+ void enable();
+ void setEnabled(boolean enabled);
+ void setLabel(String text);
+} // interface MenuItemPeer
diff --git a/libjava/classpath/java/awt/peer/MenuPeer.java b/libjava/classpath/java/awt/peer/MenuPeer.java
new file mode 100644
index 000000000..e1f7a90e2
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/MenuPeer.java
@@ -0,0 +1,48 @@
+/* MenuPeer.java -- Interface for menu peers
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.awt.MenuItem;
+
+public interface MenuPeer extends MenuItemPeer
+{
+ void addItem (MenuItem item);
+ void addSeparator ();
+ void delItem (int index);
+}
diff --git a/libjava/classpath/java/awt/peer/MouseInfoPeer.java b/libjava/classpath/java/awt/peer/MouseInfoPeer.java
new file mode 100644
index 000000000..71d294157
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/MouseInfoPeer.java
@@ -0,0 +1,61 @@
+/* MouseInfoPeer.java -- peer interface for MouseInfo
+ Copyright (C) 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.peer;
+
+import java.awt.Point;
+import java.awt.Window;
+
+/**
+ * MouseInfoPeer is the peer interface java.awt.MouseInfo.
+ *
+ * @author Sven de Marothy
+ * @since 1.5
+ */
+public interface MouseInfoPeer
+{
+ /**
+ * Get the mouse pointer coordinates and store them in p (obviously non-null)
+ * returns the index of the current screen device of the mouse.
+ */
+ public int fillPointWithCoords(Point p);
+
+ /**
+ * Returns whether a given Window is under the mouse.
+ */
+ public boolean isWindowUnderMouse(Window w);
+}
diff --git a/libjava/classpath/java/awt/peer/PanelPeer.java b/libjava/classpath/java/awt/peer/PanelPeer.java
new file mode 100644
index 000000000..a72b16cac
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/PanelPeer.java
@@ -0,0 +1,44 @@
+/* PanelPeer.java -- Interface for panel peers
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+public interface PanelPeer extends ContainerPeer
+{
+
+} // interface PanelPeer
diff --git a/libjava/classpath/java/awt/peer/PopupMenuPeer.java b/libjava/classpath/java/awt/peer/PopupMenuPeer.java
new file mode 100644
index 000000000..e747a4de7
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/PopupMenuPeer.java
@@ -0,0 +1,52 @@
+/* PopupMenuPeer.java -- Interface for popup menu peers
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.awt.Component;
+import java.awt.Event;
+
+public interface PopupMenuPeer extends MenuPeer
+{
+ /**
+ * Part of the older API, replaced by event version instead.
+ */
+ void show (Component origin, int x, int y);
+
+ void show (Event e);
+} // interface PopupMenuPeer
diff --git a/libjava/classpath/java/awt/peer/RobotPeer.java b/libjava/classpath/java/awt/peer/RobotPeer.java
new file mode 100644
index 000000000..46c0086dc
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/RobotPeer.java
@@ -0,0 +1,55 @@
+/* RobotPeer.java -- Interface for programatically driving GUI
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.awt.Rectangle;
+
+public interface RobotPeer
+{
+ void mouseMove (int x, int y);
+ void mousePress (int buttons);
+ void mouseRelease (int buttons);
+ void mouseWheel (int wheelAmt);
+ void keyPress (int keycode);
+ void keyRelease (int keycode);
+ int getRGBPixel (int x, int y);
+ int[] getRGBPixels (Rectangle screen);
+ void dispose();
+
+} // interface RobotPeer
diff --git a/libjava/classpath/java/awt/peer/ScrollPanePeer.java b/libjava/classpath/java/awt/peer/ScrollPanePeer.java
new file mode 100644
index 000000000..afbd2f861
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/ScrollPanePeer.java
@@ -0,0 +1,51 @@
+/* ScrollPanePeer.java -- Interface for scrollable panes
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.awt.Adjustable;
+
+public interface ScrollPanePeer extends ContainerPeer
+{
+ int getHScrollbarHeight();
+ int getVScrollbarWidth();
+ void setScrollPosition(int h, int v);
+ void childResized(int width, int height);
+ void setUnitIncrement(Adjustable item, int inc);
+ void setValue(Adjustable item, int value);
+} // interface ScollPanePeer
diff --git a/libjava/classpath/java/awt/peer/ScrollbarPeer.java b/libjava/classpath/java/awt/peer/ScrollbarPeer.java
new file mode 100644
index 000000000..4191a39b7
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/ScrollbarPeer.java
@@ -0,0 +1,46 @@
+/* ScrollbarPeer.java -- Interface for scrollbar peers
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+public interface ScrollbarPeer extends ComponentPeer
+{
+ void setLineIncrement(int inc);
+ void setPageIncrement(int inc);
+ void setValues(int value, int visible, int min, int max);
+} // interface ScrollbarPeer
diff --git a/libjava/classpath/java/awt/peer/TextAreaPeer.java b/libjava/classpath/java/awt/peer/TextAreaPeer.java
new file mode 100644
index 000000000..354e46d9c
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/TextAreaPeer.java
@@ -0,0 +1,53 @@
+/* TextAreaPeer.java -- Interface for text area peers
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.awt.Dimension;
+
+public interface TextAreaPeer extends TextComponentPeer
+{
+ void insert(String text, int pos);
+ void insertText(String text, int pos);
+ Dimension minimumSize(int rows, int cols);
+ Dimension getMinimumSize(int rows, int cols);
+ Dimension preferredSize(int rows, int cols);
+ Dimension getPreferredSize(int rows, int cols);
+ void replaceRange(String text, int start_pos, int end_pos);
+ void replaceText(String text, int start_pos, int end_pos);
+} // interface TextAreaPeer
diff --git a/libjava/classpath/java/awt/peer/TextComponentPeer.java b/libjava/classpath/java/awt/peer/TextComponentPeer.java
new file mode 100644
index 000000000..57f0fd2eb
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/TextComponentPeer.java
@@ -0,0 +1,65 @@
+/* TextComponentPeer.java -- Superclass interface for text components
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.awt.Rectangle;
+import java.awt.im.InputMethodRequests;
+
+public interface TextComponentPeer extends ComponentPeer
+{
+ int getSelectionEnd();
+ int getSelectionStart();
+ String getText();
+ void setText(String text);
+ void select(int start_pos, int end_pos);
+ void setEditable(boolean editable);
+ int getCaretPosition();
+ void setCaretPosition(int pos);
+ int getIndexAtPoint(int x, int y);
+ Rectangle getCharacterBounds(int pos);
+ long filterEvents(long filter);
+
+ /**
+ * Retrieve this text component peer's input method requests.
+ *
+ * @return the input method requests made by this text component peer
+ * @since 1.5
+ */
+ InputMethodRequests getInputMethodRequests();
+} // interface TextComponentPeer
diff --git a/libjava/classpath/java/awt/peer/TextFieldPeer.java b/libjava/classpath/java/awt/peer/TextFieldPeer.java
new file mode 100644
index 000000000..55c673a2d
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/TextFieldPeer.java
@@ -0,0 +1,51 @@
+/* TextFieldPeer.java -- Interface for text field peers
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.awt.Dimension;
+
+public interface TextFieldPeer extends TextComponentPeer
+{
+ Dimension minimumSize(int len);
+ Dimension preferredSize(int len);
+ Dimension getMinimumSize(int len);
+ Dimension getPreferredSize(int len);
+ void setEchoChar(char echo_char);
+ void setEchoCharacter(char echo_char);
+} // interface TextFieldPeer
diff --git a/libjava/classpath/java/awt/peer/WindowPeer.java b/libjava/classpath/java/awt/peer/WindowPeer.java
new file mode 100644
index 000000000..3ca13a20f
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/WindowPeer.java
@@ -0,0 +1,69 @@
+/* WindowPeer.java -- Interface for window peers
+ Copyright (C) 1999, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.peer;
+
+import java.awt.Dialog;
+
+public interface WindowPeer extends ContainerPeer
+{
+ void toBack();
+ void toFront();
+
+ /**
+ * Update the always-on-top status of the Window.
+ *
+ * @since 1.5
+ */
+ void updateAlwaysOnTop();
+
+ /**
+ * Request that this window peer be given the window focus.
+ *
+ * @return true if the window received focus, false otherwise
+ * @since 1.5
+ */
+ boolean requestWindowFocus();
+
+ void setAlwaysOnTop(boolean alwaysOnTop);
+ void updateFocusableWindowState();
+ void setModalBlocked(Dialog blocker, boolean blocked);
+ void updateMinimumSize();
+ void updateIconImages();
+
+} // interface WindowPeer
diff --git a/libjava/classpath/java/awt/peer/package.html b/libjava/classpath/java/awt/peer/package.html
new file mode 100644
index 000000000..7a7458c17
--- /dev/null
+++ b/libjava/classpath/java/awt/peer/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt.peer package.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - java.awt.peer</title></head>
+
+<body>
+<p>Interfaces for using native interface components.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/java/awt/print/Book.java b/libjava/classpath/java/awt/print/Book.java
new file mode 100644
index 000000000..8b040b2d1
--- /dev/null
+++ b/libjava/classpath/java/awt/print/Book.java
@@ -0,0 +1,159 @@
+/* Book.java -- A mixed group of pages to print.
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.print;
+
+import java.util.Vector;
+
+/**
+ * This class allows documents to be created with different paper types,
+ * page formatters, and painters.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class Book implements Pageable
+{
+ /**
+ * Painter objects for the book.
+ */
+ Vector printables = new Vector();
+
+ /**
+ * Page formats for the book.
+ */
+ Vector page_formats = new Vector();
+
+ /**
+ * Initializes a new instance of <code>Book</code> that is empty.
+ */
+ public Book()
+ {
+ }
+
+ /**
+ * Returns the number of pages in this book.
+ *
+ * @return The number of pages in this book.
+ */
+ public int getNumberOfPages()
+ {
+ return printables.size();
+ }
+
+ /**
+ * This method returns the <code>PageFormat</code> object for the
+ * specified page.
+ *
+ * @param page_number The number of the page to get information for, where
+ * page numbers start at 0.
+ *
+ * @return The <code>PageFormat</code> object for the specified page.
+ *
+ * @exception IndexOutOfBoundsException If the page number is not valid.
+ */
+ public PageFormat getPageFormat(int page_number)
+ {
+ return (PageFormat) page_formats.elementAt(page_number);
+ }
+
+ /**
+ * This method returns the <code>Printable</code> object for the
+ * specified page.
+ *
+ * @param page_number The number of the page to get information for, where
+ * page numbers start at 0.
+ *
+ * @return The <code>Printable</code> object for the specified page.
+ *
+ * @exception IndexOutOfBoundsException If the page number is not valid.
+ */
+ public Printable getPrintable(int page_number)
+ {
+ return (Printable) printables.elementAt(page_number);
+ }
+
+ /**
+ * This method appends a page to the end of the book.
+ *
+ * @param printable The <code>Printable</code> for this page.
+ * @param page_format The <code>PageFormat</code> for this page.
+ *
+ * @exception NullPointerException If either argument is <code>null</code>.
+ */
+ public void append(Printable printable, PageFormat page_format)
+ {
+ append(printable, page_format, 1);
+ }
+
+ /**
+ * This method appends the specified number of pages to the end of the book.
+ * Each one will be associated with the specified <code>Printable</code>
+ * and <code>PageFormat</code>.
+ *
+ * @param printable The <code>Printable</code> for this page.
+ * @param page_format The <code>PageFormat</code> for this page.
+ * @param num_pages The number of pages to append.
+ *
+ * @exception NullPointerException If any argument is <code>null</code>.
+ */
+ public void append(Printable printable, PageFormat page_format, int num_pages)
+ {
+ for (int i = 0; i < num_pages; i++)
+ {
+ printables.addElement(printable);
+ page_formats.addElement(page_format);
+ }
+ }
+
+ /**
+ * This method changes the <code>Printable</code> and <code>PageFormat</code>
+ * for the specified page. The page must already exist or an exception
+ * will be thrown.
+ *
+ * @param page_num The page number to alter.
+ * @param printable The new <code>Printable</code> for the page.
+ * @param page_format The new <code>PageFormat</code> for the page.
+ *
+ * @throws IndexOutOfBoundsException If the specified page does not exist.
+ */
+ public void setPage(int page_num, Printable printable, PageFormat page_format)
+ {
+ printables.setElementAt(printable, page_num);
+ page_formats.setElementAt(page_format, page_num);
+ }
+}
diff --git a/libjava/classpath/java/awt/print/NoPrinterJob.java b/libjava/classpath/java/awt/print/NoPrinterJob.java
new file mode 100644
index 000000000..e9659a147
--- /dev/null
+++ b/libjava/classpath/java/awt/print/NoPrinterJob.java
@@ -0,0 +1,124 @@
+/* NoPrinterJob.java -- Fake PrinterJob that just signals no print service.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.print;
+
+/**
+ * Fake PrinterJob that just signals no print service. This is only
+ * here so applications can call
+ * <code>PrintJob.getPrinterJob().getPrinterJob()</code> and check
+ * that it returns <code>null</code> which indicates no actual
+ * printing support is available.
+ */
+class NoPrinterJob extends PrinterJob
+{
+ public int getCopies()
+ {
+ return 0;
+ }
+
+ public void setCopies(int copies)
+ {
+ // Do nothing.
+ }
+
+ public String getJobName()
+ {
+ return "NoPrinterJob";
+ }
+
+ public void setJobName(String job_name)
+ {
+ // Do nothing.
+ }
+
+ public String getUserName()
+ {
+ return "NoUser";
+ }
+
+ public void cancel()
+ {
+ // Do nothing.
+ }
+
+ public boolean isCancelled()
+ {
+ return true;
+ }
+
+ public PageFormat defaultPage(PageFormat page_format)
+ {
+ return page_format;
+ }
+
+ public PageFormat pageDialog(PageFormat page_format)
+ {
+ return page_format;
+ }
+
+ public void print() throws PrinterException
+ {
+ throw new PrinterException("No printer");
+ }
+
+ public boolean printDialog()
+ {
+ return false;
+ }
+
+ public void setPageable(Pageable pageable)
+ {
+ // Do nothing.
+ }
+
+ public void setPrintable(Printable printable)
+ {
+ // Do nothing.
+ }
+
+ public void setPrintable(Printable printable, PageFormat page_format)
+ {
+ // Do nothing.
+ }
+
+ public PageFormat validatePage(PageFormat page_format)
+ {
+ return page_format;
+ }
+}
diff --git a/libjava/classpath/java/awt/print/PageFormat.java b/libjava/classpath/java/awt/print/PageFormat.java
new file mode 100644
index 000000000..86d8ba210
--- /dev/null
+++ b/libjava/classpath/java/awt/print/PageFormat.java
@@ -0,0 +1,233 @@
+/* PageFormat.java -- Information about the page format
+ Copyright (C) 1999, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.print;
+
+/**
+ * This class contains information about the desired page format to use for
+ * printing a particular set of pages.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class PageFormat
+ implements Cloneable
+{
+ /**
+ * A constant for a landscaped page orientation. Used by
+ * <code>getOrientation</code> and <code>setOrientation</code>.
+ */
+ public static final int LANDSCAPE = 0;
+
+ /**
+ * A constant for a portrait page orientation. Used by
+ * <code>getOrientation</code> and <code>setOrientation</code>.
+ */
+ public static final int PORTRAIT = 1;
+
+ /**
+ * A constant for a reversed landscaped page orientation. This is the
+ * orientation used by Macintosh's for landscape. The origin is in the
+ * upper right hand corner instead of the upper left. The X and Y axes
+ * are reversed. Used by <code>getOrientation</code> and
+ * <code>setOrientation</code>.
+ */
+ public static final int REVERSE_LANDSCAPE = 2;
+
+ // The page orientation
+ private int orientation;
+
+ // The paper type
+ private Paper paper;
+
+ /**
+ * This method creates a default page layout, which will be in portrait
+ * format.
+ */
+ public PageFormat()
+ {
+ this.paper = new Paper();
+ this.orientation = PORTRAIT;
+ }
+
+ /**
+ * This method returns the width of the page, in 1/72nd's of an inch. The
+ * "width" measured depends on orientation.
+ *
+ * @return The width of the page.
+ */
+ public double getWidth()
+ {
+ return paper.getWidth();
+ }
+
+ /**
+ * This method returns the height of the page, in 1/72nd's of an inch. The
+ * "height" measured depends on the orientation.
+ *
+ * @return The height of the page.
+ */
+ public double getHeight()
+ {
+ return paper.getHeight();
+ }
+
+ /**
+ * This method returns the X coordinate value of the upper leftmost drawable
+ * area of the paper.
+ *
+ * @return The upper leftmost imageable X coordinate.
+ */
+ public double getImageableX()
+ {
+ return paper.getImageableX();
+ }
+
+ /**
+ * This method returns the Y coordinate value of the upper leftmost drawable
+ * area of the paper.
+ *
+ * @return The upper leftmost imageable Y coordinate.
+ */
+ public double getImageableY()
+ {
+ return paper.getImageableY();
+ }
+
+ /**
+ * This method returns the imageable width of the paper, in 1/72nd's of an
+ * inch.
+ *
+ * @return The imageable width of the paper.
+ */
+ public double getImageableWidth()
+ {
+ return paper.getImageableWidth();
+ }
+
+ /**
+ * This method returns the imageable height of the paper, in 1/72nd's of an
+ * inch.
+ *
+ * @return The imageable height of the paper.
+ */
+ public double getImageableHeight()
+ {
+ return paper.getImageableHeight();
+ }
+
+ /**
+ * Returns a copy of the <code>paper</code> object being used for this page
+ * format.
+ *
+ * @return A copy of the <code>Paper</code> object for this format.
+ */
+ public Paper getPaper()
+ {
+ return (Paper) paper.clone();
+ }
+
+ /**
+ * Sets the <code>Paper</code> object to be used by this page format.
+ *
+ * @param paper The new <code>Paper</code> object for this page format.
+ */
+ public void setPaper(Paper paper)
+ {
+ this.paper = paper;
+ }
+
+ /**
+ * This method returns the current page orientation. The value returned will
+ * be one of the page orientation constants from this class.
+ *
+ * @return The current page orientation.
+ */
+ public int getOrientation()
+ {
+ return orientation;
+ }
+
+ /**
+ * This method sets the page orientation for this format to the specified
+ * value. It must be one of the page orientation constants from this class
+ * or an exception will be thrown.
+ *
+ * @param orientation The new page orientation.
+ * @exception IllegalArgumentException If the specified page orientation
+ * value is not one of the constants from this class.
+ */
+ public void setOrientation(int orientation) throws IllegalArgumentException
+ {
+ if ((orientation != PORTRAIT) && (orientation != LANDSCAPE)
+ && (orientation != REVERSE_LANDSCAPE))
+ throw new IllegalArgumentException("Bad page orientation value: "
+ + orientation);
+
+ this.orientation = orientation;
+ }
+
+ /**
+ * This method returns a matrix used for transforming user space coordinates
+ * to page coordinates. The value returned will be six doubles as described
+ * in <code>java.awt.geom.AffineTransform</code>.
+ *
+ * @return The transformation matrix for this page format.
+ */
+ public double[] getMatrix()
+ {
+ throw new RuntimeException("Not implemented since I don't know what to do");
+ }
+
+ /**
+ * This method returns a copy of this object.
+ *
+ * @return A copy of this object.
+ */
+ public Object clone()
+ {
+ try
+ {
+ return (super.clone());
+ }
+ catch (CloneNotSupportedException e)
+ {
+ return (null);
+ }
+ }
+
+}
diff --git a/libjava/classpath/java/awt/print/Pageable.java b/libjava/classpath/java/awt/print/Pageable.java
new file mode 100644
index 000000000..58e0885fb
--- /dev/null
+++ b/libjava/classpath/java/awt/print/Pageable.java
@@ -0,0 +1,90 @@
+/* Pageable.java -- Pages to be printed
+ Copyright (C) 1999, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.print;
+
+/**
+ * This interface represents pages that are to be printed.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface Pageable
+{
+ /**
+ * This constant is returned when <code>getNumberOfPages()</code> cannot
+ * determine the number of pages available for printing.
+ */
+ int UNKNOWN_NUMBER_OF_PAGES = - 1;
+
+ /**
+ * This method returns the number of pages this object contains, or
+ * <code>UNKNOWN_NUMBER_OF_PAGES</code> if it cannot determine the number
+ * of pages to be printed.
+ *
+ * @return The number of pages to be printed, or
+ * <code>UNKNOWN_NUMBER_OF_PAGES</code> if this is unknown.
+ */
+ int getNumberOfPages();
+
+ /**
+ * This method returns the <code>PageFormat</code> instance for the
+ * specified page. Page numbers start at zero. An exception is thrown if the
+ * requested page does not exist.
+ *
+ * @param pageIndex The index of the page to return the
+ * <code>PageFormat</code> for.
+ * @return The <code>PageFormat</code> for the requested page.
+ * @exception IndexOutOfBoundsException If the requested page number does
+ * not exist.
+ */
+ PageFormat getPageFormat(int pageIndex) throws IndexOutOfBoundsException;
+
+ /**
+ * This method returns the <code>Printable</code> instance for the specified
+ * page. Page numbers start at zero. An exception is thrown if the requested
+ * page does not exist.
+ *
+ * @param pageIndex The index of the page to return the
+ * <code>Printable</code> for.
+ * @return The <code>Printable</code> for the requested page.
+ * @exception IndexOutOfBoundsException If the requested page number does
+ * not exist.
+ */
+ Printable getPrintable(int pageIndex) throws IndexOutOfBoundsException;
+
+}
diff --git a/libjava/classpath/java/awt/print/Paper.java b/libjava/classpath/java/awt/print/Paper.java
new file mode 100644
index 000000000..a80da2fea
--- /dev/null
+++ b/libjava/classpath/java/awt/print/Paper.java
@@ -0,0 +1,197 @@
+/* Paper.java -- Information about a paper type.
+ Copyright (C) 1999, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.print;
+
+/**
+ * This class describes a particular type of paper.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public class Paper
+ implements Cloneable
+{
+ // Height of the paper
+ private double height;
+
+ // Width of the paper
+ private double width;
+
+ // Upper left imageable X coordinate
+ private double imageableX;
+
+ // Upper left imageable Y coordinate
+ private double imageableY;
+
+ // Imageable width of the page
+ private double imageableWidth;
+
+ // Imageable height of the page
+ private double imageableHeight;
+
+ /**
+ * This method creates a letter sized paper with one inch margins
+ */
+ public Paper()
+ {
+ width = 8.5 * 72;
+ height = 11 * 72;
+ imageableX = 72;
+ imageableY = 72;
+ imageableWidth = width - (2 * 72);
+ imageableHeight = height - (2 * 72);
+ }
+
+ /**
+ * This method returns the height of the paper in 1/72nds of an inch.
+ *
+ * @return The height of the paper in 1/72nds of an inch.
+ */
+ public double getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * Returns the width of the paper in 1/72nds of an inch.
+ *
+ * @return The width of the paper in 1/72nds of an inch.
+ */
+ public double getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * This method returns the X coordinate of the upper left hand corner of the
+ * imageable area of the paper.
+ *
+ * @return The X coordinate of the upper left hand corner of the imageable
+ * area of the paper.
+ */
+ public double getImageableX()
+ {
+ return imageableX;
+ }
+
+ /**
+ * This method returns the Y coordinate of the upper left hand corner of the
+ * imageable area of the paper.
+ *
+ * @return The Y coordinate of the upper left hand corner of the imageable
+ * area of the paper.
+ */
+ public double getImageableY()
+ {
+ return imageableY;
+ }
+
+ /**
+ * Returns the width of the imageable area of the paper.
+ *
+ * @return The width of the imageable area of the paper.
+ */
+ public double getImageableWidth()
+ {
+ return imageableWidth;
+ }
+
+ /**
+ * Returns the height of the imageable area of the paper.
+ *
+ * @return The height of the imageable area of the paper.
+ */
+ public double getImageableHeight()
+ {
+ return imageableHeight;
+ }
+
+ /**
+ * This method sets the size of the paper to the specified width and height,
+ * which are specified in 1/72nds of an inch.
+ *
+ * @param width The width of the paper in 1/72nds of an inch.
+ * @param height The height of the paper in 1/72nds of an inch.
+ */
+ public void setSize(double width, double height)
+ {
+ this.width = width;
+ this.height = height;
+ }
+
+ /**
+ * This method sets the imageable area of the paper by specifying the
+ * coordinates of the upper left hand corner of that area, and its length
+ * and height. All values are in 1/72nds of an inch.
+ *
+ * @param imageableX The X coordinate of the upper left hand corner of the
+ * imageable area, in 1/72nds of an inch.
+ * @param imageableY The Y coordinate of the upper left hand corner of the
+ * imageable area, in 1/72nds of an inch.
+ * @param imageableWidth The width of the imageable area of the paper, in
+ * 1/72nds of an inch.
+ * @param imageableHeight The heigth of the imageable area of the paper, in
+ * 1/72nds of an inch.
+ */
+ public void setImageableArea(double imageableX, double imageableY,
+ double imageableWidth, double imageableHeight)
+ {
+ this.imageableX = imageableX;
+ this.imageableY = imageableY;
+ this.imageableWidth = imageableWidth;
+ this.imageableHeight = imageableHeight;
+ }
+
+ /**
+ * This method creates a copy of this object.
+ *
+ * @return A copy of this object.
+ */
+ public Object clone()
+ {
+ try
+ {
+ return (super.clone());
+ }
+ catch (CloneNotSupportedException e)
+ {
+ return (null);
+ }
+ }
+
+}
diff --git a/libjava/classpath/java/awt/print/Printable.java b/libjava/classpath/java/awt/print/Printable.java
new file mode 100644
index 000000000..775167e66
--- /dev/null
+++ b/libjava/classpath/java/awt/print/Printable.java
@@ -0,0 +1,80 @@
+/* Printable.java -- Renders a page to the print device
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.awt.print;
+
+import java.awt.Graphics;
+
+
+/**
+ * This interface provides a mechanism for the actual printing of pages to the
+ * printer. The object implementing this interface performs the page
+ * rendering.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface Printable
+{
+ /**
+ * This value is returned by the <code>print()</code> method to indicate
+ * that the requested page exists and has been printed.
+ */
+ int PAGE_EXISTS = 0;
+
+ /**
+ * This value is returned by the <code>print()</code> method to indicate
+ * that the requested page number does not exist.
+ */
+ int NO_SUCH_PAGE = 1;
+
+ /**
+ * This method prints the specified page to the specified graphics
+ * context in the specified format. The pages are numbered starting
+ * from zero.
+ *
+ * @param graphics The graphics context to render the pages on.
+ * @param format The format in which to print the page.
+ * @param page_number The page number to print, where numbers start at zero.
+ *
+ * @return <code>PAGE_EXISTS</code> if the requested page exists and was
+ * successfully printed, <code>NO_SUCH_PAGE</code> otherwise.
+ *
+ * @exception PrinterException If an error occurs during printing.
+ */
+ int print(Graphics graphics, PageFormat format, int page_number)
+ throws PrinterException;
+}
diff --git a/libjava/classpath/java/awt/print/PrinterAbortException.java b/libjava/classpath/java/awt/print/PrinterAbortException.java
new file mode 100644
index 000000000..458063079
--- /dev/null
+++ b/libjava/classpath/java/awt/print/PrinterAbortException.java
@@ -0,0 +1,71 @@
+/* PrinterAbortException.java -- Indicates the print job was aborted
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.print;
+
+/**
+ * This exception is thrown when the print job is aborted, either by the
+ * user or by the application.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @status updated to 1.4
+ */
+public class PrinterAbortException extends PrinterException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 4725169026278854136L;
+
+ /**
+ * Create a new instance with no detailed error message.
+ */
+ public PrinterAbortException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message.
+ *
+ * @param message the descriptive error message
+ */
+ public PrinterAbortException(String message)
+ {
+ super(message);
+ }
+} // class PrinterAbortException
diff --git a/libjava/classpath/java/awt/print/PrinterException.java b/libjava/classpath/java/awt/print/PrinterException.java
new file mode 100644
index 000000000..c105f549d
--- /dev/null
+++ b/libjava/classpath/java/awt/print/PrinterException.java
@@ -0,0 +1,71 @@
+/* PrinterException.java -- generic problem in the printing subsystem
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.print;
+
+/**
+ * This is the generic toplevel exception for printing errors. Subclasses
+ * provide more detailed descriptions of the problem.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @status updated to 1.4
+ */
+public class PrinterException extends Exception
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = -3757589981158265819L;
+
+ /**
+ * Create a new instance with no detailed error message.
+ */
+ public PrinterException()
+ {
+ }
+
+ /**
+ * Create a new instance with a descriptive error message.
+ *
+ * @param message the descriptive error message
+ */
+ public PrinterException(String message)
+ {
+ super(message);
+ }
+} // class PrinterException
diff --git a/libjava/classpath/java/awt/print/PrinterGraphics.java b/libjava/classpath/java/awt/print/PrinterGraphics.java
new file mode 100644
index 000000000..c1f199c65
--- /dev/null
+++ b/libjava/classpath/java/awt/print/PrinterGraphics.java
@@ -0,0 +1,58 @@
+/* PrinterGraphics.java -- Hook to return print job controller.
+ Copyright (C) 1999, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.print;
+
+/**
+ * This interface is implemented by the <code>Graphics</code> instance that is
+ * used for rendering pages. It provides a hook to return the object that is
+ * controlling the print job.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public interface PrinterGraphics
+{
+ /**
+ * This method returns the instance of <code>PrinterJob</code> that is
+ * controlling this print job.
+ *
+ * @return The <code>PrinterJob</code> that is controlling this print job.
+ */
+ PrinterJob getPrinterJob();
+
+}
diff --git a/libjava/classpath/java/awt/print/PrinterIOException.java b/libjava/classpath/java/awt/print/PrinterIOException.java
new file mode 100644
index 000000000..2089af59e
--- /dev/null
+++ b/libjava/classpath/java/awt/print/PrinterIOException.java
@@ -0,0 +1,97 @@
+/* PrinterIOException.java -- The print job encountered an I/O error
+ Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.print;
+
+import java.io.IOException;
+
+/**
+ * This exception is thrown when the print job encounters an I/O problem
+ * of some kind.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @status updated to 1.4
+ */
+public class PrinterIOException extends PrinterException
+{
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 5850870712125932846L;
+
+ /**
+ * The exception that caused this (duplicates Throwable).
+ *
+ * @serial the I/O exception that terminated the job
+ */
+ private final IOException mException;
+
+ /**
+ * Initializes a new instance with the given cause.
+ *
+ * @param mException the cause
+ */
+ public PrinterIOException(IOException mException)
+ {
+ super(mException == null ? null : mException.toString());
+ initCause(mException);
+ this.mException = mException;
+ }
+
+ /**
+ * Gets the underlying <code>IOException</code> that caused this exception.
+ * This legacy method has been replaced by {@link #getCause()}.
+ *
+ * @return the cause
+ */
+ public IOException getIOException()
+ {
+ return mException;
+ }
+
+ /**
+ * Gets the cause.
+ *
+ * @return the cause
+ */
+ public Throwable getCause()
+ {
+ return mException;
+ }
+} // class PrinterIOException
diff --git a/libjava/classpath/java/awt/print/PrinterJob.java b/libjava/classpath/java/awt/print/PrinterJob.java
new file mode 100644
index 000000000..1a4b8c8e2
--- /dev/null
+++ b/libjava/classpath/java/awt/print/PrinterJob.java
@@ -0,0 +1,300 @@
+/* PrinterJob.java -- This job is the printer control class
+ Copyright (C) 1999, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt.print;
+
+import gnu.java.awt.print.JavaPrinterJob;
+
+import java.awt.HeadlessException;
+import javax.print.PrintService;
+import javax.print.PrintServiceLookup;
+import javax.print.DocFlavor;
+import javax.print.StreamPrintServiceFactory;
+import javax.print.attribute.PrintRequestAttributeSet;
+
+/**
+ * This class controls printing.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
+public abstract class PrinterJob
+{
+ // The print service associated with this job
+ private PrintService printer = null;
+
+ /**
+ * Creates a new print job.
+ *
+ * @return A <code>PrinterJob</code> object for the newly created print job.
+ */
+ public static PrinterJob getPrinterJob()
+ {
+ return new JavaPrinterJob();
+ }
+
+ /**
+ * Initializes a new instance of <code>PrinterJob</code>.
+ */
+ public PrinterJob()
+ {
+ }
+
+ /**
+ * Returns the number of copies to be printed.
+ *
+ * @return The number of copies to be printed.
+ */
+ public abstract int getCopies();
+
+ /**
+ * Sets the number of copies to be printed.
+ *
+ * @param copies The number of copies to be printed.
+ */
+ public abstract void setCopies(int copies);
+
+ /**
+ * Returns the name of the print job.
+ *
+ * @return The name of the print job.
+ */
+ public abstract String getJobName();
+
+ /**
+ * Sets the name of the print job.
+ *
+ * @param job_name The name of the print job.
+ */
+ public abstract void setJobName(String job_name);
+
+ /**
+ * Returns the printing user name.
+ *
+ * @return The printing username.
+ */
+ public abstract String getUserName();
+
+ /**
+ * Cancels an in progress print job.
+ */
+ public abstract void cancel();
+
+ /**
+ * Tests whether or not this job has been cancelled.
+ *
+ * @return <code>true</code> if this job has been cancelled, <code>false</code>
+ * otherwise.
+ */
+ public abstract boolean isCancelled();
+
+ /**
+ * Returns an instance of the default page which will have the default
+ * paper and orientation.
+ *
+ * @return A default instance of <code>PageFormat</code>.
+ */
+ public PageFormat defaultPage()
+ {
+ return new PageFormat();
+ }
+
+ /**
+ * Clones the specified <code>PageFormat</code> object then alters the
+ * clone so that it represents the default page format.
+ *
+ * @param page_format The <code>PageFormat</code> to clone.
+ *
+ * @return A new default page format.
+ */
+ public abstract PageFormat defaultPage(PageFormat page_format);
+
+ /**
+ * Displays a dialog box to the user which allows the page format
+ * attributes to be modified.
+ *
+ * @param page_format The <code>PageFormat</code> object to modify.
+ *
+ * @return The modified <code>PageFormat</code>.
+ */
+ public abstract PageFormat pageDialog(PageFormat page_format)
+ throws HeadlessException;
+
+ /**
+ * @since 1.4
+ */
+ public PageFormat pageDialog(PrintRequestAttributeSet attributes)
+ throws HeadlessException
+ {
+ // FIXME: Implement this for real.
+ return pageDialog((PageFormat) null);
+ }
+
+ /**
+ * Prints the pages.
+ */
+ public abstract void print () throws PrinterException;
+
+ /**
+ * Prints the page with given attributes.
+ */
+ public void print (PrintRequestAttributeSet attributes)
+ throws PrinterException
+ {
+ print ();
+ }
+
+ /**
+ * Displays a dialog box to the user which allows the print job
+ * attributes to be modified.
+ *
+ * @return <code>false</code> if the user cancels the dialog box,
+ * <code>true</code> otherwise.
+ */
+ public abstract boolean printDialog()
+ throws HeadlessException;
+
+ /**
+ * Displays a dialog box to the user which allows the print job
+ * attributes to be modified.
+ *
+ * @return <code>false</code> if the user cancels the dialog box,
+ * <code>true</code> otherwise.
+ */
+ public boolean printDialog(PrintRequestAttributeSet attributes)
+ throws HeadlessException
+ {
+ // FIXME: Implement this for real.
+ return printDialog();
+ }
+
+ /**
+ * This sets the pages that are to be printed.
+ *
+ * @param pageable The pages to be printed, which may not be <code>null</code>.
+ */
+ public abstract void setPageable(Pageable pageable);
+
+ /**
+ * Sets this specified <code>Printable</code> as the one to use for
+ * rendering the pages on the print device.
+ *
+ * @param printable The <code>Printable</code> for the print job.
+ */
+ public abstract void setPrintable(Printable printable);
+
+ /**
+ * Sets the <code>Printable</code> and the page format for the pages
+ * to be printed.
+ *
+ * @param printable The <code>Printable</code> for the print job.
+ * @param page_format The <code>PageFormat</code> for the print job.
+ */
+ public abstract void setPrintable(Printable printable, PageFormat page_format);
+
+ /**
+ * Makes any alterations to the specified <code>PageFormat</code>
+ * necessary to make it work with the current printer. The alterations
+ * are made to a clone of the input object, which is then returned.
+ *
+ * @param page_format The <code>PageFormat</code> to validate.
+ *
+ * @return The validated <code>PageFormat</code>.
+ */
+ public abstract PageFormat validatePage(PageFormat page_format);
+
+ /**
+ * Find and return 2D image print services.
+ *
+ * This is the same as calling PrintServiceLookup.lookupPrintServices()
+ * with Pageable service-specified DocFlavor.
+ * @return Array of PrintService objects, could be empty.
+ * @since 1.4
+ */
+ public static PrintService[] lookupPrintServices()
+ {
+ return PrintServiceLookup.lookupPrintServices
+ (
+ new DocFlavor("application/x-java-jvm-local-objectref",
+ "java.awt.print.Pageable"),
+ null);
+ }
+
+ /**
+ * Find and return 2D image stream print services.
+ *
+ * This is the same as calling
+ * StreamPrintServiceFactory.lookupStreamPrintServices()
+ * with Pageable service-specified DocFlavor.
+ * @param mimeType The output format mime type, or null for any type.
+ * @return Array of stream print services, could be empty.
+ * @since 1.4
+ */
+ public static StreamPrintServiceFactory[]
+ lookupStreamPrintServices(String mimeType)
+ {
+ return StreamPrintServiceFactory.lookupStreamPrintServiceFactories(
+ DocFlavor.SERVICE_FORMATTED.PAGEABLE, mimeType);
+ }
+
+ /**
+ * Return the printer for this job. If print services aren't supported by
+ * the subclass, returns null.
+ *
+ * @return The associated PrintService.
+ * @since 1.4
+ */
+ public PrintService getPrintService()
+ {
+ return printer;
+ }
+
+ /**
+ * Change the printer for this print job to service. Subclasses that
+ * support setting the print service override this method. Throws
+ * PrinterException when the class doesn't support setting the printer,
+ * the service doesn't support Pageable or Printable interfaces for 2D
+ * print output.
+ * @param service The new printer to use.
+ * @throws PrinterException if service is not valid.
+ */
+ public void setPrintService(PrintService service)
+ throws PrinterException
+ {
+ printer = service;
+ }
+}
diff --git a/libjava/classpath/java/awt/print/package.html b/libjava/classpath/java/awt/print/package.html
new file mode 100644
index 000000000..50abcbfad
--- /dev/null
+++ b/libjava/classpath/java/awt/print/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.awt.print package.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - java.awt.print</title></head>
+
+<body>
+<p>Classes for printer jobs, pages, paper sizes, graphics and formats.</p>
+
+</body>
+</html>