From 8aa540d2f783474d1d2e06f16744bf67b9c1facc Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Fri, 10 Mar 2006 21:46:48 +0000 Subject: Imported GNU Classpath 0.90 Imported GNU Classpath 0.90 * scripts/makemake.tcl: Set gnu/java/awt/peer/swing to ignore. * gnu/classpath/jdwp/VMFrame.java (SIZE): New constant. * java/lang/VMCompiler.java: Use gnu.java.security.hash.MD5. * java/lang/Math.java: New override file. * java/lang/Character.java: Merged from Classpath. (start, end): Now 'int's. (canonicalName): New field. (CANONICAL_NAME, NO_SPACES_NAME, CONSTANT_NAME): New constants. (UnicodeBlock): Added argument. (of): New overload. (forName): New method. Updated unicode blocks. (sets): Updated. * sources.am: Regenerated. * Makefile.in: Likewise. From-SVN: r111942 --- .../javax/crypto/EncryptedPrivateKeyInfo.java | 41 +- .../classpath/javax/imageio/ImageWriteParam.java | 94 + .../imageio/plugins/bmp/BMPImageWriteParam.java | 144 ++ .../javax/naming/AuthenticationException.java | 4 +- .../AuthenticationNotSupportedException.java | 4 +- libjava/classpath/javax/naming/Binding.java | 4 +- .../javax/naming/CannotProceedException.java | 4 +- .../javax/naming/CommunicationException.java | 4 +- .../javax/naming/ConfigurationException.java | 4 +- .../javax/naming/ContextNotEmptyException.java | 4 +- .../naming/InsufficientResourcesException.java | 4 +- .../javax/naming/InterruptedNamingException.java | 4 +- .../javax/naming/InvalidNameException.java | 4 +- .../javax/naming/LimitExceededException.java | 4 +- libjava/classpath/javax/naming/LinkException.java | 4 +- .../classpath/javax/naming/LinkLoopException.java | 4 +- .../javax/naming/MalformedLinkException.java | 4 +- .../javax/naming/NameAlreadyBoundException.java | 4 +- libjava/classpath/javax/naming/NameClassPair.java | 4 +- .../javax/naming/NameNotFoundException.java | 4 +- .../classpath/javax/naming/NamingException.java | 2 +- .../javax/naming/NoInitialContextException.java | 4 +- .../javax/naming/NoPermissionException.java | 4 +- .../javax/naming/NotContextException.java | 4 +- .../naming/OperationNotSupportedException.java | 4 +- .../javax/naming/PartialResultException.java | 4 +- libjava/classpath/javax/naming/Reference.java | 4 +- .../javax/naming/ServiceUnavailableException.java | 4 +- .../javax/naming/SizeLimitExceededException.java | 4 +- .../javax/naming/TimeLimitExceededException.java | 4 +- .../naming/directory/AttributeInUseException.java | 4 +- .../directory/AttributeModificationException.java | 3 +- .../InvalidAttributeIdentifierException.java | 4 +- .../directory/InvalidAttributeValueException.java | 4 +- .../directory/InvalidAttributesException.java | 4 +- .../directory/InvalidSearchControlsException.java | 4 +- .../directory/InvalidSearchFilterException.java | 4 +- .../javax/naming/directory/ModificationItem.java | 3 +- .../naming/directory/NoSuchAttributeException.java | 4 +- .../naming/directory/SchemaViolationException.java | 4 +- .../javax/naming/directory/SearchControls.java | 3 +- .../javax/naming/directory/SearchResult.java | 3 +- .../classpath/javax/naming/event/NamingEvent.java | 4 +- .../javax/naming/event/NamingExceptionEvent.java | 4 +- .../classpath/javax/naming/spi/ResolveResult.java | 4 +- libjava/classpath/javax/net/ssl/SSLException.java | 34 +- .../classpath/javax/print/CancelablePrintJob.java | 21 +- libjava/classpath/javax/print/Doc.java | 81 +- libjava/classpath/javax/print/DocFlavor.java | 671 +++++- libjava/classpath/javax/print/DocPrintJob.java | 76 +- libjava/classpath/javax/print/PrintService.java | 168 +- .../classpath/javax/print/ServiceUIFactory.java | 31 +- libjava/classpath/javax/print/SimpleDoc.java | 223 ++ .../classpath/javax/print/StreamPrintService.java | 19 +- .../javax/print/StreamPrintServiceFactory.java | 130 ++ .../print/attribute/AttributeSetUtilities.java | 52 +- .../javax/print/attribute/DateTimeSyntax.java | 10 + .../javax/print/attribute/HashAttributeSet.java | 37 +- .../print/attribute/standard/Compression.java | 6 +- .../javax/print/attribute/standard/Finishings.java | 6 +- .../print/attribute/standard/JobMediaSheets.java | 6 +- .../javax/print/attribute/standard/JobSheets.java | 6 +- .../javax/print/attribute/standard/JobState.java | 6 +- .../print/attribute/standard/JobStateReason.java | 6 +- .../print/attribute/standard/JobStateReasons.java | 2 +- .../javax/print/attribute/standard/Media.java | 6 +- .../attribute/standard/MediaPrintableArea.java | 22 +- .../javax/print/attribute/standard/MediaSize.java | 84 +- .../standard/MultipleDocumentHandling.java | 6 +- .../attribute/standard/PDLOverrideSupported.java | 6 +- .../print/attribute/standard/PrintQuality.java | 6 +- .../attribute/standard/PrinterIsAcceptingJobs.java | 2 +- .../attribute/standard/PrinterStateReason.java | 6 +- .../attribute/standard/PrinterStateReasons.java | 2 +- .../standard/ReferenceUriSchemesSupported.java | 6 +- .../security/auth/login/AppConfigurationEntry.java | 40 +- .../javax/security/auth/login/Configuration.java | 9 +- .../classpath/javax/sound/sampled/LineEvent.java | 24 +- libjava/classpath/javax/swing/AbstractAction.java | 102 +- libjava/classpath/javax/swing/AbstractButton.java | 8 + .../classpath/javax/swing/AbstractCellEditor.java | 29 +- .../classpath/javax/swing/AbstractListModel.java | 11 +- libjava/classpath/javax/swing/CellEditor.java | 42 +- .../classpath/javax/swing/CellRendererPane.java | 44 +- libjava/classpath/javax/swing/ComboBoxModel.java | 28 +- .../classpath/javax/swing/DefaultCellEditor.java | 350 +++- .../javax/swing/DefaultListCellRenderer.java | 2 +- .../javax/swing/DefaultListSelectionModel.java | 9 + libjava/classpath/javax/swing/ImageIcon.java | 4 +- libjava/classpath/javax/swing/JApplet.java | 2 +- libjava/classpath/javax/swing/JCheckBox.java | 2 +- libjava/classpath/javax/swing/JComponent.java | 332 +-- libjava/classpath/javax/swing/JDialog.java | 7 +- libjava/classpath/javax/swing/JEditorPane.java | 55 +- libjava/classpath/javax/swing/JFileChooser.java | 12 +- libjava/classpath/javax/swing/JFrame.java | 11 +- libjava/classpath/javax/swing/JInternalFrame.java | 65 +- libjava/classpath/javax/swing/JLayeredPane.java | 492 +++-- libjava/classpath/javax/swing/JMenu.java | 2 +- libjava/classpath/javax/swing/JMenuBar.java | 12 +- libjava/classpath/javax/swing/JOptionPane.java | 4 +- libjava/classpath/javax/swing/JPanel.java | 2 +- libjava/classpath/javax/swing/JPopupMenu.java | 2 +- libjava/classpath/javax/swing/JProgressBar.java | 16 +- libjava/classpath/javax/swing/JRootPane.java | 58 +- libjava/classpath/javax/swing/JSpinner.java | 317 ++- libjava/classpath/javax/swing/JSplitPane.java | 7 +- libjava/classpath/javax/swing/JTabbedPane.java | 81 +- libjava/classpath/javax/swing/JTable.java | 841 +++++--- libjava/classpath/javax/swing/JTextField.java | 20 +- libjava/classpath/javax/swing/JTextPane.java | 8 +- libjava/classpath/javax/swing/JTree.java | 17 +- libjava/classpath/javax/swing/JViewport.java | 104 +- libjava/classpath/javax/swing/JWindow.java | 54 +- libjava/classpath/javax/swing/Popup.java | 2 +- libjava/classpath/javax/swing/PopupFactory.java | 19 +- libjava/classpath/javax/swing/RepaintManager.java | 392 ++-- .../classpath/javax/swing/ScrollPaneLayout.java | 26 +- .../classpath/javax/swing/SpinnerDateModel.java | 150 +- .../classpath/javax/swing/SpinnerNumberModel.java | 187 +- libjava/classpath/javax/swing/Spring.java | 136 ++ libjava/classpath/javax/swing/SpringLayout.java | 29 +- libjava/classpath/javax/swing/SwingUtilities.java | 104 +- libjava/classpath/javax/swing/Timer.java | 7 +- libjava/classpath/javax/swing/ToolTipManager.java | 3 - libjava/classpath/javax/swing/UIManager.java | 6 +- .../swing/UnsupportedLookAndFeelException.java | 18 +- libjava/classpath/javax/swing/ViewportLayout.java | 91 +- .../classpath/javax/swing/event/CaretEvent.java | 53 +- .../classpath/javax/swing/event/DocumentEvent.java | 24 +- .../javax/swing/event/EventListenerList.java | 4 +- .../javax/swing/event/ListSelectionEvent.java | 173 +- .../javax/swing/event/ListSelectionListener.java | 26 +- .../javax/swing/event/MenuDragMouseEvent.java | 117 +- .../classpath/javax/swing/event/MenuKeyEvent.java | 113 +- .../swing/event/SwingPropertyChangeSupport.java | 278 +-- .../javax/swing/event/TableColumnModelEvent.java | 104 +- .../javax/swing/event/TableModelListener.java | 29 +- .../javax/swing/event/TreeExpansionEvent.java | 72 +- .../javax/swing/event/TreeModelEvent.java | 245 ++- .../javax/swing/event/TreeSelectionEvent.java | 45 +- .../javax/swing/event/UndoableEditEvent.java | 70 +- .../javax/swing/plaf/basic/BasicBorders.java | 36 +- .../swing/plaf/basic/BasicCheckBoxMenuItemUI.java | 1 - .../swing/plaf/basic/BasicColorChooserUI.java | 5 +- .../javax/swing/plaf/basic/BasicComboPopup.java | 16 + .../javax/swing/plaf/basic/BasicHTML.java | 297 ++- .../swing/plaf/basic/BasicInternalFrameUI.java | 70 +- .../javax/swing/plaf/basic/BasicLabelUI.java | 57 +- .../javax/swing/plaf/basic/BasicListUI.java | 40 +- .../javax/swing/plaf/basic/BasicLookAndFeel.java | 141 ++ .../javax/swing/plaf/basic/BasicMenuItemUI.java | 3 +- .../javax/swing/plaf/basic/BasicPopupMenuUI.java | 323 +-- .../plaf/basic/BasicRadioButtonMenuItemUI.java | 1 - .../javax/swing/plaf/basic/BasicRootPaneUI.java | 6 +- .../javax/swing/plaf/basic/BasicScrollBarUI.java | 42 +- .../javax/swing/plaf/basic/BasicSpinnerUI.java | 206 +- .../swing/plaf/basic/BasicSplitPaneDivider.java | 31 - .../javax/swing/plaf/basic/BasicSplitPaneUI.java | 108 +- .../javax/swing/plaf/basic/BasicTabbedPaneUI.java | 7 +- .../javax/swing/plaf/basic/BasicTableHeaderUI.java | 351 +++- .../javax/swing/plaf/basic/BasicTableUI.java | 160 +- .../javax/swing/plaf/basic/BasicTextUI.java | 250 ++- .../javax/swing/plaf/basic/BasicTreeUI.java | 297 ++- .../javax/swing/plaf/metal/MetalBorders.java | 93 +- .../javax/swing/plaf/metal/MetalFileChooserUI.java | 7 +- .../javax/swing/plaf/metal/MetalLookAndFeel.java | 13 + .../javax/swing/plaf/metal/MetalRootPaneUI.java | 909 ++++++++- .../javax/swing/plaf/metal/MetalScrollBarUI.java | 59 +- .../swing/plaf/metal/MetalSplitPaneDivider.java | 8 + .../javax/swing/plaf/metal/MetalUtils.java | 5 +- .../javax/swing/plaf/synth/ColorType.java | 130 ++ .../classpath/javax/swing/plaf/synth/Region.java | 474 +++++ .../javax/swing/plaf/synth/SynthConstants.java | 85 + .../javax/swing/plaf/synth/SynthContext.java | 134 ++ .../javax/swing/plaf/synth/SynthGraphicsUtils.java | 283 +++ .../javax/swing/plaf/synth/SynthLookAndFeel.java | 272 +++ .../javax/swing/plaf/synth/SynthPainter.java | 80 + .../javax/swing/plaf/synth/SynthStyle.java | 144 ++ .../javax/swing/plaf/synth/SynthStyleFactory.java | 64 + .../classpath/javax/swing/plaf/synth/package.html | 47 + .../swing/table/DefaultTableCellRenderer.java | 17 +- .../javax/swing/table/DefaultTableModel.java | 5 +- .../classpath/javax/swing/table/JTableHeader.java | 89 +- .../javax/swing/text/AbstractDocument.java | 167 +- .../classpath/javax/swing/text/AsyncBoxView.java | 1480 ++++++++++++++ libjava/classpath/javax/swing/text/BoxView.java | 594 ++++-- .../classpath/javax/swing/text/ComponentView.java | 3 +- .../classpath/javax/swing/text/CompositeView.java | 44 +- .../classpath/javax/swing/text/DefaultCaret.java | 123 +- .../javax/swing/text/DefaultEditorKit.java | 332 ++- .../javax/swing/text/DefaultFormatter.java | 7 +- .../javax/swing/text/DefaultHighlighter.java | 140 +- .../javax/swing/text/DefaultStyledDocument.java | 2145 ++++++++++++-------- .../classpath/javax/swing/text/DefaultTextUI.java | 1 + libjava/classpath/javax/swing/text/FlowView.java | 394 ++-- libjava/classpath/javax/swing/text/GapContent.java | 167 +- libjava/classpath/javax/swing/text/GlyphView.java | 126 +- libjava/classpath/javax/swing/text/IconView.java | 2 - .../classpath/javax/swing/text/JTextComponent.java | 395 +++- libjava/classpath/javax/swing/text/LabelView.java | 6 +- .../javax/swing/text/MutableAttributeSet.java | 64 +- .../javax/swing/text/NavigationFilter.java | 27 + .../classpath/javax/swing/text/ParagraphView.java | 203 +- .../classpath/javax/swing/text/PasswordView.java | 44 +- .../classpath/javax/swing/text/PlainDocument.java | 55 +- libjava/classpath/javax/swing/text/PlainView.java | 110 +- libjava/classpath/javax/swing/text/Segment.java | 120 +- .../javax/swing/text/SimpleAttributeSet.java | 195 +- .../classpath/javax/swing/text/StringContent.java | 138 +- .../classpath/javax/swing/text/StyleConstants.java | 823 +++++++- .../classpath/javax/swing/text/StyleContext.java | 25 +- libjava/classpath/javax/swing/text/TableView.java | 56 +- libjava/classpath/javax/swing/text/Utilities.java | 99 +- libjava/classpath/javax/swing/text/View.java | 136 +- .../javax/swing/text/WrappedPlainView.java | 3 +- .../classpath/javax/swing/text/html/FormView.java | 230 +++ libjava/classpath/javax/swing/text/html/HTML.java | 79 +- .../javax/swing/text/html/HTMLDocument.java | 193 +- .../javax/swing/text/html/HTMLEditorKit.java | 43 +- .../javax/swing/text/html/HTMLTableView.java | 82 + .../javax/swing/text/html/InlineView.java | 166 ++ .../classpath/javax/swing/text/html/NullView.java | 102 + .../javax/swing/text/html/ObjectView.java | 110 + .../classpath/javax/swing/text/html/Option.java | 157 ++ .../javax/swing/text/html/ParagraphView.java | 209 ++ libjava/classpath/javax/swing/text/package.html | 4 +- .../javax/swing/tree/DefaultTreeCellEditor.java | 208 +- libjava/classpath/javax/swing/undo/StateEdit.java | 6 +- .../classpath/javax/swing/undo/StateEditable.java | 6 +- .../javax/xml/parsers/DocumentBuilderFactory.java | 27 +- .../classpath/javax/xml/stream/EventFilter.java | 3 +- libjava/classpath/javax/xml/stream/Location.java | 7 +- .../classpath/javax/xml/stream/StreamFilter.java | 3 +- .../javax/xml/stream/XMLEventFactory.java | 6 +- .../classpath/javax/xml/stream/XMLEventReader.java | 22 +- .../classpath/javax/xml/stream/XMLEventWriter.java | 2 +- libjava/classpath/javax/xml/stream/XMLFilter.java | 46 - .../javax/xml/stream/XMLInputFactory.java | 28 +- .../classpath/javax/xml/stream/XMLIterator.java | 61 - .../javax/xml/stream/XMLOutputFactory.java | 30 +- .../classpath/javax/xml/stream/XMLReporter.java | 2 +- .../classpath/javax/xml/stream/XMLResolver.java | 24 +- .../javax/xml/stream/XMLStreamConstants.java | 16 +- .../javax/xml/stream/XMLStreamReader.java | 6 +- .../javax/xml/stream/events/EndEntity.java | 53 - .../javax/xml/stream/events/EntityDeclaration.java | 6 +- .../javax/xml/stream/events/EntityReference.java | 24 +- .../javax/xml/stream/events/StartEntity.java | 53 - .../javax/xml/stream/events/XMLEvent.java | 12 +- .../javax/xml/stream/util/EventReaderDelegate.java | 24 +- .../javax/xml/stream/util/ReaderDelegate.java | 10 +- .../javax/xml/validation/SchemaFactory.java | 8 +- 253 files changed, 17290 insertions(+), 6294 deletions(-) create mode 100644 libjava/classpath/javax/imageio/plugins/bmp/BMPImageWriteParam.java create mode 100644 libjava/classpath/javax/print/SimpleDoc.java create mode 100644 libjava/classpath/javax/print/StreamPrintServiceFactory.java create mode 100644 libjava/classpath/javax/swing/plaf/synth/ColorType.java create mode 100644 libjava/classpath/javax/swing/plaf/synth/Region.java create mode 100644 libjava/classpath/javax/swing/plaf/synth/SynthConstants.java create mode 100644 libjava/classpath/javax/swing/plaf/synth/SynthContext.java create mode 100644 libjava/classpath/javax/swing/plaf/synth/SynthGraphicsUtils.java create mode 100644 libjava/classpath/javax/swing/plaf/synth/SynthLookAndFeel.java create mode 100644 libjava/classpath/javax/swing/plaf/synth/SynthPainter.java create mode 100644 libjava/classpath/javax/swing/plaf/synth/SynthStyle.java create mode 100644 libjava/classpath/javax/swing/plaf/synth/SynthStyleFactory.java create mode 100644 libjava/classpath/javax/swing/plaf/synth/package.html create mode 100644 libjava/classpath/javax/swing/text/AsyncBoxView.java create mode 100644 libjava/classpath/javax/swing/text/html/FormView.java create mode 100644 libjava/classpath/javax/swing/text/html/HTMLTableView.java create mode 100644 libjava/classpath/javax/swing/text/html/InlineView.java create mode 100644 libjava/classpath/javax/swing/text/html/NullView.java create mode 100644 libjava/classpath/javax/swing/text/html/ObjectView.java create mode 100644 libjava/classpath/javax/swing/text/html/Option.java create mode 100644 libjava/classpath/javax/swing/text/html/ParagraphView.java delete mode 100644 libjava/classpath/javax/xml/stream/XMLFilter.java delete mode 100644 libjava/classpath/javax/xml/stream/XMLIterator.java delete mode 100644 libjava/classpath/javax/xml/stream/events/EndEntity.java delete mode 100644 libjava/classpath/javax/xml/stream/events/StartEntity.java (limited to 'libjava/classpath/javax') diff --git a/libjava/classpath/javax/crypto/EncryptedPrivateKeyInfo.java b/libjava/classpath/javax/crypto/EncryptedPrivateKeyInfo.java index a52d7b1..0fddd54 100644 --- a/libjava/classpath/javax/crypto/EncryptedPrivateKeyInfo.java +++ b/libjava/classpath/javax/crypto/EncryptedPrivateKeyInfo.java @@ -92,6 +92,9 @@ public class EncryptedPrivateKeyInfo /** The OID of the encryption algorithm. */ private OID algOid; + /** The encryption algorithm name. */ + private String algName; + /** The encryption algorithm's parameters. */ private AlgorithmParameters params; @@ -125,7 +128,8 @@ public class EncryptedPrivateKeyInfo throw new IllegalArgumentException("0-length encryptedData"); } this.params = params; - algOid = new OID(params.getAlgorithm()); + algName = params.getAlgorithm (); + algOid = getOid (algName); this.encryptedData = (byte[]) encryptedData.clone(); } @@ -168,10 +172,36 @@ public class EncryptedPrivateKeyInfo { throw new IllegalArgumentException("0-length encryptedData"); } - this.algOid = new OID(algName); + this.algName = algName.toString (); // do NP check + this.algOid = getOid (algName); this.encryptedData = (byte[]) encryptedData.clone(); } + /** + * Return the OID for the given cipher name. + * + * @param str The string. + * @throws NoSuchAlgorithmException If the OID is not known. + */ + private static OID getOid (final String str) + throws NoSuchAlgorithmException + { + if (str.equalsIgnoreCase ("DSA")) + { + return new OID ("1.2.840.10040.4.3"); + } + // FIXME add more + + try + { + return new OID (str); + } + catch (Throwable t) + { + } + throw new NoSuchAlgorithmException ("cannot determine OID for '" + str + "'"); + } + // Instance methods. // ------------------------------------------------------------------------ @@ -196,6 +226,7 @@ public class EncryptedPrivateKeyInfo } catch (NoSuchAlgorithmException ignore) { + // FIXME throw exception? } catch (IOException ignore) { @@ -272,7 +303,11 @@ public class EncryptedPrivateKeyInfo getAlgParameters(); if (params != null) { - algId.add(DERReader.read(params.getEncoded())); + algId.add (DERReader.read (params.getEncoded())); + } + else + { + algId.add (new DERValue (DER.NULL, null)); } List epki = new ArrayList(2); epki.add(new DERValue(DER.CONSTRUCTED|DER.SEQUENCE, algId)); diff --git a/libjava/classpath/javax/imageio/ImageWriteParam.java b/libjava/classpath/javax/imageio/ImageWriteParam.java index 84b257e..1979957 100644 --- a/libjava/classpath/javax/imageio/ImageWriteParam.java +++ b/libjava/classpath/javax/imageio/ImageWriteParam.java @@ -46,27 +46,121 @@ import java.util.Locale; */ public class ImageWriteParam extends IIOParam { + + /** + * Can be passed to setTilingMode, setProgressiveMode and + * setCompressionMode to disable feature. + */ public static final int MODE_DISABLED = 0; + + /** + * Can be passed to setTilingMode, setProgressiveMode and + * setCompressionMode to enable feature. + */ public static final int MODE_DEFAULT = 1; + + /** + * Can be passed to setTilingMode, setCompressionMode to disable feature. + */ public static final int MODE_EXPLICIT = 2; + + /** + * Can be passed to setTilingMode, setProgressiveMode and + * setCompressionMode to enable feature. + */ public static final int MODE_COPY_FROM_METADATA = 3; + /** + * True if tiling grid offset parameters can be set. + */ protected boolean canOffsetTiles; + + /** + * True if this writer can write images using compression. + */ protected boolean canWriteCompressed; + + /** + * True if images can be written as a progressive sequence + * of increasing quality. + */ protected boolean canWriteProgressive; + + /** + * True if tile width and height parameters can be set. + */ protected boolean canWriteTiles; + + /** + * Controls compression settings, which must be set to one of the four + * MODE_* values. + */ protected int compressionMode = MODE_COPY_FROM_METADATA; + + /** + * Contains the current compression quality setting. + */ protected float compressionQuality; + + /** + * Contains the name of the available compression types. + */ protected String compressionType; + + /** + * Array of the names of the available compression types. + */ protected String[] compressionTypes; + + /** + * Localizes compression type names and quality descriptions, + * or null to use default Locale. + */ protected Locale locale; + + /** + * Preferred tile size range pairs. + */ protected Dimension[] preferredTileSizes; + + /** + * The mode controlling progressive encoding, which must + * be set to one of the four MODE_* values, except + * MODE_EXPLICIT. + */ protected int progressiveMode = MODE_COPY_FROM_METADATA; + + /** + * The amount by which the tile grid origin should be offset + * horizontally from the image origin if tiling has been set. + */ protected int tileGridXOffset; + + /** + * The amount by which the tile grid origin should be offset + * vertically from the image origin if tiling has been set. + */ protected int tileGridYOffset; + + /** + * The height of each tile if tiling has been set. + */ protected int tileHeight; + + /** + * The width of each tile if tiling has been set. + */ protected int tileWidth; + + /** + * The mode controlling tiling settings, which must be + * set to one of the four MODE_* values. + */ protected int tilingMode; + + /** + * True if the tiling parameters have been specified. + */ protected boolean tilingSet; /** diff --git a/libjava/classpath/javax/imageio/plugins/bmp/BMPImageWriteParam.java b/libjava/classpath/javax/imageio/plugins/bmp/BMPImageWriteParam.java new file mode 100644 index 0000000..de59efb --- /dev/null +++ b/libjava/classpath/javax/imageio/plugins/bmp/BMPImageWriteParam.java @@ -0,0 +1,144 @@ +/* BMPImageWriteParam.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 javax.imageio.plugins.bmp; + +import java.util.Locale; + +import javax.imageio.ImageWriteParam; + +/** + * A class to encode images in the BMP format. + * By default, the data layout is bottom-up, such that the pixels are stored in + * bottom-up order. + * + * The compression scheme can be specified by using setCompressionType() + * appropriate type string. The compression scheme specified will be honored + * if it is compatible with the type of image being written. If the + * compression scheme is not compatible with the type of image being written, + * then an IOException will be thrown by the BMP image writer. If the + * compression type is not set, then getCompressionType() will return null. + * In this case the BMP image writer will select a compression type that + * supports encoding of the given image without loss of the color resolution. + * + * The compression type strings and the image type each supports are: + * Uncompressed RLE: BI_RGB, image type: <= 8-bits/sample. + * 8-bit Run Length Encoding: BI_RLE8, image type: <= 8-bits/sample + * 4-bit Run Length Encoding: BI_RLE4, image type: <= 4-bits/sample + * Packed data: BI_BITFIELDS, image type: 16 or 32 bits/sample + * + * @author Lillian Angel (langel at redhat dot com) + */ +public class BMPImageWriteParam + extends ImageWriteParam +{ + + /** + * This boolean is true if the data will be written in a topdown manner. + */ + private boolean topDown; + + /** + * Compression type strings. + */ + String rgb = "BI_RGB"; + String rle8 = "BI_RLE8"; + String rle4 = "BI_RLE4"; + String bitfields = "BI_BITFIELDS"; + + /** + * Constants to represent image types. + */ + static final int BI_RGB = 0; + static final int BI_RLE8 = 1; + static final int BI_RLE4 = 2; + static final int BI_BITFIELDS = 3; + + /** + * Constructs an BMPImageWriteParam object with default values + * and a null Locale. + */ + public BMPImageWriteParam() + { + this(null); + } + + /** + * Constructs a BMPImageWriteParam set to use a given + * Locale and with default values for all parameters. + * + * @param locale - a Locale to be used to localize compression + * type names and quality descriptions, or null. + */ + public BMPImageWriteParam(Locale locale) + { + super(locale); + topDown = false; + canWriteCompressed = true; + + compressionTypes = new String[4]; + compressionTypes[BI_RGB] = rgb; + compressionTypes[BI_RLE8] = rle8; + compressionTypes[BI_RLE4] = rle4; + compressionTypes[BI_BITFIELDS] = bitfields; + + compressionType = compressionTypes[BI_RGB]; + } + + /** + * If set, the data will be written out in a top-down manner, the first + * scanline being written first. + * + * @param topDown - whether the data are written in top-down order. + */ + public void setTopDown(boolean topDown) + { + this.topDown = topDown; + } + + /** + * Returns the value of the topDown parameter. The default is + * false. + * + * @return whether the data are written in top-down order. + */ + public boolean isTopDown() + { + return topDown; + } +} diff --git a/libjava/classpath/javax/naming/AuthenticationException.java b/libjava/classpath/javax/naming/AuthenticationException.java index f332561..1a6ade9 100644 --- a/libjava/classpath/javax/naming/AuthenticationException.java +++ b/libjava/classpath/javax/naming/AuthenticationException.java @@ -1,5 +1,5 @@ /* AuthenticationException.java -- - Copyright (C) 2000, 2004 Free Software Foundation, Inc. + Copyright (C) 2000, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,6 +41,8 @@ package javax.naming; public class AuthenticationException extends NamingSecurityException { + private static final long serialVersionUID = 3678497619904568096L; + public AuthenticationException () { super (); diff --git a/libjava/classpath/javax/naming/AuthenticationNotSupportedException.java b/libjava/classpath/javax/naming/AuthenticationNotSupportedException.java index 52b133a..a1e811b 100644 --- a/libjava/classpath/javax/naming/AuthenticationNotSupportedException.java +++ b/libjava/classpath/javax/naming/AuthenticationNotSupportedException.java @@ -1,5 +1,5 @@ /* AuthenticationNotSupportedException.java -- - Copyright (C) 2000, 2004 Free Software Foundation, Inc. + Copyright (C) 2000, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -42,6 +42,8 @@ package javax.naming; public class AuthenticationNotSupportedException extends NamingSecurityException { + private static final long serialVersionUID = - 7149033933259492300L; + public AuthenticationNotSupportedException () { super (); diff --git a/libjava/classpath/javax/naming/Binding.java b/libjava/classpath/javax/naming/Binding.java index 91c0d95..9d6608a 100644 --- a/libjava/classpath/javax/naming/Binding.java +++ b/libjava/classpath/javax/naming/Binding.java @@ -1,5 +1,5 @@ /* Binding.java -- - Copyright (C) 2001, 2005 Free Software Foundation, Inc. + Copyright (C) 2001, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -44,6 +44,8 @@ package javax.naming; */ public class Binding extends NameClassPair { + private static final long serialVersionUID = 8839217842691845890L; + public Binding (String name, Object obj) { super (name, null); diff --git a/libjava/classpath/javax/naming/CannotProceedException.java b/libjava/classpath/javax/naming/CannotProceedException.java index 3a69cd3..27868e2 100644 --- a/libjava/classpath/javax/naming/CannotProceedException.java +++ b/libjava/classpath/javax/naming/CannotProceedException.java @@ -1,5 +1,5 @@ /* CannotProceedException.java -- - Copyright (C) 2001, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2001, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -47,6 +47,8 @@ import java.util.Hashtable; public class CannotProceedException extends NamingException { + private static final long serialVersionUID = 1219724816191576813L; + // Serialized fields. protected Name remainingNewName; protected Hashtable environment; diff --git a/libjava/classpath/javax/naming/CommunicationException.java b/libjava/classpath/javax/naming/CommunicationException.java index c780387..7b11b5f 100644 --- a/libjava/classpath/javax/naming/CommunicationException.java +++ b/libjava/classpath/javax/naming/CommunicationException.java @@ -1,5 +1,5 @@ /* CommunicationException.java -- - Copyright (C) 2000, 2004 Free Software Foundation, Inc. + Copyright (C) 2000, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,6 +41,8 @@ package javax.naming; public class CommunicationException extends NamingException { + private static final long serialVersionUID = 3618507780299986611L; + public CommunicationException () { super (); diff --git a/libjava/classpath/javax/naming/ConfigurationException.java b/libjava/classpath/javax/naming/ConfigurationException.java index 1966548..1f4002a 100644 --- a/libjava/classpath/javax/naming/ConfigurationException.java +++ b/libjava/classpath/javax/naming/ConfigurationException.java @@ -1,5 +1,5 @@ /* ConfigurationException.java -- - Copyright (C) 2000, 2004 Free Software Foundation, Inc. + Copyright (C) 2000, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,6 +41,8 @@ package javax.naming; public class ConfigurationException extends NamingException { + private static final long serialVersionUID = - 2535156726228855704L; + public ConfigurationException () { super (); diff --git a/libjava/classpath/javax/naming/ContextNotEmptyException.java b/libjava/classpath/javax/naming/ContextNotEmptyException.java index c6fe5e8..acbd46b 100644 --- a/libjava/classpath/javax/naming/ContextNotEmptyException.java +++ b/libjava/classpath/javax/naming/ContextNotEmptyException.java @@ -1,5 +1,5 @@ /* ContextNotEmptyException.java -- - Copyright (C) 2000, 2004 Free Software Foundation, Inc. + Copyright (C) 2000, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,6 +41,8 @@ package javax.naming; public class ContextNotEmptyException extends NamingException { + private static final long serialVersionUID = 1090963683348219877L; + public ContextNotEmptyException () { super (); diff --git a/libjava/classpath/javax/naming/InsufficientResourcesException.java b/libjava/classpath/javax/naming/InsufficientResourcesException.java index bcb9fe5..7a9ebe0 100644 --- a/libjava/classpath/javax/naming/InsufficientResourcesException.java +++ b/libjava/classpath/javax/naming/InsufficientResourcesException.java @@ -1,5 +1,5 @@ /* InsufficientResourcesException.java -- - Copyright (C) 2000, 2004 Free Software Foundation, Inc. + Copyright (C) 2000, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,6 +41,8 @@ package javax.naming; public class InsufficientResourcesException extends NamingException { + private static final long serialVersionUID = 6227672693037844532L; + public InsufficientResourcesException () { super (); diff --git a/libjava/classpath/javax/naming/InterruptedNamingException.java b/libjava/classpath/javax/naming/InterruptedNamingException.java index 8cdf30d..90d6e5e 100644 --- a/libjava/classpath/javax/naming/InterruptedNamingException.java +++ b/libjava/classpath/javax/naming/InterruptedNamingException.java @@ -1,5 +1,5 @@ /* InterruptedNamingException.java -- - Copyright (C) 2000, 2004 Free Software Foundation, Inc. + Copyright (C) 2000, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,6 +41,8 @@ package javax.naming; public class InterruptedNamingException extends NamingException { + private static final long serialVersionUID = 6404516648893194728L; + public InterruptedNamingException () { super (); diff --git a/libjava/classpath/javax/naming/InvalidNameException.java b/libjava/classpath/javax/naming/InvalidNameException.java index a3b99e1..286f045 100644 --- a/libjava/classpath/javax/naming/InvalidNameException.java +++ b/libjava/classpath/javax/naming/InvalidNameException.java @@ -1,5 +1,5 @@ /* InvalidNameException.java -- Exception indicating an invalid component/name - Copyright (C) 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 2000, 2001, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -47,6 +47,8 @@ package javax.naming; */ public class InvalidNameException extends NamingException { + private static final long serialVersionUID = - 8370672380823801105L; + /** * Creates a new exception without setting any of its fields. */ diff --git a/libjava/classpath/javax/naming/LimitExceededException.java b/libjava/classpath/javax/naming/LimitExceededException.java index 7e7af81..8c005ac 100644 --- a/libjava/classpath/javax/naming/LimitExceededException.java +++ b/libjava/classpath/javax/naming/LimitExceededException.java @@ -1,5 +1,5 @@ /* LimitExceededException.java -- - Copyright (C) 2000, 2004 Free Software Foundation, Inc. + Copyright (C) 2000, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,6 +41,8 @@ package javax.naming; public class LimitExceededException extends NamingException { + private static final long serialVersionUID = - 776898738660207856L; + public LimitExceededException () { super (); diff --git a/libjava/classpath/javax/naming/LinkException.java b/libjava/classpath/javax/naming/LinkException.java index 2c3c507..8f5df8b 100644 --- a/libjava/classpath/javax/naming/LinkException.java +++ b/libjava/classpath/javax/naming/LinkException.java @@ -1,5 +1,5 @@ /* LinkException.java -- - Copyright (C) 2001, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2001, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -46,6 +46,8 @@ package javax.naming; public class LinkException extends NamingException { + private static final long serialVersionUID = - 7967662604076777712L; + // Serialized fields. protected Name linkResolvedName; protected Object linkResolvedObj; diff --git a/libjava/classpath/javax/naming/LinkLoopException.java b/libjava/classpath/javax/naming/LinkLoopException.java index 9c00dbe..0c68e01 100644 --- a/libjava/classpath/javax/naming/LinkLoopException.java +++ b/libjava/classpath/javax/naming/LinkLoopException.java @@ -1,5 +1,5 @@ /* LinkLoopException.java -- - Copyright (C) 2000, 2004 Free Software Foundation, Inc. + Copyright (C) 2000, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,6 +41,8 @@ package javax.naming; public class LinkLoopException extends LinkException { + private static final long serialVersionUID = - 3119189944325198009L; + public LinkLoopException () { super (); diff --git a/libjava/classpath/javax/naming/MalformedLinkException.java b/libjava/classpath/javax/naming/MalformedLinkException.java index 5422b90..db0753d 100644 --- a/libjava/classpath/javax/naming/MalformedLinkException.java +++ b/libjava/classpath/javax/naming/MalformedLinkException.java @@ -1,5 +1,5 @@ /* MalformedLinkException.java -- - Copyright (C) 2000, 2004 Free Software Foundation, Inc. + Copyright (C) 2000, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,6 +41,8 @@ package javax.naming; public class MalformedLinkException extends LinkException { + private static final long serialVersionUID = - 3066740437737830242L; + public MalformedLinkException () { super (); diff --git a/libjava/classpath/javax/naming/NameAlreadyBoundException.java b/libjava/classpath/javax/naming/NameAlreadyBoundException.java index 4b2fb0e..5ddd7d8 100644 --- a/libjava/classpath/javax/naming/NameAlreadyBoundException.java +++ b/libjava/classpath/javax/naming/NameAlreadyBoundException.java @@ -1,5 +1,5 @@ /* NameAlreadyBoundException.java -- - Copyright (C) 2000, 2004 Free Software Foundation, Inc. + Copyright (C) 2000, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,6 +41,8 @@ package javax.naming; public class NameAlreadyBoundException extends NamingException { + private static final long serialVersionUID = - 8491441000356780586L; + public NameAlreadyBoundException () { super (); diff --git a/libjava/classpath/javax/naming/NameClassPair.java b/libjava/classpath/javax/naming/NameClassPair.java index 4e26051..127730a 100644 --- a/libjava/classpath/javax/naming/NameClassPair.java +++ b/libjava/classpath/javax/naming/NameClassPair.java @@ -1,5 +1,5 @@ /* NameClassPair.java -- - Copyright (C) 2001, 2005 Free Software Foundation, Inc. + Copyright (C) 2001, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -46,6 +46,8 @@ import java.io.Serializable; */ public class NameClassPair implements Serializable { + private static final long serialVersionUID = 5620776610160863339L; + public NameClassPair (String name, String className) { this (name, className, true); diff --git a/libjava/classpath/javax/naming/NameNotFoundException.java b/libjava/classpath/javax/naming/NameNotFoundException.java index b533b04..b7c24a6 100644 --- a/libjava/classpath/javax/naming/NameNotFoundException.java +++ b/libjava/classpath/javax/naming/NameNotFoundException.java @@ -1,5 +1,5 @@ /* NameNotFoundException.java -- - Copyright (C) 2000, 2004 Free Software Foundation, Inc. + Copyright (C) 2000, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,6 +41,8 @@ package javax.naming; public class NameNotFoundException extends NamingException { + private static final long serialVersionUID = - 8007156725367842053L; + public NameNotFoundException () { super (); diff --git a/libjava/classpath/javax/naming/NamingException.java b/libjava/classpath/javax/naming/NamingException.java index ad39233..dbe1e37 100644 --- a/libjava/classpath/javax/naming/NamingException.java +++ b/libjava/classpath/javax/naming/NamingException.java @@ -223,7 +223,7 @@ public class NamingException extends Exception /** * Gets the message given to the constructor or null if no message was given. * - * @see Throwable#getMessage(); + * @see Throwable#getMessage() */ public String getExplanation() { diff --git a/libjava/classpath/javax/naming/NoInitialContextException.java b/libjava/classpath/javax/naming/NoInitialContextException.java index d12dfcb..5e4f6df 100644 --- a/libjava/classpath/javax/naming/NoInitialContextException.java +++ b/libjava/classpath/javax/naming/NoInitialContextException.java @@ -1,5 +1,5 @@ /* NoInitialContextException.java -- - Copyright (C) 2000, 2004 Free Software Foundation, Inc. + Copyright (C) 2000, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,6 +41,8 @@ package javax.naming; public class NoInitialContextException extends NamingException { + private static final long serialVersionUID = - 3413733186901258623L; + public NoInitialContextException() { super(); diff --git a/libjava/classpath/javax/naming/NoPermissionException.java b/libjava/classpath/javax/naming/NoPermissionException.java index ddc4393..02764a9 100644 --- a/libjava/classpath/javax/naming/NoPermissionException.java +++ b/libjava/classpath/javax/naming/NoPermissionException.java @@ -1,5 +1,5 @@ /* NoPermissionException.java -- - Copyright (C) 2000, 2004 Free Software Foundation, Inc. + Copyright (C) 2000, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,6 +41,8 @@ package javax.naming; public class NoPermissionException extends NamingSecurityException { + private static final long serialVersionUID = 8395332708699751775L; + public NoPermissionException () { super (); diff --git a/libjava/classpath/javax/naming/NotContextException.java b/libjava/classpath/javax/naming/NotContextException.java index b3d02cf..a27f10f 100644 --- a/libjava/classpath/javax/naming/NotContextException.java +++ b/libjava/classpath/javax/naming/NotContextException.java @@ -1,5 +1,5 @@ /* NotContextException.java -- - Copyright (C) 2000, 2004 Free Software Foundation, Inc. + Copyright (C) 2000, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,6 +41,8 @@ package javax.naming; public class NotContextException extends NamingException { + private static final long serialVersionUID = 849752551644540417L; + public NotContextException () { super (); diff --git a/libjava/classpath/javax/naming/OperationNotSupportedException.java b/libjava/classpath/javax/naming/OperationNotSupportedException.java index a4a4945..d813403 100644 --- a/libjava/classpath/javax/naming/OperationNotSupportedException.java +++ b/libjava/classpath/javax/naming/OperationNotSupportedException.java @@ -1,5 +1,5 @@ /* OperationNotSupportedException.java -- - Copyright (C) 2000 Free Software Foundation, Inc. + Copyright (C) 2000, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -40,6 +40,8 @@ package javax.naming; public class OperationNotSupportedException extends NamingException { + private static final long serialVersionUID = 5493232822427682064L; + public OperationNotSupportedException() { super(); diff --git a/libjava/classpath/javax/naming/PartialResultException.java b/libjava/classpath/javax/naming/PartialResultException.java index 32f389d..6166078 100644 --- a/libjava/classpath/javax/naming/PartialResultException.java +++ b/libjava/classpath/javax/naming/PartialResultException.java @@ -1,5 +1,5 @@ /* PartialResultException.java -- - Copyright (C) 2000, 2004 Free Software Foundation, Inc. + Copyright (C) 2000, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,6 +41,8 @@ package javax.naming; public class PartialResultException extends NamingException { + private static final long serialVersionUID = 2572144970049426786L; + public PartialResultException () { super (); diff --git a/libjava/classpath/javax/naming/Reference.java b/libjava/classpath/javax/naming/Reference.java index 6cc4d15..5b9883a 100644 --- a/libjava/classpath/javax/naming/Reference.java +++ b/libjava/classpath/javax/naming/Reference.java @@ -1,5 +1,5 @@ /* Reference.java -- - Copyright (C) 2000, 2001, 2005 Free Software Foundation, Inc. + Copyright (C) 2000, 2001, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -48,6 +48,8 @@ import java.util.Vector; */ public class Reference implements Cloneable, Serializable { + private static final long serialVersionUID = - 1673475790065791735L; + public Reference (String className) { this.className = className; diff --git a/libjava/classpath/javax/naming/ServiceUnavailableException.java b/libjava/classpath/javax/naming/ServiceUnavailableException.java index 678eb13..ddb154f 100644 --- a/libjava/classpath/javax/naming/ServiceUnavailableException.java +++ b/libjava/classpath/javax/naming/ServiceUnavailableException.java @@ -1,5 +1,5 @@ /* ServiceUnavailableException.java -- - Copyright (C) 2000, 2004 Free Software Foundation, Inc. + Copyright (C) 2000, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,6 +41,8 @@ package javax.naming; public class ServiceUnavailableException extends NamingException { + private static final long serialVersionUID = - 4996964726566773444L; + public ServiceUnavailableException () { super (); diff --git a/libjava/classpath/javax/naming/SizeLimitExceededException.java b/libjava/classpath/javax/naming/SizeLimitExceededException.java index e23f4d2..3ca9a23 100644 --- a/libjava/classpath/javax/naming/SizeLimitExceededException.java +++ b/libjava/classpath/javax/naming/SizeLimitExceededException.java @@ -1,5 +1,5 @@ /* SizeLimitExceededException.java -- - Copyright (C) 2000, 2004 Free Software Foundation, Inc. + Copyright (C) 2000, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,6 +41,8 @@ package javax.naming; public class SizeLimitExceededException extends LimitExceededException { + private static final long serialVersionUID = 7129289564879168579L; + public SizeLimitExceededException () { super (); diff --git a/libjava/classpath/javax/naming/TimeLimitExceededException.java b/libjava/classpath/javax/naming/TimeLimitExceededException.java index f4be675..e3456f5 100644 --- a/libjava/classpath/javax/naming/TimeLimitExceededException.java +++ b/libjava/classpath/javax/naming/TimeLimitExceededException.java @@ -1,5 +1,5 @@ /* TimeLimitExceededException.java -- - Copyright (C) 2000, 2004 Free Software Foundation, Inc. + Copyright (C) 2000, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,6 +41,8 @@ package javax.naming; public class TimeLimitExceededException extends LimitExceededException { + private static final long serialVersionUID = - 3597009011385034696L; + public TimeLimitExceededException () { super (); diff --git a/libjava/classpath/javax/naming/directory/AttributeInUseException.java b/libjava/classpath/javax/naming/directory/AttributeInUseException.java index 4661424..9be25c9 100644 --- a/libjava/classpath/javax/naming/directory/AttributeInUseException.java +++ b/libjava/classpath/javax/naming/directory/AttributeInUseException.java @@ -1,5 +1,5 @@ /* AttributeInUseException.java -- - Copyright (C) 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 2000, 2001, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -42,6 +42,8 @@ import javax.naming.NamingException; public class AttributeInUseException extends NamingException { + private static final long serialVersionUID = 4437710305529322564L; + public AttributeInUseException () { super (); diff --git a/libjava/classpath/javax/naming/directory/AttributeModificationException.java b/libjava/classpath/javax/naming/directory/AttributeModificationException.java index 4ef6fc2..9614bac 100644 --- a/libjava/classpath/javax/naming/directory/AttributeModificationException.java +++ b/libjava/classpath/javax/naming/directory/AttributeModificationException.java @@ -1,5 +1,5 @@ /* AttributeModificationException.java -- - Copyright (C) 2001, 2005 Free Software Foundation, Inc. + Copyright (C) 2001, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -47,6 +47,7 @@ import javax.naming.NamingException; public class AttributeModificationException extends NamingException { + private static final long serialVersionUID = 8060676069678710186L; // Serialized fields. private ModificationItem[] unexecs; diff --git a/libjava/classpath/javax/naming/directory/InvalidAttributeIdentifierException.java b/libjava/classpath/javax/naming/directory/InvalidAttributeIdentifierException.java index af1a8c7..afd9a90 100644 --- a/libjava/classpath/javax/naming/directory/InvalidAttributeIdentifierException.java +++ b/libjava/classpath/javax/naming/directory/InvalidAttributeIdentifierException.java @@ -1,5 +1,5 @@ /* InvalidAttributeIdentifierException.java -- - Copyright (C) 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 2000, 2001, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -42,6 +42,8 @@ import javax.naming.NamingException; public class InvalidAttributeIdentifierException extends NamingException { + private static final long serialVersionUID = - 9036920266322999923L; + public InvalidAttributeIdentifierException () { super (); diff --git a/libjava/classpath/javax/naming/directory/InvalidAttributeValueException.java b/libjava/classpath/javax/naming/directory/InvalidAttributeValueException.java index b667fa9..a18adbf 100644 --- a/libjava/classpath/javax/naming/directory/InvalidAttributeValueException.java +++ b/libjava/classpath/javax/naming/directory/InvalidAttributeValueException.java @@ -1,5 +1,5 @@ /* InvalidAttributeValueException.java -- - Copyright (C) 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 2000, 2001, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -42,6 +42,8 @@ import javax.naming.NamingException; public class InvalidAttributeValueException extends NamingException { + private static final long serialVersionUID = 8720050295499275011L; + public InvalidAttributeValueException () { super (); diff --git a/libjava/classpath/javax/naming/directory/InvalidAttributesException.java b/libjava/classpath/javax/naming/directory/InvalidAttributesException.java index ad7f7c1..ac540e2 100644 --- a/libjava/classpath/javax/naming/directory/InvalidAttributesException.java +++ b/libjava/classpath/javax/naming/directory/InvalidAttributesException.java @@ -1,5 +1,5 @@ /* InvalidAttributesException.java -- - Copyright (C) 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 2000, 2001, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -42,6 +42,8 @@ import javax.naming.NamingException; public class InvalidAttributesException extends NamingException { + private static final long serialVersionUID = 2607612850539889765L; + public InvalidAttributesException () { super (); diff --git a/libjava/classpath/javax/naming/directory/InvalidSearchControlsException.java b/libjava/classpath/javax/naming/directory/InvalidSearchControlsException.java index 594e5d1..9c716fa 100644 --- a/libjava/classpath/javax/naming/directory/InvalidSearchControlsException.java +++ b/libjava/classpath/javax/naming/directory/InvalidSearchControlsException.java @@ -1,5 +1,5 @@ /* InvalidSearchControlsException.java -- - Copyright (C) 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 2000, 2001, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -42,6 +42,8 @@ import javax.naming.NamingException; public class InvalidSearchControlsException extends NamingException { + private static final long serialVersionUID = - 5124108943352665777L; + public InvalidSearchControlsException () { super (); diff --git a/libjava/classpath/javax/naming/directory/InvalidSearchFilterException.java b/libjava/classpath/javax/naming/directory/InvalidSearchFilterException.java index 127b381..21843cc 100644 --- a/libjava/classpath/javax/naming/directory/InvalidSearchFilterException.java +++ b/libjava/classpath/javax/naming/directory/InvalidSearchFilterException.java @@ -1,5 +1,5 @@ /* InvalidSearchFilterException.java -- - Copyright (C) 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 2000, 2001, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -42,6 +42,8 @@ import javax.naming.NamingException; public class InvalidSearchFilterException extends NamingException { + private static final long serialVersionUID = 2902700940682875441L; + public InvalidSearchFilterException () { super (); diff --git a/libjava/classpath/javax/naming/directory/ModificationItem.java b/libjava/classpath/javax/naming/directory/ModificationItem.java index f0a69f5..56a5ae6 100644 --- a/libjava/classpath/javax/naming/directory/ModificationItem.java +++ b/libjava/classpath/javax/naming/directory/ModificationItem.java @@ -1,5 +1,5 @@ /* ModificationItem.java -- - Copyright (C) 2001, 2005 Free Software Foundation, Inc. + Copyright (C) 2001, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -47,6 +47,7 @@ import java.io.Serializable; public class ModificationItem implements Serializable { + private static final long serialVersionUID = 7573258562534746850L; // Serialized fields. private int mod_op; private Attribute attr; diff --git a/libjava/classpath/javax/naming/directory/NoSuchAttributeException.java b/libjava/classpath/javax/naming/directory/NoSuchAttributeException.java index cff9f95..8eb5e95 100644 --- a/libjava/classpath/javax/naming/directory/NoSuchAttributeException.java +++ b/libjava/classpath/javax/naming/directory/NoSuchAttributeException.java @@ -1,5 +1,5 @@ /* NoSuchAttributeException.java -- - Copyright (C) 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 2000, 2001, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -42,6 +42,8 @@ import javax.naming.NamingException; public class NoSuchAttributeException extends NamingException { + private static final long serialVersionUID = 4836415647935888137L; + public NoSuchAttributeException () { super (); diff --git a/libjava/classpath/javax/naming/directory/SchemaViolationException.java b/libjava/classpath/javax/naming/directory/SchemaViolationException.java index a11e50f..f60f32a 100644 --- a/libjava/classpath/javax/naming/directory/SchemaViolationException.java +++ b/libjava/classpath/javax/naming/directory/SchemaViolationException.java @@ -1,5 +1,5 @@ /* SchemaViolationException.java -- - Copyright (C) 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 2000, 2001, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -42,6 +42,8 @@ import javax.naming.NamingException; public class SchemaViolationException extends NamingException { + private static final long serialVersionUID = - 3041762429525049663L; + public SchemaViolationException () { super (); diff --git a/libjava/classpath/javax/naming/directory/SearchControls.java b/libjava/classpath/javax/naming/directory/SearchControls.java index 4cc789d..5ba488b 100644 --- a/libjava/classpath/javax/naming/directory/SearchControls.java +++ b/libjava/classpath/javax/naming/directory/SearchControls.java @@ -1,5 +1,5 @@ /* SearchControls.java -- - Copyright (C) 2001, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2001, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -47,6 +47,7 @@ import java.io.Serializable; public class SearchControls implements Serializable { + private static final long serialVersionUID = - 2480540967773454797L; public static final int OBJECT_SCOPE = 0; public static final int ONELEVEL_SCOPE = 1; public static final int SUBTREE_SCOPE = 2; diff --git a/libjava/classpath/javax/naming/directory/SearchResult.java b/libjava/classpath/javax/naming/directory/SearchResult.java index a6d5490..ce6bfed 100644 --- a/libjava/classpath/javax/naming/directory/SearchResult.java +++ b/libjava/classpath/javax/naming/directory/SearchResult.java @@ -1,5 +1,5 @@ /* SearchResult.java -- - Copyright (C) 2001, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2001, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -47,6 +47,7 @@ import javax.naming.Binding; public class SearchResult extends Binding { + private static final long serialVersionUID = - 9158063327699723172L; // Serialized fields. private Attributes attrs; diff --git a/libjava/classpath/javax/naming/event/NamingEvent.java b/libjava/classpath/javax/naming/event/NamingEvent.java index a121b8e..1bf381a 100644 --- a/libjava/classpath/javax/naming/event/NamingEvent.java +++ b/libjava/classpath/javax/naming/event/NamingEvent.java @@ -1,5 +1,5 @@ /* NamingEvent.java -- - Copyright (C) 2001, 2004 Free Software Foundation, Inc. + Copyright (C) 2001, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -48,6 +48,8 @@ import javax.naming.Binding; */ public class NamingEvent extends EventObject { + private static final long serialVersionUID = - 7126752885365133499L; + public static final int OBJECT_ADDED = 0; public static final int OBJECT_REMOVED = 1; public static final int OBJECT_RENAMED = 2; diff --git a/libjava/classpath/javax/naming/event/NamingExceptionEvent.java b/libjava/classpath/javax/naming/event/NamingExceptionEvent.java index 07896d4..3a9de21 100644 --- a/libjava/classpath/javax/naming/event/NamingExceptionEvent.java +++ b/libjava/classpath/javax/naming/event/NamingExceptionEvent.java @@ -1,5 +1,5 @@ /* NamingExceptionEvent.java -- - Copyright (C) 2001, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2001, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -49,6 +49,8 @@ import javax.naming.NamingException; public class NamingExceptionEvent extends EventObject { + private static final long serialVersionUID = - 4877678086134736336L; + // Serialized fields. private NamingException exception; diff --git a/libjava/classpath/javax/naming/spi/ResolveResult.java b/libjava/classpath/javax/naming/spi/ResolveResult.java index 72a101e..07e2df3 100644 --- a/libjava/classpath/javax/naming/spi/ResolveResult.java +++ b/libjava/classpath/javax/naming/spi/ResolveResult.java @@ -1,5 +1,5 @@ /* ResolveResult.java -- - Copyright (C) 2001, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2001, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -51,6 +51,8 @@ import javax.naming.Name; public class ResolveResult implements Serializable { + private static final long serialVersionUID = - 4552108072002407559L; + // Serialized fields. protected Object resolvedObj; protected Name remainingName; diff --git a/libjava/classpath/javax/net/ssl/SSLException.java b/libjava/classpath/javax/net/ssl/SSLException.java index 91d4cb7..3213b0b 100644 --- a/libjava/classpath/javax/net/ssl/SSLException.java +++ b/libjava/classpath/javax/net/ssl/SSLException.java @@ -1,5 +1,5 @@ /* SSLException.java -- generic SSL exception. - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -45,15 +45,47 @@ import java.io.IOException; * exception is thrown instead of this exception. * * @author Casey Marshall (rsdio@metastatic.org) + * + * @since 1.4 */ public class SSLException extends IOException { + private static final long serialVersionUID = 4511006460650708967L; // Constructor. // ------------------------------------------------------------------ + /** + * Create a new instance with a descriptive error message. + * + * @param message the descriptive error message + */ public SSLException(String message) { super(message); } + + /** + * Create a new instance with a descriptive error message and + * a cause. + * @param message the descriptive error message + * @param cause the cause + * @since 1.5 + */ + public SSLException(String message, Throwable cause) + { + super(message); + initCause(cause); + } + + /** + * Create a new instance with a cause. + * @param cause the cause + * @since 1.5 + */ + public SSLException(Throwable cause) + { + super(cause == null ? null : cause.toString()); + initCause(cause); + } } diff --git a/libjava/classpath/javax/print/CancelablePrintJob.java b/libjava/classpath/javax/print/CancelablePrintJob.java index 94e9475..39a2544 100644 --- a/libjava/classpath/javax/print/CancelablePrintJob.java +++ b/libjava/classpath/javax/print/CancelablePrintJob.java @@ -1,5 +1,5 @@ /* CancelablePrintJob.java -- - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -39,14 +39,29 @@ exception statement from your version. */ package javax.print; /** + * CancelablePrintJob represents a print job which can be + * canceled. + *

+ * It is implemented by DocPrintJobs which support to cancel + * a print job during processing. Clients need to explicitly test if a given + * DocPrintJob object from a print service implementes this + * interface and therefore supports cancelling. + *

+ * Implementor of java print services should implement this interface if + * cancelling is supported by the underlying print system. If implemented the + * corresponding print job event + * {@link javax.print.event.PrintJobEvent#JOB_CANCELED} should be delivered to + * registered clients. Implementations have to be thread-safe. + *

+ * * @author Michael Koch (konqueror@gmx.de) */ public interface CancelablePrintJob extends DocPrintJob { /** - * Cancel print job. + * Cancel the print job. * - * @exception PrintException if an error occured + * @exception PrintException if an error during cancellation occurs. */ void cancel() throws PrintException; } diff --git a/libjava/classpath/javax/print/Doc.java b/libjava/classpath/javax/print/Doc.java index 00e9dc9..c489de1 100644 --- a/libjava/classpath/javax/print/Doc.java +++ b/libjava/classpath/javax/print/Doc.java @@ -1,5 +1,5 @@ /* Doc.java -- - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -45,51 +45,102 @@ import java.io.Reader; import javax.print.attribute.DocAttributeSet; /** + * Doc specifies the interface for print services how to obtain + * the print data and document specific attributes for printing. + *

+ * The print data is always passed to a {@link javax.print.DocPrintJob} object + * as a Doc object which allows the print services to: + *

+ *

+ * Every method of a Doc implementation has to return always the + * same object on every method call. Therefore if the print job consumes the + * print data via a stream or a reader object it can read only once the + * supplied print data. Implementations of this interface have to be thread + * safe. + *

+ * * @author Michael Koch (konqueror@gmx.de) */ public interface Doc { /** - * Returns a set of attributes applying to this document. + * Returns the unmodifiable view of the attributes of this doc object. + *

+ * The attributes of this doc's attributes set overrides attributes of + * the same category in the print job's attribute set. If an attribute + * is not available in this doc's attributes set or null + * is returned the attributes of the same category of the print job are + * used. + *

* - * @return the attributes + * @return The unmodifiable attributes set, or null. */ DocAttributeSet getAttributes(); /** - * Returns the flavor in which this document will provide its print data. - * - * @return the document flavor for printing + * Returns the flavor of this doc objects print data. + * + * @return The document flavor. */ DocFlavor getDocFlavor(); /** - * Returns the print data of this document represented in a format that supports - * the document flavor. - * - * @return the print data + * Returns the print data of this doc object. + *

+ * The returned object is an instance as described by the associated + * document flavor ({@link DocFlavor#getRepresentationClassName()}) + * and can be cast to this representation class. + *

* - * @throws IOException if an error occurs + * @return The print data in the representation class. + * @throws IOException if representation class is a stream and I/O + * exception occures. */ Object getPrintData() throws IOException; /** * Returns a Reader object for extracting character print data * from this document. + *

+ * This method is supported if the document flavor is of type: + *

+ * otherwise this method returns null. + *

* - * @return the Reader object + * @return The Reader object, or null. * - * @throws IOException if an error occurs + * @throws IOException if an error occurs. */ Reader getReaderForText() throws IOException; /** * Returns an InputStream object for extracting byte print data * from this document. + *

+ * This method is supported if the document flavor is of type: + *

+ * otherwise this method returns null. + *

* - * @return the InputStream object + * @return The InputStream object, or null. * - * @throws IOException if an error occurs + * @throws IOException if an error occurs. */ InputStream getStreamForBytes() throws IOException; } \ No newline at end of file diff --git a/libjava/classpath/javax/print/DocFlavor.java b/libjava/classpath/javax/print/DocFlavor.java index 1e96a70..6030595 100644 --- a/libjava/classpath/javax/print/DocFlavor.java +++ b/libjava/classpath/javax/print/DocFlavor.java @@ -1,5 +1,5 @@ /* DocFlavor.java -- - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,17 +38,108 @@ exception statement from your version. */ package javax.print; +import java.io.IOException; +import java.io.ObjectInputStream; import java.io.Serializable; -import java.util.HashMap; +import java.io.StreamTokenizer; +import java.io.StringReader; +import java.nio.charset.Charset; import java.util.Iterator; import java.util.Map; +import java.util.TreeMap; /** + * DocFlavor provides a description of the format in which the + * print data will be supplied in a print job to the print service. + *

+ * A doc flavor consists of two parts: + *

+ * The DocFlavor class is therefore used in several places in the + * Java Print Service API. A print service provides its supported document + * flavors as an array of DocFlavor objects and a print job gets the flavor of + * its data to print from the Doc object provided as a DocFlavor + * instance. + *

+ *

+ * It has to be differentiated between client formatted and service + * formatted print data. Client formatted print data is already provided + * formatted by the client e.g. in an image format or as postscript. For + * service formatted print data, the Java Print Service instance produces + * the formatted print data. Here the doc flavor's representation class name + * does specify an interface instead of the actual print data source. The + * print service will call the methods of the given implementation of this + * interface with a special Graphics object capable of producing formatted + * print data from the graphics routines inside the interface methods. + *

+ *

+ *

Client formatted print data document flavors

+ * The print service uses the representation class of the doc flavor to know + * how to retrieve the print data. If the representation class is a + * URL it will open the URL to read the print data from it. If it is + * a byte[] it will directly use the array and send it to the + * printer. There are predefined doc flavor as inner class for the most common + * representation class types: + * + *

+ *

+ *

Service formatted print data document flavors

+ * The print service uses the provided object implementing the interface + * specified by the representation class to produce the formatted print data. + * The mime type of service formatted data is always + * "application/x-java-jvm-local-objectref" to signal the local + * reference to the print data object implementing the interface. Predefined + * doc flavor classes exist as an inner class for the three available interface + * to produce print data: + * + *

+ * * @author Michael Koch (konqueror@gmx.de) + * @author Wolfgang Baer (WBaer@gmx.de) */ public class DocFlavor implements Cloneable, Serializable { /** + * Predefined static DocFlavor objects for document + * types which use a byte array for the print data representation. + *

All the defined doc flavors have a print data representation + * classname of "[B" (byte array).

+ * * @author Michael Koch (konqueror@gmx.de) */ public static class BYTE_ARRAY @@ -56,26 +147,92 @@ public class DocFlavor implements Cloneable, Serializable { private static final long serialVersionUID = -9065578006593857475L; + /** + * Byte array doc flavor with a MIME Type of "application/octet-stream". + */ public static final BYTE_ARRAY AUTOSENSE = new BYTE_ARRAY("application/octet-stream"); + /** + * Byte array doc flavor with a MIME Type of "image/gif". + */ public static final BYTE_ARRAY GIF = new BYTE_ARRAY("image/gif"); + /** + * Byte array doc flavor with a MIME Type of "image/jpeg". + */ public static final BYTE_ARRAY JPEG = new BYTE_ARRAY("image/jpeg"); + /** + * Byte array doc flavor with a MIME Type of "application/vnd.hp-PCL". + */ public static final BYTE_ARRAY PCL = new BYTE_ARRAY("application/vnd.hp-PCL"); + /** + * Byte array doc flavor with a MIME Type of "application/pdf". + */ public static final BYTE_ARRAY PDF = new BYTE_ARRAY("application/pdf"); + /** + * Byte array doc flavor with a MIME Type of "image/png". + */ public static final BYTE_ARRAY PNG = new BYTE_ARRAY("image/png"); + /** + * Byte array doc flavor with a MIME Type of "application/postscript". + */ public static final BYTE_ARRAY POSTSCRIPT = new BYTE_ARRAY("application/postscript"); - public static final BYTE_ARRAY TEXT_HTML_HOST = new BYTE_ARRAY("text/html"); + /** + * Byte array doc flavor with a MIME Type of "text/html" in the host encoding. + */ + public static final BYTE_ARRAY TEXT_HTML_HOST = new BYTE_ARRAY("text/html; charset=" + hostEncoding); + /** + * Byte array doc flavor with a MIME Type of "text/html; charset=us-ascii". + */ public static final BYTE_ARRAY TEXT_HTML_US_ASCII = new BYTE_ARRAY("text/html; charset=us-ascii"); + /** + * Byte array doc flavor with a MIME Type of "text/html; charset=utf-16". + */ public static final BYTE_ARRAY TEXT_HTML_UTF_16 = new BYTE_ARRAY("text/html; charset=utf-16"); + /** + * Byte array doc flavor with a MIME Type of "text/html; charset=utf-16be". + */ public static final BYTE_ARRAY TEXT_HTML_UTF_16BE = new BYTE_ARRAY("text/html; charset=utf-16be"); + /** + * Byte array doc flavor with a MIME Type of "text/html; charset=utf-16le". + */ public static final BYTE_ARRAY TEXT_HTML_UTF_16LE = new BYTE_ARRAY("text/html; charset=utf-16le"); + /** + * Byte array doc flavor with a MIME Type of "text/html; charset=utf-8". + */ public static final BYTE_ARRAY TEXT_HTML_UTF_8 = new BYTE_ARRAY("text/html; charset=utf-8"); - public static final BYTE_ARRAY TEXT_PLAIN_HOST = new BYTE_ARRAY("text/plain"); - public static final BYTE_ARRAY TEXT_PLAIN_US_ASCII = new BYTE_ARRAY("text/plain; charset=us-ascii"); + /** + * Byte array doc flavor with a MIME Type of "text/plain" in the host encoding. + */ + public static final BYTE_ARRAY TEXT_PLAIN_HOST = new BYTE_ARRAY("text/plain; charset=" + hostEncoding); + /** + * Byte array doc flavor with a MIME Type of "text/plain; charset=us-ascii". + */ + public static final BYTE_ARRAY TEXT_PLAIN_US_ASCII = new BYTE_ARRAY("text/plain; charset=us-ascii"); + /** + * Byte array doc flavor with a MIME Type of "text/plain; charset=utf-16". + */ public static final BYTE_ARRAY TEXT_PLAIN_UTF_16 = new BYTE_ARRAY("text/plain; charset=utf-16"); + /** + * Byte array doc flavor with a MIME Type of "text/plain; charset=utf-16be". + */ public static final BYTE_ARRAY TEXT_PLAIN_UTF_16BE = new BYTE_ARRAY("text/plain; charset=utf-16be"); + /** + * Byte array doc flavor with a MIME Type of "text/plain; charset=utf-16le". + */ public static final BYTE_ARRAY TEXT_PLAIN_UTF_16LE = new BYTE_ARRAY("text/plain; charset=utf-16le"); + /** + * Byte array doc flavor with a MIME Type of "text/plain; charset=utf-8". + */ public static final BYTE_ARRAY TEXT_PLAIN_UTF_8 = new BYTE_ARRAY("text/plain; charset=utf-8"); + /** + * Constructor for doc flavor objects with the given MIME type + * and a print data representation class name of "[B". + * + * @param mimeType the mime type string + * + * @throws NullPointerException if mimeType is null. + * @throws IllegalArgumentException if mimeType has the wrong syntax. + */ public BYTE_ARRAY(String mimeType) { super(mimeType, "[B"); @@ -83,6 +240,11 @@ public class DocFlavor implements Cloneable, Serializable } /** + * Predefined static DocFlavor objects for document + * types which use a char array for the print data representation. + *

All the defined doc flavors have a print data representation + * classname of "[C" (char array).

+ * * @author Michael Koch (konqueror@gmx.de) */ public static class CHAR_ARRAY @@ -90,9 +252,24 @@ public class DocFlavor implements Cloneable, Serializable { private static final long serialVersionUID = -8720590903724405128L; + /** + * Char array doc flavor with a MIME Type of "text/html; charset=utf-16". + */ public static final DocFlavor.CHAR_ARRAY TEXT_HTML = new CHAR_ARRAY("text/html; charset=utf-16"); + /** + * Char array doc flavor with a MIME Type of "text/plain; charset=utf-16". + */ public static final DocFlavor.CHAR_ARRAY TEXT_PLAIN = new CHAR_ARRAY("text/plain; charset=utf-16"); + /** + * Constructor for doc flavor objects with the given MIME type + * and a print data representation class name of "[C". + * + * @param mimeType the mime type string + * + * @throws NullPointerException if mimeType is null. + * @throws IllegalArgumentException if mimeType has the wrong syntax. + */ public CHAR_ARRAY(String mimeType) { super(mimeType, "[C"); @@ -100,6 +277,11 @@ public class DocFlavor implements Cloneable, Serializable } /** + * Predefined static DocFlavor objects for document + * types which use an InputStream to retrieve the print data. + *

All the defined doc flavors have a print data representation + * classname of "java.io.InputStream".

+ * * @author Michael Koch (konqueror@gmx.de) */ public static class INPUT_STREAM @@ -107,26 +289,92 @@ public class DocFlavor implements Cloneable, Serializable { private static final long serialVersionUID = -7045842700749194127L; + /** + * InputStream doc flavor with a MIME Type of "application/octet-stream". + */ public static final INPUT_STREAM AUTOSENSE = new INPUT_STREAM("application/octet-stream"); + /** + * InputStream doc flavor with a MIME Type of "image/gif". + */ public static final INPUT_STREAM GIF = new INPUT_STREAM("image/gif"); + /** + * InputStream doc flavor with a MIME Type of "image/jpeg". + */ public static final INPUT_STREAM JPEG = new INPUT_STREAM("image/jpeg"); + /** + * InputStream doc flavor with a MIME Type of "application/vnd.hp-PCL". + */ public static final INPUT_STREAM PCL = new INPUT_STREAM("application/vnd.hp-PCL"); + /** + * InputStream doc flavor with a MIME Type of "application/pdf". + */ public static final INPUT_STREAM PDF = new INPUT_STREAM("application/pdf"); + /** + * InputStream doc flavor with a MIME Type of "image/png". + */ public static final INPUT_STREAM PNG = new INPUT_STREAM("image/png"); + /** + * InputStream doc flavor with a MIME Type of "application/postscript". + */ public static final INPUT_STREAM POSTSCRIPT = new INPUT_STREAM("application/postscript"); - public static final INPUT_STREAM TEXT_HTML_HOST = new INPUT_STREAM("text/html"); + /** + * InputStream doc flavor with a MIME Type of "text/html" in the host encoding. + */ + public static final INPUT_STREAM TEXT_HTML_HOST = new INPUT_STREAM("text/html; charset=" + hostEncoding); + /** + * InputStream doc flavor with a MIME Type of "text/html; charset=us-ascii". + */ public static final INPUT_STREAM TEXT_HTML_US_ASCII = new INPUT_STREAM("text/html; charset=us-ascii"); + /** + * InputStream doc flavor with a MIME Type of "text/html; charset=utf-16". + */ public static final INPUT_STREAM TEXT_HTML_UTF_16 = new INPUT_STREAM("text/html; charset=utf-16"); + /** + * InputStream doc flavor with a MIME Type of "text/html; charset=utf-16be". + */ public static final INPUT_STREAM TEXT_HTML_UTF_16BE = new INPUT_STREAM("text/html; charset=utf-16be"); + /** + * InputStream doc flavor with a MIME Type of "text/html; charset=utf-16le". + */ public static final INPUT_STREAM TEXT_HTML_UTF_16LE = new INPUT_STREAM("text/html; charset=utf-16le"); + /** + * InputStream doc flavor with a MIME Type of "text/html; charset=utf-8". + */ public static final INPUT_STREAM TEXT_HTML_UTF_8 = new INPUT_STREAM("text/html; charset=utf-8"); - public static final INPUT_STREAM TEXT_PLAIN_HOST = new INPUT_STREAM("text/plain"); + /** + * InputStream doc flavor with a MIME Type of "text/plain" in the host encoding. + */ + public static final INPUT_STREAM TEXT_PLAIN_HOST = new INPUT_STREAM("text/plain; charset=" + hostEncoding); + /** + * InputStream doc flavor with a MIME Type of "text/plain; charset=us-ascii". + */ public static final INPUT_STREAM TEXT_PLAIN_US_ASCII = new INPUT_STREAM("text/plain; charset=us-ascii"); + /** + * InputStream doc flavor with a MIME Type of "text/plain; charset=utf-16". + */ public static final INPUT_STREAM TEXT_PLAIN_UTF_16 = new INPUT_STREAM("text/plain; charset=utf-16"); + /** + * InputStream doc flavor with a MIME Type of "text/plain; charset=utf-16be". + */ public static final INPUT_STREAM TEXT_PLAIN_UTF_16BE = new INPUT_STREAM("text/plain; charset=utf-16be"); + /** + * InputStream doc flavor with a MIME Type of "text/plain; charset=utf-16le". + */ public static final INPUT_STREAM TEXT_PLAIN_UTF_16LE = new INPUT_STREAM("text/plain; charset=utf-16le"); + /** + * InputStream doc flavor with a MIME Type of "text/plain; charset=utf-8". + */ public static final INPUT_STREAM TEXT_PLAIN_UTF_8 = new INPUT_STREAM("text/plain; charset=utf-8"); + /** + * Constructor for doc flavor objects with the given MIME type + * and a print data representation class name of "java.io.InputStream". + * + * @param mimeType the mime type string + * + * @throws NullPointerException if mimeType is null. + * @throws IllegalArgumentException if mimeType has the wrong syntax. + */ public INPUT_STREAM(String mimeType) { super(mimeType, "java.io.InputStream"); @@ -134,6 +382,11 @@ public class DocFlavor implements Cloneable, Serializable } /** + * Predefined static DocFlavor objects for document + * types which use an Reader to retrieve the print data. + *

All the defined doc flavors have a print data representation + * classname of "java.io.Reader".

+ * * @author Michael Koch (konqueror@gmx.de) */ public static class READER @@ -141,9 +394,24 @@ public class DocFlavor implements Cloneable, Serializable { private static final long serialVersionUID = 7100295812579351567L; + /** + * Reader doc flavor with a MIME Type of "text/html; charset=utf-16". + */ public static final DocFlavor.READER TEXT_HTML = new READER("text/html; charset=utf-16"); + /** + * Reader doc flavor with a MIME Type of "text/plain; charset=utf-16". + */ public static final DocFlavor.READER TEXT_PLAIN = new READER("text/plain; charset=utf-16"); + /** + * Constructor for doc flavor objects with the given MIME type + * and a print data representation class name of "java.io.Reader". + * + * @param mimeType the mime type string + * + * @throws NullPointerException if mimeType is null. + * @throws IllegalArgumentException if mimeType has the wrong syntax. + */ public READER(String mimeType) { super(mimeType, "java.io.Reader"); @@ -151,6 +419,11 @@ public class DocFlavor implements Cloneable, Serializable } /** + * Predefined static DocFlavor objects for document + * types which use service formatted print data. + *

All the defined doc flavors have a MIME type of + * "application/x-java-jvm-local-objectref".

+ * * @author Michael Koch (konqueror@gmx.de) */ public static class SERVICE_FORMATTED @@ -158,10 +431,31 @@ public class DocFlavor implements Cloneable, Serializable { private static final long serialVersionUID = 6181337766266637256L; + /** + * Service formatted doc flavor with a representation class of + * "java.awt.print.Pageable". + */ public static final DocFlavor.SERVICE_FORMATTED PAGEABLE = new SERVICE_FORMATTED("java.awt.print.Pageable"); + /** + * Service formatted doc flavor with a representation class of + * "java.awt.print.Printable". + */ public static final DocFlavor.SERVICE_FORMATTED PRINTABLE = new SERVICE_FORMATTED("java.awt.print.Printable"); + /** + * Service formatted doc flavor with a representation class of + * "java.awt.image.renderable.RenderableImage". + */ public static final DocFlavor.SERVICE_FORMATTED RENDERABLE_IMAGE = new SERVICE_FORMATTED("java.awt.image.renderable.RenderableImage"); + /** + * Constructor for doc flavor objects with a MIME type of + * "application/x-java-jvm-local-objectref" and the given + * print data representation classname. + * + * @param className the representation classname + * + * @throws NullPointerException if className is null. + */ public SERVICE_FORMATTED(String className) { super("application/x-java-jvm-local-objectref", className); @@ -169,6 +463,11 @@ public class DocFlavor implements Cloneable, Serializable } /** + * Predefined static DocFlavor objects for document + * types which use a String for the print data representation. + *

All the defined doc flavors have a print data representation + * classname of "java.lang.String".

+ * * @author Michael Koch (konqueror@gmx.de) */ public static class STRING @@ -176,9 +475,24 @@ public class DocFlavor implements Cloneable, Serializable { private static final long serialVersionUID = 4414407504887034035L; + /** + * String doc flavor with a MIME Type of "text/html; charset=utf-16". + */ public static final DocFlavor.STRING TEXT_HTML = new STRING("text/html; charset=utf-16"); + /** + * String doc flavor with a MIME Type of "text/plain; charset=utf-16". + */ public static final DocFlavor.STRING TEXT_PLAIN = new STRING("text/plain; charset=utf-16"); + /** + * Constructor for doc flavor objects with the given MIME type + * and a print data representation class name of "java.lang.String". + * + * @param mimeType the mime type string + * + * @throws NullPointerException if mimeType is null. + * @throws IllegalArgumentException if mimeType has the wrong syntax. + */ public STRING(String mimeType) { super(mimeType, "java.lang.String"); @@ -186,6 +500,11 @@ public class DocFlavor implements Cloneable, Serializable } /** + * Predefined static DocFlavor objects for document + * types which have an URL where to retrieve the print data. + *

All the defined doc flavors have a print data representation + * classname of "java.net.URL".

+ * * @author Michael Koch (konqueror@gmx.de) */ public static class URL @@ -193,26 +512,92 @@ public class DocFlavor implements Cloneable, Serializable { private static final long serialVersionUID = 2936725788144902062L; + /** + * URL doc flavor with a MIME Type of "application/octet-stream". + */ public static final DocFlavor.URL AUTOSENSE = new URL("application/octet-stream"); + /** + * URL doc flavor with a MIME Type of "image/gif". + */ public static final DocFlavor.URL GIF = new URL("image/gif"); + /** + * URL doc flavor with a MIME Type of "image/jpeg". + */ public static final DocFlavor.URL JPEG = new URL("image/jpeg"); + /** + * URL doc flavor with a MIME Type of "application/vnd.hp-PCL". + */ public static final DocFlavor.URL PCL = new URL("application/vnd.hp-PCL"); + /** + * URL doc flavor with a MIME Type of "application/pdf". + */ public static final DocFlavor.URL PDF = new URL("application/pdf"); + /** + * URL doc flavor with a MIME Type of "image/png". + */ public static final DocFlavor.URL PNG = new URL("image/png"); + /** + * URL doc flavor with a MIME Type of "application/postscript". + */ public static final DocFlavor.URL POSTSCRIPT = new URL("application/postscript"); - public static final DocFlavor.URL TEXT_HTML_HOST = new URL("text/html"); + /** + * URL doc flavor with a MIME Type of "text/html" in the host encoding. + */ + public static final DocFlavor.URL TEXT_HTML_HOST = new URL("text/html; charset=" + hostEncoding); + /** + * URL doc flavor with a MIME Type of "text/html; charset=us-ascii". + */ public static final DocFlavor.URL TEXT_HTML_US_ASCII = new URL("text/html; charset=us-ascii"); + /** + * URL doc flavor with a MIME Type of "text/html; charset=utf-16". + */ public static final DocFlavor.URL TEXT_HTML_UTF_16 = new URL("text/html; charset=utf-16"); + /** + * URL doc flavor with a MIME Type of "text/html; charset=utf-16be". + */ public static final DocFlavor.URL TEXT_HTML_UTF_16BE = new URL("text/html; charset=utf-16be"); + /** + * URL doc flavor with a MIME Type of "text/html; charset=utf-16le". + */ public static final DocFlavor.URL TEXT_HTML_UTF_16LE = new URL("text/html; charset=utf-16le"); + /** + * URL doc flavor with a MIME Type of "text/html; charset=utf-8". + */ public static final DocFlavor.URL TEXT_HTML_UTF_8 = new URL("text/html; charset=utf-8"); - public static final DocFlavor.URL TEXT_PLAIN_HOST = new URL("text/plain"); + /** + * URL doc flavor with a MIME Type of "text/plain" in the host encoding. + */ + public static final DocFlavor.URL TEXT_PLAIN_HOST = new URL("text/plain; charset=" + hostEncoding); + /** + * URL doc flavor with a MIME Type of "text/plain; charset=us-ascii". + */ public static final DocFlavor.URL TEXT_PLAIN_US_ASCII = new URL("text/plain; charset=us-ascii"); + /** + * URL doc flavor with a MIME Type of "text/plain; charset=utf-16". + */ public static final DocFlavor.URL TEXT_PLAIN_UTF_16 = new URL("text/plain; charset=utf-16"); + /** + * URL doc flavor with a MIME Type of "text/plain; charset=utf-16be". + */ public static final DocFlavor.URL TEXT_PLAIN_UTF_16BE = new URL("text/plain; charset=utf-16be"); + /** + * URL doc flavor with a MIME Type of "text/plain; charset=utf-16le". + */ public static final DocFlavor.URL TEXT_PLAIN_UTF_16LE = new URL("text/plain; charset=utf-16le"); + /** + * URL doc flavor with a MIME Type of "text/plain; charset=utf-8". + */ public static final DocFlavor.URL TEXT_PLAIN_UTF_8 = new URL("text/plain; charset=utf-8"); + /** + * Constructor for doc flavor objects with the given MIME type + * and a print data representation class name of "java.net.URL". + * + * @param mimeType the mime type string + * + * @throws NullPointerException if mimeType is null. + * @throws IllegalArgumentException if mimeType has the wrong syntax. + */ public URL(String mimeType) { super(mimeType, "java.net.URL"); @@ -221,47 +606,191 @@ public class DocFlavor implements Cloneable, Serializable private static final long serialVersionUID = -4512080796965449721L; - // FIXME: Get the host encoding from somewhere. Note that the new String is to make - // sure the field won't be a compile time constant. - public static final String hostEncoding = new String("US-ASCII"); - - private String mediaSubtype; - private String mediaType; - private String className; - private HashMap params = new HashMap(); + /** + * The string representing the host encoding. This is the encoding + * used in the predefined HOST doc flavors + * (e.g. {@link BYTE_ARRAY#TEXT_HTML_HOST}). + */ + public static final String hostEncoding = Charset.defaultCharset().name(); + + private transient String mediaSubtype; + private transient String mediaType; + private transient TreeMap params; + // name as defined in Serialized Form JDK 1.4 + private String myClassName; + + /** + * Constructs a DocFlavor object with the given MIME type and + * representation class name. + * + * @param mimeType the MIME type string. + * @param className the fully-qualified name of the representation class. + * + * @throws NullPointerException if mimeType or className are null. + * @throws IllegalArgumentException if given mimeType has syntax errors. + */ public DocFlavor(String mimeType, String className) { if (mimeType == null || className == null) throw new NullPointerException(); + params = new TreeMap(); parseMimeType(mimeType); - this.className = className; + + myClassName = className; } - + + /** + * Parses the given string as MIME type. + * The mediatype, mediasubtype and all parameter/value + * combinations are extracted, comments are dropped. + * + * @param mimeType the string to parse + * @throws IllegalArgumentException if not conformant. + */ private void parseMimeType(String mimeType) { - // FIXME: This method is know to be not completely correct, but it works for now. + int MEDIA = 1; + int MEDIASUB = 2; + int PARAM_NAME = 3; + int PARAM_VALUE = 4; + int COMMENT_START = 5; - int pos = mimeType.indexOf(';'); - - if (pos != -1) + int state = 0; + int lastState = 0; // keeps track of state before comment + int tok; + + try { - String tmp = mimeType.substring(pos + 2); - mimeType = mimeType.substring(0, pos); - pos = tmp.indexOf('='); - params.put(tmp.substring(0, pos), tmp.substring(pos + 1)); + String paramName = null; + StreamTokenizer in = new StreamTokenizer(new StringReader(mimeType)); + in.resetSyntax(); + // Allowed characters are anything except: + // SPACE, CTLs (= Unicode characters U+0000 - U+001F and U+007F) + // and tspecials ( ) < > @ , ; : \ " / [ ] ? = + in.whitespaceChars(0x00, 0x20); + in.whitespaceChars(0x7F, 0x7F); + in.wordChars('A', 'Z'); + in.wordChars('a', 'z'); + in.wordChars('0', '9'); + in.wordChars(0xA0, 0xFF); + in.wordChars(0x21, 0x21); + in.wordChars(0x23, 0x27); + in.wordChars(0x2A, 0x2B); + in.wordChars(0x2D, 0x2E); + in.wordChars(0x5E, 0x60); + in.wordChars(0x7B, 0x7E); + in.quoteChar('"'); + + while ((tok = in.nextToken()) != StreamTokenizer.TT_EOF) + { + switch (tok) + { + case StreamTokenizer.TT_WORD: + if (state == 0) + { + mediaType = in.sval.toLowerCase(); + state = MEDIA; + break; + } + if (state == MEDIA) + { + mediaSubtype = in.sval.toLowerCase(); + state = MEDIASUB; + break; + } + // begin of parameters is either after mediasub or a parameter value + if (state == MEDIASUB || state == PARAM_VALUE) + { + paramName = in.sval.toLowerCase(); + state = PARAM_NAME; + break; + } + // a parameter always needs to follow a value + if (state == PARAM_NAME) + { + String paramValue = in.sval; + // if a charset param the value needs to be stored lowercase + if (paramName.equals("charset")) + paramValue = paramValue.toLowerCase(); + + state = PARAM_VALUE; + params.put(paramName, paramValue); + break; + } + if (state == COMMENT_START) + { + // ignore; + break; + } + break; + case '/': + // may only occur after the mediatype + if (state != MEDIA) + throw new IllegalArgumentException(); + + break; + case '=': + // may only occur after a parameter + if (state != PARAM_NAME) + throw new IllegalArgumentException(); + + break; + case ';': + // differentiates mime type and parameters/value combinations + if (state != MEDIASUB && state != PARAM_VALUE) + throw new IllegalArgumentException(); + + break; + case '(': // begin comment + lastState = state; + state = COMMENT_START; + break; + case ')': // end comment + state = lastState; + break; + // a parameter always needs to follow a value / or quoted value + case '"': + if (state == PARAM_NAME) + { + String paramValue = in.sval; + // if a charset param the value needs to be stored lowercase + if (paramName.equals("charset")) + paramValue = paramValue.toLowerCase(); + + state = PARAM_VALUE; + params.put(paramName, paramValue); + break; + } + + // only values may be quoted + throw new IllegalArgumentException(); + default: + // if any other char is observed its not allowed + throw new IllegalArgumentException(); + } + } + } + catch (IOException e) + { + // should not happen as mimetype str cannot be null + throw new InternalError("IOException during parsing String " + mimeType); } - - pos = mimeType.indexOf('/'); - - if (pos == -1) - throw new IllegalArgumentException(); - - mediaType = mimeType.substring(0, pos); - mediaSubtype = mimeType.substring(pos + 1); } + /** + * Checks if this doc flavor object is equal to the given object. + *

+ * Two doc flavor objects are considered equal if the provided object is not + * null and an instance of DocFlavor. The MIME + * types has to be equal in their media type, media subtype, their + * paramter/value combinations and the representation classname. + *

+ * + * @param obj the object to test. + * @return true if equal, false otherwise. + */ public boolean equals(Object obj) { if (! (obj instanceof DocFlavor)) @@ -273,20 +802,39 @@ public class DocFlavor implements Cloneable, Serializable && getRepresentationClassName().equals(tmp.getRepresentationClassName())); } + /** + * Returns the media subtype of this flavor object. + * A mimetype of "text/html; charset=us-ascii" will + * return "html" as the media subtype. + * + * @return The media subtype. + */ public String getMediaSubtype() { return mediaSubtype; } + /** + * Returns the media type of this flavor object. + * A mimetype of "text/html; charset=us-ascii" will + * return "text" as the media type. + * + * @return The media type. + */ public String getMediaType() { return mediaType; } + /** + * Returns the mime type of this flavor object. + * The mimetype will have every parameter value + * enclosed in quotes. + * + * @return The mime type. + */ public String getMimeType() { - // FIXME: Check if this algorithm is correct. - String mimeType = getMediaType() + "/" + getMediaSubtype(); Iterator it = params.entrySet().iterator(); @@ -299,28 +847,69 @@ public class DocFlavor implements Cloneable, Serializable return mimeType; } + /** + * Returns the value for an optional parameter of the mime type of this + * flavor object. + * + * @param paramName the name of the parameter + * @return The value for the parameter, or null if none bound. + * @throws NullPointerException if paramName is null. + */ public String getParameter(String paramName) { if (paramName == null) throw new NullPointerException(); - return (String) params.get(paramName); + return (String) params.get(paramName.toLowerCase()); } + /** + * Returns the name of the representation class of this flavor object. + * + * @return The representation classname. + */ public String getRepresentationClassName() { - return className; + return myClassName; } + /** + * Returns a hash code for this doc flavor object. + * + * @return The hashcode. + */ public int hashCode() { return ((mediaType.hashCode() * mediaSubtype.hashCode() - * className.hashCode()) ^ params.hashCode()); + * myClassName.hashCode()) ^ params.hashCode()); } + /** + * Returns a string representation of this doc flavor object. + * The returned string is of the form + * getMimeType() + "; class=\"" + getRepresentationClassName() + "\""; + * + * @return The constructed string representation. + */ public String toString() { - return getMimeType(); + return getMimeType() + "; class=\"" + getRepresentationClassName() + "\""; + } + + // needs special treatment for serialization + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException + { + params = new TreeMap(); + myClassName = (String) stream.readObject(); + parseMimeType((String) stream.readObject()); + } + + private void writeObject(java.io.ObjectOutputStream stream) + throws IOException + { + stream.writeObject(myClassName); + stream.writeObject(getMimeType()); } } diff --git a/libjava/classpath/javax/print/DocPrintJob.java b/libjava/classpath/javax/print/DocPrintJob.java index f7d3615..eec4e2a 100644 --- a/libjava/classpath/javax/print/DocPrintJob.java +++ b/libjava/classpath/javax/print/DocPrintJob.java @@ -1,5 +1,5 @@ /* DocPrintJob.java -- - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -44,61 +44,105 @@ import javax.print.event.PrintJobAttributeListener; import javax.print.event.PrintJobListener; /** + * DocPrintJob represents a print job which supports printing + * of a single document. + *

+ * An instance can be obtained from every PrintService available + * by calling the {@link javax.print.PrintService#createPrintJob()} method. + * A print job is bound to the print service it is created from. + *

+ * * @author Michael Koch (konqueror@gmx.de) */ public interface DocPrintJob { /** - * Registers a listener for changes in the specified attributes. + * Registers a listener for changes in the specified attribute set + * during processing of this print job. + *

+ * If the given attribute set is empty no changes will be reported. + * If the set is null all attributes are monitored. + *

* - * @param listener the listener to add - * @param attributes the attributes to observe + * @param listener the listener to register. + * @param attributes the attributes to observe. + * + * @see #removePrintJobAttributeListener(PrintJobAttributeListener) */ void addPrintJobAttributeListener(PrintJobAttributeListener listener, PrintJobAttributeSet attributes); /** - * Registers a listener for events occuring during this print job. + * Registers a listener for events occuring during processing + * of this print job. + * + * @param listener the listener to add, if null nothing is done. * - * @param listener the listener to add + * @see #removePrintJobListener(PrintJobListener) */ void addPrintJobListener(PrintJobListener listener); /** - * Returns the print job's attributes. + * Returns the print job's attributes. + *

+ * The returned set of attributes is a snapshot at the time of calling this + * method and will not be updated if changes to the print job's attributes + * happens. To monitor changes register a print job listener. + *

* - * @return the attributes of this print job + * @return The attributes of this print job, + * may be empty but never null. */ PrintJobAttributeSet getAttributes(); /** * Returns the PrintService object this print job is bound to. * - * @return the print service + * @return The print service. */ PrintService getPrintService(); /** * Prints a document with the specified print job attributes. * + *

+ * If the doc flavor provided by the Doc implementation is + * not supported by this print service a PrintException + * implementing the FlavorException interface will be thrown. + *

+ * * @param doc the document to print - * @param attributes the attributes to use + * @param attributes the job attributes to use. If null the + * default attribute values of the print service will be used. + * + * @throws PrintException if an error occurs. The thrown exception may + * implement refining print exception interface to provide more detail of + * the error. * - * @throws PrintException if an error occurs + * @see AttributeException + * @see FlavorException */ void print(Doc doc, PrintRequestAttributeSet attributes) throws PrintException; /** - * De-registers an attribute listener. + * Removes the given listener from the listeners registered for changes + * in their provided attribute set during processing of this print job. * - * @param listener the listener to remove - */ + * @param listener the listener to remove, if null or not + * registered nothing will be done. + * + * @see #addPrintJobAttributeListener(PrintJobAttributeListener, PrintJobAttributeSet) + */ void removePrintJobAttributeListener(PrintJobAttributeListener listener); /** - * De-registers a print job listener. + * Removes the given listener from the listeners registered for events + * occuring during processing of this print job. + * + * @param listener the listener to remove, if null or not + * registered nothing will be done. * - * @param listener the listener to remove + * @see #addPrintJobListener(PrintJobListener) */ void removePrintJobListener(PrintJobListener listener); } \ No newline at end of file diff --git a/libjava/classpath/javax/print/PrintService.java b/libjava/classpath/javax/print/PrintService.java index d34fde8..b5fe004 100644 --- a/libjava/classpath/javax/print/PrintService.java +++ b/libjava/classpath/javax/print/PrintService.java @@ -1,5 +1,5 @@ /* PrintService.java -- - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -45,14 +45,25 @@ import javax.print.attribute.PrintServiceAttributeSet; import javax.print.event.PrintServiceAttributeListener; /** + * A PrintService represents a printer available for printing. + *

+ * The print service hereby may be a real physical printer device, a printer + * group with same capabilities or a logical print service (like for example + * a PDF writer). The print service is used to query the capabilities of the + * represented printer instance. If a suitable print service is found it is + * used to create a print job for the actual printing process. + *

+ * @see javax.print.DocPrintJob + * * @author Michael Koch (konqueror@gmx.de) */ public interface PrintService { /** - * Returns a new print job capable to handle all supported document flavors. + * Creates and returns a new print job which is capable to handle all + * the document flavors supported by this print service. * - * @return the new print job + * @return The created print job object. */ DocPrintJob createPrintJob(); @@ -61,39 +72,54 @@ public interface PrintService * * @param obj the service to check against * - * @return true if both services refer to the sam underlying - * service, false otherwise + * @return true if both services refer to the same underlying + * service, false otherwise. */ boolean equals(Object obj); /** - * Returns the value of a single specified attribute. + * Returns the value of the single specified attribute. * * @param category the category of a PrintServiceAttribute * - * @return the value of the attribute + * @return The value of the attribute, or null if the attribute + * category is not supported by this print service implementation. * - * @throws NullPointerException if category is null + * @throws NullPointerException if category is null. * @throws IllegalArgumentException if category is not a class that - * implements PrintServiceAttribute + * implements PrintServiceAttribute. */ PrintServiceAttribute getAttribute(Class category); /** - * Returns all attributes of this printer service - * - * @return all attributes of this print service + * Returns the attributes describing this print service. The returned + * attributes set is unmodifiable and represents the current state of + * the print service. As some print service attributes may change + * (depends on the print service implementation) a subsequent call to + * this method may return a different set. To monitor changes a + * PrintServiceAttributeListener may be registered. + * + * @return All the description attributes of this print service. + * @see #addPrintServiceAttributeListener(PrintServiceAttributeListener) */ PrintServiceAttributeSet getAttributes(); /** - * Returns the service's default value for a given attribute. + * Determines and returns the default value for a given attribute category + * of this print service. + *

+ * A return value of null means either that the print service + * does not support the attribute category or there is no default value + * available for this category. To distinguish these two case one can test + * with {@link #isAttributeCategorySupported(Class)} if the category is + * supported. + *

* * @param category the category of the attribute * - * @return the default value + * @return The default value, or null. * - * @throws NullPointerException if category is null + * @throws NullPointerException if category is null * @throws IllegalArgumentException if category is a class * not implementing Attribute */ @@ -101,36 +127,50 @@ public interface PrintService /** * Returns the name of this print service. + * This may be the value of the PrinterName attribute. * - * @return the name + * @return The print service name. */ String getName(); /** - * Returns a factory for UI components. + * Returns a factory for UI components if supported by the print service. * - * @return the factory + * @return A factory for UI components or null. */ ServiceUIFactory getServiceUIFactory(); /** * Returns all supported attribute categories. * - * @return an array of all supported attribute categories + * @return The class array of all supported attribute categories. */ Class[] getSupportedAttributeCategories(); /** - * Returns all supported attribute values a client can use when setting up - * a print job with this service. + * Determines and returns all supported attribute values of a given + * attribute category a client can use when setting up a print job + * for this print service. + *

+ * The returned object may be one of the following types: + *

+ *

* * @param category the attribute category to test - * @param flavor the document flavor to use, or null - * @param attributes set of printing attributes for a supposed job, or null + * @param flavor the document flavor to use, or null + * @param attributes set of attributes for a supposed job, + * or null * - * @return object indicating supported values for category, - * or null if this print service doesnt support specifying doc-level or - * job-level attribute in a print request. + * @return A object (as defined above) indicating the supported values + * for the given attribute category, or null if this print + * service doesn't support the given attribute category at all. * * @throws NullPointerException if category is null * @throws IllegalArgumentException if category is a class not @@ -140,73 +180,101 @@ public interface PrintService Object getSupportedAttributeValues(Class category, DocFlavor flavor, AttributeSet attributes); /** - * Returns an array of all supproted document flavors. - * - * @return the supported document flavors + * Determines and returns an array of all supported document flavors which + * can be used to supply print data to this print service. + *

+ * The supported attribute categories may differ between the supported + * document flavors. To test for supported attributes one can use the + * {@link #getUnsupportedAttributes(DocFlavor, AttributeSet)} method with + * the specific doc flavor and attributes set. + *

+ * + * @return The supported document flavors. */ DocFlavor[] getSupportedDocFlavors(); /** - * Returns all attributes that are unsupported for a print request in the - * context of a particular document flavor. - * - * @param flavor document flavor to test, or null + * Identifies all the unsupported attributes of the given set of attributes + * in the context of the specified document flavor. + *

+ * The given flavor has to be supported by the print service (use + * {@link #isDocFlavorSupported(DocFlavor)} to verify). The method will + * return null if all given attributes are supported. Otherwise + * a set of unsupported attributes are returned. The attributes in the + * returned set may be completely unsupported or only the specific requested + * value. If flavor is null the default document flavor of the + * print service is used in the identification process. + *

+ * + * @param flavor document flavor to test, or null. * @param attributes set of printing attributes for a supposed job * - * @return null if this PrintService supports the print request - * specification, else the unsupported attributes + * @return null if this print service supports all the given + * attributes for the specified doc flavor. Otherwise the set of unsupported + * attributes are returned. * * @throws IllegalArgumentException if flavor is unsupported */ AttributeSet getUnsupportedAttributes(DocFlavor flavor, AttributeSet attributes); + /** - * Returns a hashcode for this printer service. + * Returns a hashcode for this print service. * - * @return the hashcode + * @return The hashcode. */ int hashCode(); /** - * Determines a given attribute category is supported or not. + * Determines a given attribute category is supported by this + * print service implementation. This only tests for the category + * not for any specific values of this category nor in the context + * of a specific document flavor. * * @param category the category to check * * @return true if category is supported, - * false otherwise + * false otherwise. * - * @throws NullPointerException if category is null + * @throws NullPointerException if category is null * @throws IllegalArgumentException if category is a class not * implementing Attribute. */ boolean isAttributeCategorySupported(Class category); /** - * Determines a given attribute value is supported when creating a print job - * for this print service. + * Determines if a given attribute value is supported when creating a print + * job for this print service. + *

+ * If either the document flavor or the provided attributes are + * null it is determined if the given attribute value is + * supported in some combination of the available document flavors and + * attributes of the print service. Otherwise it is checked for the + * specific context of the given document flavor/attributes set. + *

* * @param attrval the attribute value to check - * @param flavor the document flavor to use, or null - * @param attributes set of printing attributes to use, or null + * @param flavor the document flavor to use, or null. + * @param attributes set of attributes to use, or null. * - * @return true if the attribute value is supported, - * false otherwise + * @return true if the attribute value is supported in the + * requested context, false otherwise. * - * @throws NullPointerException if attrval is null + * @throws NullPointerException if attrval is null. * @throws IllegalArgumentException if flavor is not supported * by this print service */ boolean isAttributeValueSupported(Attribute attrval, DocFlavor flavor, AttributeSet attributes); /** - * Determines a given document flavor is supported or not. + * Determines if a given document flavor is supported or not. * * @param flavor the document flavor to check * * @return true if flavor is supported, - * false otherwise + * false otherwise. * - * @throws NullPointerException if flavor is null + * @throws NullPointerException if flavor is null. */ boolean isDocFlavorSupported(DocFlavor flavor); diff --git a/libjava/classpath/javax/print/ServiceUIFactory.java b/libjava/classpath/javax/print/ServiceUIFactory.java index 66e6114..1a5c1cf 100644 --- a/libjava/classpath/javax/print/ServiceUIFactory.java +++ b/libjava/classpath/javax/print/ServiceUIFactory.java @@ -1,5 +1,5 @@ /* ServiceUIFactory.java -- - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -39,18 +39,47 @@ exception statement from your version. */ package javax.print; /** + * ServiceUIFactory enables print services to provide additional + * user interface dialogs. + *

+ * A print service may provide a ServiceUIFactory implementation + * if its getServiceUIFactory() method is called. If a factory + * object is returned it can be queried for provided user interface dialogs. + * Different roles are defined to denote dialogs providing informations about + * the print service, dialogs for administration of a print service and for + * end-user browsing dialogs. + *

+ * The factory can support providing these UI roles in different dialog types + * (AWT, Swing, JComponent, Panel). The support and use of Swing interfaces is + * however preferred. + *

+ * * @author Michael Koch */ public abstract class ServiceUIFactory { + /** A user interface providing informations about the print service. */ public static final int ABOUT_UIROLE = 1; + + /** A user interface to administer the print service. */ public static final int ADMIN_UIROLE = 2; + + /** A user interface for end-user browsing of the print service. */ public static final int MAIN_UIROLE = 3; + + /** Role IDs greater than this may be used for other private roles. */ public static final int RESERVED_UIROLE = 99; + /** Identifies a UI provided as an AWT dialog. */ public static final String DIALOG_UI = "java.awt.Dialog"; + + /** Identifies a UI provided as a Swing JComponent. */ public static final String JCOMPONENT_UI = "javax.swing.JComponent"; + + /** Identifies a UI provided as a Swing JDialog. */ public static final String JDIALOG_UI = "javax.swing.JDialog"; + + /** Identifies a UI provided as an AWT Panel. */ public static final String PANEL_UI = "java.awt.Panel"; /** diff --git a/libjava/classpath/javax/print/SimpleDoc.java b/libjava/classpath/javax/print/SimpleDoc.java new file mode 100644 index 0000000..a49406b --- /dev/null +++ b/libjava/classpath/javax/print/SimpleDoc.java @@ -0,0 +1,223 @@ +/* SimpleDoc.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 javax.print; + +import java.io.ByteArrayInputStream; +import java.io.CharArrayReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.io.StringReader; + +import javax.print.attribute.AttributeSetUtilities; +import javax.print.attribute.DocAttributeSet; + +/** + * Simple implementation of the Doc interface capable of handling + * the predefined document flavors of DocFlavor. + *

+ * This implementation can construct a reader or stream for the service from + * the print data and ensures that always the same object is returned on each + * method call. It does simple checks that the supplied data matches the + * specified flavor of the doc object and supports thread safe access. + *

+ * + * @author Wolfgang Baer (WBaer@gmx.de) + */ +public final class SimpleDoc implements Doc +{ + private final Object printData; + private final DocFlavor flavor; + private final DocAttributeSet attributes; + + private InputStream stream; + private Reader reader; + + /** + * Constructs a SimpleDoc with the specified print data, doc flavor and doc attribute set. + * @param printData the object with the data to print. + * @param flavor the document flavor of the print data. + * @param attributes the attributes of the doc (may be null). + * + * @throws IllegalArgumentException if either printData or + * flavor are null, or the print data is not + * supplied in the document format specified by the given flavor object. + */ + public SimpleDoc(Object printData, DocFlavor flavor, + DocAttributeSet attributes) + { + if (printData == null || flavor == null) + throw new IllegalArgumentException("printData/flavor may not be null"); + + if (! (printData.getClass().getName().equals( + flavor.getRepresentationClassName()) + || flavor.getRepresentationClassName().equals("java.io.Reader") + && printData instanceof Reader + || flavor.getRepresentationClassName().equals("java.io.InputStream") + && printData instanceof InputStream)) + { + throw new IllegalArgumentException("data is not of declared flavor type"); + } + + this.printData = printData; + this.flavor = flavor; + + if (attributes != null) + this.attributes = AttributeSetUtilities.unmodifiableView(attributes); + else + this.attributes = null; + + stream = null; + reader = null; + } + + /** + * Returns the unmodifiable view of the attributes of this doc object. + *

+ * The attributes of this doc's attributes set overrides attributes of + * the same category in the print job's attribute set. If an attribute + * is not available in this doc's attributes set or null + * is returned the attributes of the same category of the print job are + * used. + *

+ * + * @return The unmodifiable attributes set, or null. + */ + public DocAttributeSet getAttributes() + { + return attributes; + } + + /** + * Returns the flavor of this doc objects print data. + * + * @return The document flavor. + */ + public DocFlavor getDocFlavor() + { + return flavor; + } + + /** + * Returns the print data of this doc object. + *

+ * The returned object is an instance as described by the associated + * document flavor ({@link DocFlavor#getRepresentationClassName()}) + * and can be cast to this representation class. + *

+ * + * @return The print data in the representation class. + * @throws IOException if representation class is a stream and I/O + * exception occures. + */ + public Object getPrintData() throws IOException + { + return printData; + } + + /** + * Returns a Reader object for extracting character print data + * from this document. + *

+ * This method is supported if the document flavor is of type: + *

+ * otherwise this method returns null. + *

+ * + * @return The Reader object, or null. + * + * @throws IOException if an error occurs. + */ + public Reader getReaderForText() throws IOException + { + synchronized (this) + { + // construct the reader if applicable on request + if (reader == null) + { + if (flavor instanceof DocFlavor.CHAR_ARRAY) + reader = new CharArrayReader((char[]) printData); + else if (flavor instanceof DocFlavor.STRING) + reader = new StringReader((String) printData); + else if (flavor instanceof DocFlavor.READER) + reader = (Reader) printData; + } + + return reader; + } + } + + /** + * Returns an InputStream object for extracting byte print data + * from this document. + *

+ * This method is supported if the document flavor is of type: + *

+ * otherwise this method returns null. + *

+ * + * @return The InputStream object, or null. + * + * @throws IOException if an error occurs. + */ + public InputStream getStreamForBytes() throws IOException + { + synchronized (this) + { + // construct the stream if applicable on request + if (stream == null) + { + if (flavor instanceof DocFlavor.BYTE_ARRAY) + stream = new ByteArrayInputStream((byte[]) printData); + else if (flavor instanceof DocFlavor.INPUT_STREAM) + stream = (InputStream) printData; + } + + return stream; + } + } + +} diff --git a/libjava/classpath/javax/print/StreamPrintService.java b/libjava/classpath/javax/print/StreamPrintService.java index 9246ea4..8398a73 100644 --- a/libjava/classpath/javax/print/StreamPrintService.java +++ b/libjava/classpath/javax/print/StreamPrintService.java @@ -1,5 +1,5 @@ /* StreamPrintService.java -- - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -42,6 +42,15 @@ import java.io.OutputStream; /** + * StreamPrintService is a special print service capable of + * printing into a supplied output stream. + *

+ * Beside providing the same functionality as a print service it additionally + * allows to specify the output stream for the print data. A stream print + * service is obtained via the {@link javax.print.StreamPrintServiceFactory} + * by looking for services supporting a given output format type. + *

+ * * @author Michael Koch (konqueror@gmx.de) */ public abstract class StreamPrintService implements PrintService @@ -68,16 +77,18 @@ public abstract class StreamPrintService implements PrintService } /** - * Returns the document format emited by this print service. + * Returns the document format emitted by this print service. + * The returned string is a MIME type compatible with the + * {@link DocFlavor} class. * - * @return the document format + * @return The document format of the output. */ public abstract String getOutputFormat(); /** * Returns the OutputStream of this object. * - * @return the OutputStream + * @return The OutputStream */ public OutputStream getOutputStream() { diff --git a/libjava/classpath/javax/print/StreamPrintServiceFactory.java b/libjava/classpath/javax/print/StreamPrintServiceFactory.java new file mode 100644 index 0000000..90496b3 --- /dev/null +++ b/libjava/classpath/javax/print/StreamPrintServiceFactory.java @@ -0,0 +1,130 @@ +/* StreamPrintServiceFactory.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 javax.print; + +import gnu.classpath.ServiceFactory; + +import java.io.OutputStream; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; + +/** + * StreamPrintServiceFactory provides a static method to lookup + * registered factories to construct StreamPrintService instances. + *

+ * StreamPrintService are used to print into a provided output + * stream in the document format provided by the stream print service + * implementation. + *

+ * Implementations are located and loaded automatically through the SPI JAR + * file specification. Therefore implementation classes must provide a default + * constructor for instantiation. + *

+ * + * @author Wolfgang Baer (WBaer@gmx.de) + */ +public abstract class StreamPrintServiceFactory +{ + /** + * Default public constructor. + * Used for automatic loading and instantiation through + * the SPI jar file specification. + */ + public StreamPrintServiceFactory() + { + // nothing to do + } + + /** + * Searches for matching factories providing stream print services that + * support the printing of documents with the given document flavor into + * the given output mime type. + * + * @param flavor the document flavor needed, null doesn't + * constrain the lookup result. + * @param outputMimeType the mime type needed, null doesn't + * constrain the lookup result. + * + * @return The matching StreamPrintServiceFactory instances. + */ + public static StreamPrintServiceFactory[] lookupStreamPrintServiceFactories( + DocFlavor flavor, String outputMimeType) + { + HashSet set = new HashSet(); + + Iterator it = + ServiceFactory.lookupProviders(StreamPrintServiceFactory.class); + + while (it.hasNext()) + { + StreamPrintServiceFactory tmp = (StreamPrintServiceFactory) it.next(); + if (tmp.getOutputFormat().equals(outputMimeType) + && Arrays.asList(tmp.getSupportedDocFlavors()).contains(flavor)) + set.add(tmp); + } + + StreamPrintServiceFactory[] tmp = new StreamPrintServiceFactory[set.size()]; + return (StreamPrintServiceFactory[]) set.toArray(tmp); + } + + /** + * Returns the output format supported by this factory. + * + * @return The mime type of the output format as string representation. + */ + public abstract String getOutputFormat(); + + /** + * Returns the document flavors this factory supports as flavors + * for the input documents. + * + * @return The array of supported document flavors. + */ + public abstract DocFlavor[] getSupportedDocFlavors(); + + /** + * Constructs a StreamPrintService which directs its output + * the given output stream. + * + * @param out the output stream for the produced document. + * @return The constructed stream print service. + */ + public abstract StreamPrintService getPrintService(OutputStream out); +} diff --git a/libjava/classpath/javax/print/attribute/AttributeSetUtilities.java b/libjava/classpath/javax/print/attribute/AttributeSetUtilities.java index 5d97c66..f6a64eb 100644 --- a/libjava/classpath/javax/print/attribute/AttributeSetUtilities.java +++ b/libjava/classpath/javax/print/attribute/AttributeSetUtilities.java @@ -1,5 +1,5 @@ /* AttributeSetUtilities.java -- - Copyright (C) 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -78,14 +78,14 @@ public final class AttributeSetUtilities private static class UnmodifiableAttributeSet implements AttributeSet, Serializable { - private AttributeSet set; + private AttributeSet attrset; public UnmodifiableAttributeSet(AttributeSet attributeSet) { if (attributeSet == null) throw new NullPointerException("attributeSet may not be null"); - this.set = attributeSet; + this.attrset = attributeSet; } public boolean add(Attribute attribute) @@ -105,32 +105,32 @@ public final class AttributeSetUtilities public boolean containsKey(Class category) { - return set.containsKey(category); + return attrset.containsKey(category); } public boolean containsValue(Attribute attribute) { - return set.containsValue(attribute); + return attrset.containsValue(attribute); } public boolean equals(Object obj) { - return set.equals(obj); + return attrset.equals(obj); } public Attribute get(Class interfaceName) { - return set.get(interfaceName); + return attrset.get(interfaceName); } public int hashCode() { - return set.hashCode(); + return attrset.hashCode(); } public boolean isEmpty() { - return set.isEmpty(); + return attrset.isEmpty(); } public boolean remove(Class category) @@ -145,12 +145,12 @@ public final class AttributeSetUtilities public int size() { - return set.size(); + return attrset.size(); } public Attribute[] toArray() { - return set.toArray(); + return attrset.toArray(); } } @@ -197,79 +197,79 @@ public final class AttributeSetUtilities private static class SynchronizedAttributeSet implements AttributeSet, Serializable { - private AttributeSet set; + private AttributeSet attrset; public SynchronizedAttributeSet(AttributeSet attributeSet) { if (attributeSet == null) throw new NullPointerException("attributeSet may not be null"); - this.set = attributeSet; + attrset = attributeSet; } public synchronized boolean add(Attribute attribute) { - return set.add(attribute); + return attrset.add(attribute); } public synchronized boolean addAll(AttributeSet attributes) { - return set.addAll(attributes); + return attrset.addAll(attributes); } public synchronized void clear() { - set.clear(); + attrset.clear(); } public synchronized boolean containsKey(Class category) { - return set.containsKey(category); + return attrset.containsKey(category); } public synchronized boolean containsValue(Attribute attribute) { - return set.containsValue(attribute); + return attrset.containsValue(attribute); } public synchronized boolean equals(Object obj) { - return set.equals(obj); + return attrset.equals(obj); } public synchronized Attribute get(Class interfaceName) { - return set.get(interfaceName); + return attrset.get(interfaceName); } public synchronized int hashCode() { - return set.hashCode(); + return attrset.hashCode(); } public synchronized boolean isEmpty() { - return set.isEmpty(); + return attrset.isEmpty(); } public synchronized boolean remove(Class category) { - return set.remove(category); + return attrset.remove(category); } public synchronized boolean remove(Attribute attribute) { - return set.remove(attribute); + return attrset.remove(attribute); } public synchronized int size() { - return set.size(); + return attrset.size(); } public synchronized Attribute[] toArray() { - return set.toArray(); + return attrset.toArray(); } } diff --git a/libjava/classpath/javax/print/attribute/DateTimeSyntax.java b/libjava/classpath/javax/print/attribute/DateTimeSyntax.java index d591932..8cff702 100644 --- a/libjava/classpath/javax/print/attribute/DateTimeSyntax.java +++ b/libjava/classpath/javax/print/attribute/DateTimeSyntax.java @@ -102,4 +102,14 @@ public abstract class DateTimeSyntax implements Cloneable, Serializable { return value.hashCode(); } + + /** + * Returns the string representation for this object. + * + * @return The string representation. + */ + public String toString() + { + return value.toString(); + } } diff --git a/libjava/classpath/javax/print/attribute/HashAttributeSet.java b/libjava/classpath/javax/print/attribute/HashAttributeSet.java index 0db81ba..65371ea 100644 --- a/libjava/classpath/javax/print/attribute/HashAttributeSet.java +++ b/libjava/classpath/javax/print/attribute/HashAttributeSet.java @@ -1,5 +1,5 @@ /* HashAttributeSet.java -- - Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -37,6 +37,9 @@ exception statement from your version. */ package javax.print.attribute; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.HashMap; import java.util.Iterator; @@ -49,8 +52,8 @@ public class HashAttributeSet implements AttributeSet, Serializable { private static final long serialVersionUID = 5311560590283707917L; - private Class interfaceName; - private HashMap attributeMap = new HashMap(); + private Class myInterface; + private transient HashMap attributeMap = new HashMap(); /** * Creates an empty HashAttributeSet object. @@ -112,7 +115,7 @@ public class HashAttributeSet implements AttributeSet, Serializable if (interfaceName == null) throw new NullPointerException("interfaceName may not be null"); - this.interfaceName = interfaceName; + myInterface = interfaceName; } /** @@ -192,7 +195,7 @@ public class HashAttributeSet implements AttributeSet, Serializable */ public boolean add(Attribute attribute) { - return addInternal(attribute, interfaceName); + return addInternal(attribute, myInterface); } private boolean addInternal(Attribute attribute, Class interfaceName) @@ -201,7 +204,7 @@ public class HashAttributeSet implements AttributeSet, Serializable throw new NullPointerException("attribute may not be null"); AttributeSetUtilities.verifyAttributeCategory(interfaceName, - this.interfaceName); + myInterface); Object old = attributeMap.put (attribute.getCategory(), AttributeSetUtilities.verifyAttributeValue @@ -220,7 +223,7 @@ public class HashAttributeSet implements AttributeSet, Serializable */ public boolean addAll(AttributeSet attributes) { - return addAllInternal(attributes, interfaceName); + return addAllInternal(attributes, myInterface); } private boolean addAllInternal(AttributeSet attributes, Class interfaceName) @@ -393,4 +396,24 @@ public class HashAttributeSet implements AttributeSet, Serializable return array; } + + // Implemented as specified in serialized form + private void readObject(ObjectInputStream s) + throws ClassNotFoundException, IOException + { + myInterface = (Class) s.readObject(); + int size = s.readInt(); + attributeMap = new HashMap(size); + for (int i=0; i < size; i++) + add((Attribute) s.readObject()); + } + + private void writeObject(ObjectOutputStream s) throws IOException + { + s.writeObject(myInterface); + s.writeInt(size()); + Iterator it = attributeMap.values().iterator(); + while (it.hasNext()) + s.writeObject(it.next()); + } } diff --git a/libjava/classpath/javax/print/attribute/standard/Compression.java b/libjava/classpath/javax/print/attribute/standard/Compression.java index d29ffa0..01891fe 100644 --- a/libjava/classpath/javax/print/attribute/standard/Compression.java +++ b/libjava/classpath/javax/print/attribute/standard/Compression.java @@ -1,5 +1,5 @@ /* Compression.java -- - Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -91,7 +91,7 @@ public class Compression extends EnumSyntax * * @return The class Compression itself. */ - public Class getCategory() + public final Class getCategory() { return Compression.class; } @@ -101,7 +101,7 @@ public class Compression extends EnumSyntax * * @return The name "compression". */ - public String getName() + public final String getName() { return "compression"; } diff --git a/libjava/classpath/javax/print/attribute/standard/Finishings.java b/libjava/classpath/javax/print/attribute/standard/Finishings.java index 6d474a6..963485e 100644 --- a/libjava/classpath/javax/print/attribute/standard/Finishings.java +++ b/libjava/classpath/javax/print/attribute/standard/Finishings.java @@ -1,5 +1,5 @@ /* Finishings.java -- - Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -238,7 +238,7 @@ public class Finishings extends EnumSyntax * * @return the class Finishings itself */ - public Class getCategory() + public final Class getCategory() { return Finishings.class; } @@ -248,7 +248,7 @@ public class Finishings extends EnumSyntax * * @return The name "finishings". */ - public String getName() + public final String getName() { return "finishings"; } diff --git a/libjava/classpath/javax/print/attribute/standard/JobMediaSheets.java b/libjava/classpath/javax/print/attribute/standard/JobMediaSheets.java index 75e072c..04b8306 100644 --- a/libjava/classpath/javax/print/attribute/standard/JobMediaSheets.java +++ b/libjava/classpath/javax/print/attribute/standard/JobMediaSheets.java @@ -1,5 +1,5 @@ /* JobMediaSheets.java -- - Copyright (C) 2003, 2005 Free Software Foundation, Inc. + Copyright (C) 2003, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -107,7 +107,7 @@ public class JobMediaSheets extends IntegerSyntax * * @return The class JobMediaSheets itself. */ - public Class getCategory() + public final Class getCategory() { return JobMediaSheets.class; } @@ -117,7 +117,7 @@ public class JobMediaSheets extends IntegerSyntax * * @return The name "job-media-sheets". */ - public String getName() + public final String getName() { return "job-media-sheets"; } diff --git a/libjava/classpath/javax/print/attribute/standard/JobSheets.java b/libjava/classpath/javax/print/attribute/standard/JobSheets.java index d61acfe..f2cfacc 100644 --- a/libjava/classpath/javax/print/attribute/standard/JobSheets.java +++ b/libjava/classpath/javax/print/attribute/standard/JobSheets.java @@ -1,5 +1,5 @@ /* JobSheets.java -- - Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -88,7 +88,7 @@ public class JobSheets extends EnumSyntax * * @return The class JobSheets itself. */ - public Class getCategory() + public final Class getCategory() { return JobSheets.class; } @@ -98,7 +98,7 @@ public class JobSheets extends EnumSyntax * * @return The name "job-sheets". */ - public String getName() + public final String getName() { return "job-sheets"; } diff --git a/libjava/classpath/javax/print/attribute/standard/JobState.java b/libjava/classpath/javax/print/attribute/standard/JobState.java index bd09e1f..8289569 100644 --- a/libjava/classpath/javax/print/attribute/standard/JobState.java +++ b/libjava/classpath/javax/print/attribute/standard/JobState.java @@ -1,5 +1,5 @@ /* JobState.java -- - Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -137,7 +137,7 @@ public class JobState extends EnumSyntax * * @return The class JobState itself. */ - public Class getCategory() + public final Class getCategory() { return JobState.class; } @@ -147,7 +147,7 @@ public class JobState extends EnumSyntax * * @return The name "job-state". */ - public String getName() + public final String getName() { return "job-state"; } diff --git a/libjava/classpath/javax/print/attribute/standard/JobStateReason.java b/libjava/classpath/javax/print/attribute/standard/JobStateReason.java index bd831cd..967a6bf 100644 --- a/libjava/classpath/javax/print/attribute/standard/JobStateReason.java +++ b/libjava/classpath/javax/print/attribute/standard/JobStateReason.java @@ -1,5 +1,5 @@ /* JobStateReason.java -- - Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -262,7 +262,7 @@ public class JobStateReason extends EnumSyntax * * @return The class JobStateReason itself. */ - public Class getCategory() + public final Class getCategory() { return JobStateReason.class; } @@ -272,7 +272,7 @@ public class JobStateReason extends EnumSyntax * * @return The name "job-state-reason". */ - public String getName() + public final String getName() { return "job-state-reason"; } diff --git a/libjava/classpath/javax/print/attribute/standard/JobStateReasons.java b/libjava/classpath/javax/print/attribute/standard/JobStateReasons.java index 9dbca0c..32f942b 100644 --- a/libjava/classpath/javax/print/attribute/standard/JobStateReasons.java +++ b/libjava/classpath/javax/print/attribute/standard/JobStateReasons.java @@ -131,7 +131,7 @@ public final class JobStateReasons extends HashSet if (o == null) throw new NullPointerException("reason is null"); - return add((JobStateReason) o); + return super.add((JobStateReason) o); } /** diff --git a/libjava/classpath/javax/print/attribute/standard/Media.java b/libjava/classpath/javax/print/attribute/standard/Media.java index 202a3f3..37132e7 100644 --- a/libjava/classpath/javax/print/attribute/standard/Media.java +++ b/libjava/classpath/javax/print/attribute/standard/Media.java @@ -1,5 +1,5 @@ /* Media.java -- - Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -105,7 +105,7 @@ public abstract class Media extends EnumSyntax * * @return The class Media itself. */ - public Class getCategory() + public final Class getCategory() { return Media.class; } @@ -115,7 +115,7 @@ public abstract class Media extends EnumSyntax * * @return The name "media". */ - public String getName() + public final String getName() { return "media"; } diff --git a/libjava/classpath/javax/print/attribute/standard/MediaPrintableArea.java b/libjava/classpath/javax/print/attribute/standard/MediaPrintableArea.java index 9a1342c..e0366f5 100644 --- a/libjava/classpath/javax/print/attribute/standard/MediaPrintableArea.java +++ b/libjava/classpath/javax/print/attribute/standard/MediaPrintableArea.java @@ -1,5 +1,5 @@ /* MediaPrintableArea.java -- - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -95,9 +95,9 @@ public final class MediaPrintableArea /** y in micrometers. */ private int y; /** width in micrometers. */ - private int width; + private int w; /** height in micrometers. */ - private int height; + private int h; /** * Creates a new MediaPrintableArea object with the given @@ -119,8 +119,8 @@ public final class MediaPrintableArea this.x = (int) (x * units + 0.5f); this.y = (int) (y * units + 0.5f); - this.width = (int) (w * units + 0.5f); - this.height = (int) (h * units + 0.5f); + this.w = (int) (w * units + 0.5f); + this.h = (int) (h * units + 0.5f); } /** @@ -143,8 +143,8 @@ public final class MediaPrintableArea this.x = x * units; this.y = y * units; - this.width = w * units; - this.height = h * units; + this.w = w * units; + this.h = h * units; } /** @@ -180,7 +180,7 @@ public final class MediaPrintableArea if (units < 1) throw new IllegalArgumentException("units may not be less than 1"); - return height / ((float)units); + return h / ((float)units); } /** @@ -196,7 +196,7 @@ public final class MediaPrintableArea if (units < 1) throw new IllegalArgumentException("units may not be less than 1"); - return width / ((float)units); + return w / ((float)units); } /** @@ -248,7 +248,7 @@ public final class MediaPrintableArea MediaPrintableArea tmp = (MediaPrintableArea) obj; return (x == tmp.getX(1) && y == tmp.getY(1) - && width == tmp.getWidth(1) && height == tmp.getHeight(1)); + && w == tmp.getWidth(1) && h == tmp.getHeight(1)); } /** @@ -270,7 +270,7 @@ public final class MediaPrintableArea */ public int hashCode() { - return x ^ y + width ^ height; + return x ^ y + w ^ h; } /** diff --git a/libjava/classpath/javax/print/attribute/standard/MediaSize.java b/libjava/classpath/javax/print/attribute/standard/MediaSize.java index 00bcb34..982b5c5 100644 --- a/libjava/classpath/javax/print/attribute/standard/MediaSize.java +++ b/libjava/classpath/javax/print/attribute/standard/MediaSize.java @@ -1,5 +1,5 @@ /* MediaSize.java -- - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -72,7 +72,14 @@ public class MediaSize extends Size2DSyntax static { mediaCache = new ArrayList(); - + + // We call one instance of every container class to make sure it gets + // loaded during class initialization and therefore all other static + // fields of this container class also. + + // This is needed to put all MediaSize instance into the mediaCache + // for use by the static methods in this class. + MediaSize tmp = MediaSize.ISO.A0; tmp = MediaSize.JIS.B0; tmp = MediaSize.Engineering.A; @@ -80,16 +87,21 @@ public class MediaSize extends Size2DSyntax tmp = MediaSize.Other.EXECUTIVE; } - private MediaSizeName media; + private MediaSizeName mediaName; /** - * Creates a MediaSize object. + * Creates a MediaSize object. The created object will be added + * to an internal cache used in the static methods of this class for lookup + * of available MediaSize instances. * * @param x the size in x direction * @param y the size in y direction * @param units the units to use for the sizes * * @exception IllegalArgumentException if x or y < 0 or units < 1 + * + * @see #findMedia(float, float, int) + * @see #getMediaSizeForName(MediaSizeName) */ public MediaSize(float x, float y, int units) { @@ -99,7 +111,9 @@ public class MediaSize extends Size2DSyntax /** * Creates a MediaSize object associated with the given - * media name. + * media name. The created object will be added to an internal cache used + * in the static methods of this class for lookup of available + * MediaSize instances. * * @param x the size in x direction * @param y the size in y direction @@ -107,22 +121,30 @@ public class MediaSize extends Size2DSyntax * @param media the media name to associate * * @exception IllegalArgumentException if x or y < 0 or units < 1 + * + * @see #findMedia(float, float, int) + * @see #getMediaSizeForName(MediaSizeName) */ public MediaSize(float x, float y, int units, MediaSizeName media) { super(x, y, units); - this.media = media; + mediaName = media; mediaCache.add(this); } /** - * Creates a MediaSize object. + * Creates a MediaSize object. The created object will be added + * to an internal cache used in the static methods of this class for lookup + * of available MediaSize instances. * * @param x the size in x direction * @param y the size in y direction * @param units the units to use for the sizes * * @exception IllegalArgumentException if x or y < 0 or units < 1 + * + * @see #findMedia(float, float, int) + * @see #getMediaSizeForName(MediaSizeName) */ public MediaSize(int x, int y, int units) { @@ -132,7 +154,9 @@ public class MediaSize extends Size2DSyntax /** * Creates a MediaSize object associated with the given - * media name. + * media name. The created object will be added to an internal cache used + * in the static methods of this class for lookup of available + * MediaSize instances. * * @param x the size in x direction * @param y the size in y direction @@ -140,11 +164,14 @@ public class MediaSize extends Size2DSyntax * @param media the media name to associate * * @exception IllegalArgumentException if x or y < 0 or units < 1 + * + * @see #findMedia(float, float, int) + * @see #getMediaSizeForName(MediaSizeName) */ public MediaSize(int x, int y, int units, MediaSizeName media) { super(x, y, units); - this.media = media; + mediaName = media; mediaCache.add(this); } @@ -153,7 +180,7 @@ public class MediaSize extends Size2DSyntax * * @return The class MediaSize itself. */ - public Class getCategory() + public final Class getCategory() { return MediaSize.class; } @@ -246,7 +273,7 @@ public class MediaSize extends Size2DSyntax */ public MediaSizeName getMediaSizeName() { - return media; + return mediaName; } /** @@ -254,7 +281,7 @@ public class MediaSize extends Size2DSyntax * * @return The name "media-size". */ - public String getName() + public final String getName() { return "media-size"; } @@ -266,7 +293,11 @@ public class MediaSize extends Size2DSyntax */ public static final class ISO { - + private ISO() + { + // prevent instantiation + } + /** * ISO A0 paper, 841 mm x 1189 mm. */ @@ -415,6 +446,11 @@ public class MediaSize extends Size2DSyntax */ public static final class NA { + private NA() + { + // prevent instantiation + } + /** * US Legal paper size, 8.5 inch x 14 inch */ @@ -530,6 +566,11 @@ public class MediaSize extends Size2DSyntax */ public static final class Engineering { + private Engineering() + { + // prevent instantiation + } + /** * ANSI A paper size. 8.5 inch x 11 inch */ @@ -568,6 +609,11 @@ public class MediaSize extends Size2DSyntax */ public static final class JIS { + private JIS() + { + // prevent instantiation + } + /** * JIS B0 paper. 1030 mm x 1456 mm * Note: The JIS B-series is not identical to the ISO B-series. @@ -762,6 +808,11 @@ public class MediaSize extends Size2DSyntax */ public static final class Other { + private Other() + { + // prevent instantiation + } + /** * US Executive paper size, 7.25 inch x 10.5 inch */ @@ -820,6 +871,13 @@ public class MediaSize extends Size2DSyntax * Japanese double postcard, 148 mm x 200 mm */ public static final MediaSize JAPANESE_DOUBLE_POSTCARD = new MediaSize(148, 200, MediaSize.MM, MediaSizeName.JAPANESE_DOUBLE_POSTCARD); + + /** + * Tabloid size, 11 inch x 17 inch. + * @since 1.5 + */ + public static final MediaSize TABLOID = + new MediaSize(11, 17, Size2DSyntax.INCH, MediaSizeName.TABLOID); } } diff --git a/libjava/classpath/javax/print/attribute/standard/MultipleDocumentHandling.java b/libjava/classpath/javax/print/attribute/standard/MultipleDocumentHandling.java index 1ed0c91..1a89fd0 100644 --- a/libjava/classpath/javax/print/attribute/standard/MultipleDocumentHandling.java +++ b/libjava/classpath/javax/print/attribute/standard/MultipleDocumentHandling.java @@ -1,5 +1,5 @@ /* MultipleDocumentHandling.java -- - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -108,7 +108,7 @@ public class MultipleDocumentHandling extends EnumSyntax * * @return The class MultipleDocumentHandling itself. */ - public Class getCategory() + public final Class getCategory() { return MultipleDocumentHandling.class; } @@ -118,7 +118,7 @@ public class MultipleDocumentHandling extends EnumSyntax * * @return The name "multiple-document-handling". */ - public String getName() + public final String getName() { return "multiple-document-handling"; } diff --git a/libjava/classpath/javax/print/attribute/standard/PDLOverrideSupported.java b/libjava/classpath/javax/print/attribute/standard/PDLOverrideSupported.java index d3be3e5..ee07edb 100644 --- a/libjava/classpath/javax/print/attribute/standard/PDLOverrideSupported.java +++ b/libjava/classpath/javax/print/attribute/standard/PDLOverrideSupported.java @@ -1,5 +1,5 @@ /* PDLOverrideSupported.java -- - Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -91,7 +91,7 @@ public class PDLOverrideSupported extends EnumSyntax * * @return The class PDLOverrideSupported itself. */ - public Class getCategory() + public final Class getCategory() { return PDLOverrideSupported.class; } @@ -101,7 +101,7 @@ public class PDLOverrideSupported extends EnumSyntax * * @return The name "pdl-override-supported". */ - public String getName() + public final String getName() { return "pdl-override-supported"; } diff --git a/libjava/classpath/javax/print/attribute/standard/PrintQuality.java b/libjava/classpath/javax/print/attribute/standard/PrintQuality.java index 2f1a105..c581d5f 100644 --- a/libjava/classpath/javax/print/attribute/standard/PrintQuality.java +++ b/libjava/classpath/javax/print/attribute/standard/PrintQuality.java @@ -1,5 +1,5 @@ /* PrintQuality.java -- - Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -92,7 +92,7 @@ public class PrintQuality extends EnumSyntax * * @return The class PrintQuality itself. */ - public Class getCategory() + public final Class getCategory() { return PrintQuality.class; } @@ -102,7 +102,7 @@ public class PrintQuality extends EnumSyntax * * @return The name "print-quality". */ - public String getName() + public final String getName() { return "print-quality"; } diff --git a/libjava/classpath/javax/print/attribute/standard/PrinterIsAcceptingJobs.java b/libjava/classpath/javax/print/attribute/standard/PrinterIsAcceptingJobs.java index 51f96c1..96dbc57c 100644 --- a/libjava/classpath/javax/print/attribute/standard/PrinterIsAcceptingJobs.java +++ b/libjava/classpath/javax/print/attribute/standard/PrinterIsAcceptingJobs.java @@ -55,7 +55,7 @@ import javax.print.attribute.PrintServiceAttribute; * @author Michael Koch (konqueror@gmx.de) * @author Wolfgang Baer (WBaer@gmx.de) */ -public class PrinterIsAcceptingJobs extends EnumSyntax +public final class PrinterIsAcceptingJobs extends EnumSyntax implements PrintServiceAttribute { private static final long serialVersionUID = -5052010680537678061L; diff --git a/libjava/classpath/javax/print/attribute/standard/PrinterStateReason.java b/libjava/classpath/javax/print/attribute/standard/PrinterStateReason.java index 3a13585..340bfba 100644 --- a/libjava/classpath/javax/print/attribute/standard/PrinterStateReason.java +++ b/libjava/classpath/javax/print/attribute/standard/PrinterStateReason.java @@ -1,5 +1,5 @@ /* PrinterStateReason.java -- - Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -293,7 +293,7 @@ public class PrinterStateReason extends EnumSyntax * * @return The class PrintStateReason itself. */ - public Class getCategory() + public final Class getCategory() { return PrinterStateReason.class; } @@ -303,7 +303,7 @@ public class PrinterStateReason extends EnumSyntax * * @return The name "printer-state-reason". */ - public String getName() + public final String getName() { return "printer-state-reason"; } diff --git a/libjava/classpath/javax/print/attribute/standard/PrinterStateReasons.java b/libjava/classpath/javax/print/attribute/standard/PrinterStateReasons.java index 67f160d..40c6f1b 100644 --- a/libjava/classpath/javax/print/attribute/standard/PrinterStateReasons.java +++ b/libjava/classpath/javax/print/attribute/standard/PrinterStateReasons.java @@ -178,7 +178,7 @@ public final class PrinterStateReasons extends HashMap if (severity == null) throw new NullPointerException("severity is null"); - return put((PrinterStateReason) reason, (Severity) severity); + return super.put((PrinterStateReason) reason, (Severity) severity); } /** diff --git a/libjava/classpath/javax/print/attribute/standard/ReferenceUriSchemesSupported.java b/libjava/classpath/javax/print/attribute/standard/ReferenceUriSchemesSupported.java index 8a00218..aeccaac 100644 --- a/libjava/classpath/javax/print/attribute/standard/ReferenceUriSchemesSupported.java +++ b/libjava/classpath/javax/print/attribute/standard/ReferenceUriSchemesSupported.java @@ -1,5 +1,5 @@ /* ReferenceUriSchemesSupported.java -- - Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -128,7 +128,7 @@ public class ReferenceUriSchemesSupported extends EnumSyntax * * @return The class ReferenceUriSchemesSupported itself. */ - public Class getCategory() + public final Class getCategory() { return ReferenceUriSchemesSupported.class; } @@ -138,7 +138,7 @@ public class ReferenceUriSchemesSupported extends EnumSyntax * * @return The name "reference-uri-schemes-supported". */ - public String getName() + public final String getName() { return "reference-uri-schemes-supported"; } diff --git a/libjava/classpath/javax/security/auth/login/AppConfigurationEntry.java b/libjava/classpath/javax/security/auth/login/AppConfigurationEntry.java index 557d3d7..b455dbb 100644 --- a/libjava/classpath/javax/security/auth/login/AppConfigurationEntry.java +++ b/libjava/classpath/javax/security/auth/login/AppConfigurationEntry.java @@ -1,5 +1,5 @@ /* AppConfigurationEntry.java - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -44,7 +44,6 @@ import java.util.Map; public class AppConfigurationEntry { - // Fields. // ------------------------------------------------------------------------- @@ -61,13 +60,16 @@ public class AppConfigurationEntry { if (loginModuleName == null || loginModuleName.length() == 0) throw new IllegalArgumentException ("module name cannot be null nor empty"); + if (LoginModuleControlFlag.OPTIONAL != controlFlag && LoginModuleControlFlag.REQUIRED != controlFlag && LoginModuleControlFlag.REQUISITE != controlFlag && LoginModuleControlFlag.SUFFICIENT != controlFlag) throw new IllegalArgumentException ("invalid controlFlag"); + if (options == null) throw new IllegalArgumentException ("options cannot be null"); + this.loginModuleName = loginModuleName; this.controlFlag = controlFlag; this.options = Collections.unmodifiableMap (new HashMap (options)); @@ -91,7 +93,17 @@ public class AppConfigurationEntry return options; } - // Inner class. + // Object methods ---------------------------------------------------------- + + public String toString() + { + + return loginModuleName + "\t" + + String.valueOf(controlFlag) + "\t" + + String.valueOf(options); + } + + // Inner class. // ------------------------------------------------------------------------- public static class LoginModuleControlFlag @@ -117,19 +129,15 @@ public class AppConfigurationEntry public String toString() { - StringBuffer buf = new StringBuffer (LoginModuleControlFlag.class.getName()); - buf.append ('.'); - if (this == OPTIONAL) - buf.append ("OPTIONAL"); - else if (this == REQUIRED) - buf.append ("REQUIRED"); - else if (this == REQUISITE) - buf.append ("REQUISITE"); - else if (this == SUFFICIENT) - buf.append ("SUFFICIENT"); - else - buf.append ("HARVEY_THE_RABBIT"); - return buf.toString(); + if (this == LoginModuleControlFlag.REQUIRED) + return "REQUIRED"; + if (this == LoginModuleControlFlag.REQUISITE) + return "REQUISITE"; + if (this == LoginModuleControlFlag.SUFFICIENT) + return "SUFFICIENT"; + if (this == LoginModuleControlFlag.OPTIONAL) + return "OPTIONAL"; + return "???"; } } } diff --git a/libjava/classpath/javax/security/auth/login/Configuration.java b/libjava/classpath/javax/security/auth/login/Configuration.java index eb5e4a8..fe56f8a 100644 --- a/libjava/classpath/javax/security/auth/login/Configuration.java +++ b/libjava/classpath/javax/security/auth/login/Configuration.java @@ -1,5 +1,5 @@ /* Configuration.java - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,6 +38,8 @@ exception statement from your version. */ package javax.security.auth.login; +import gnu.javax.security.auth.login.GnuConfiguration; + import java.security.AccessController; import java.security.PrivilegedAction; import java.security.Security; @@ -46,7 +48,6 @@ import javax.security.auth.AuthPermission; public abstract class Configuration { - // Fields. // ------------------------------------------------------------------------- @@ -108,11 +109,11 @@ public abstract class Configuration if (conf != null) config = (Configuration) Class.forName (conf).newInstance(); else - config = new NullConfiguration(); + config = new GnuConfiguration(); } catch (Exception x) { - config = new NullConfiguration(); + config = new GnuConfiguration(); } } return config; diff --git a/libjava/classpath/javax/sound/sampled/LineEvent.java b/libjava/classpath/javax/sound/sampled/LineEvent.java index 7bba2cd..db92593 100644 --- a/libjava/classpath/javax/sound/sampled/LineEvent.java +++ b/libjava/classpath/javax/sound/sampled/LineEvent.java @@ -38,16 +38,24 @@ exception statement from your version. */ package javax.sound.sampled; +import java.io.IOException; +import java.io.NotSerializableException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.util.EventObject; -// FIXME: attempts to serialize this should fail - /** * This class holds information about a state change of a Line. + * @specnote This class is not really serializable, and attempts to + * serialize it will throw {@link NotSerializableException}. * @since 1.3 */ public class LineEvent extends EventObject { + // We define this even though this class can't be serialized, in + // order to placate the compiler. + private static final long serialVersionUID = -1274246333383880410L; + /** * This class represents the kinds of state changes that can occur * to a Line. The standard states are availabe as static instances. @@ -147,4 +155,16 @@ public class LineEvent extends EventObject return ("type=" + type + "; framePosition=" + framePosition + "line=" + line); } + + private void readObject(ObjectInputStream ois) + throws IOException + { + throw new NotSerializableException("LineEvent is not serializable"); + } + + private void writeObject(ObjectOutputStream oos) + throws IOException + { + throw new NotSerializableException("LineEvent is not serializable"); + } } diff --git a/libjava/classpath/javax/swing/AbstractAction.java b/libjava/classpath/javax/swing/AbstractAction.java index bd3167e..4a23345 100644 --- a/libjava/classpath/javax/swing/AbstractAction.java +++ b/libjava/classpath/javax/swing/AbstractAction.java @@ -1,5 +1,5 @@ /* AbstractAction.java -- - Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,6 +38,7 @@ exception statement from your version. */ package javax.swing; +import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.IOException; import java.io.ObjectInputStream; @@ -74,28 +75,30 @@ public abstract class AbstractAction private transient HashMap store = new HashMap(); /** - * Creates a new action with an empty string for the name. All other - * properties are initialised to null + * Creates a new action with no properties set. */ public AbstractAction() { - this(null); + // Nothing to do. } /** - * Creates a new action with the specified name. All other properties are - * initialised to null. + * Creates a new action with the specified name. The name is stored as a + * property with the key {@link Action#NAME}, and no other properties are + * initialised. * * @param name the name (null permitted). */ public AbstractAction(String name) { - this(name, null); + putValue(NAME, name); } /** - * Creates a new action with the specified name and icon. All other - * properties are initialised to null. + * Creates a new action with the specified name and icon. The name is stored + * as a property with the key {@link Action#NAME}, the icon is stored as a + * property with the key {@link Action#SMALL_ICON}, and no other properties + * are initialised. * * @param name the name (null permitted). * @param icon the icon (null permitted). @@ -133,11 +136,12 @@ public abstract class AbstractAction } /** - * clone + * Returns a clone of the action. * - * @return Object + * @return A clone of the action. * - * @exception CloneNotSupportedException TODO + * @exception CloneNotSupportedException if there is a problem cloning the + * action. */ protected Object clone() throws CloneNotSupportedException { @@ -153,6 +157,8 @@ public abstract class AbstractAction * * @return The value associated with the specified key, or * null if the key is not found. + * + * @see #putValue(String, Object) */ public Object getValue(String key) { @@ -162,11 +168,17 @@ public abstract class AbstractAction /** * Sets the value associated with the specified key and sends a * {@link java.beans.PropertyChangeEvent} to all registered listeners. - * The standard keys are: {@link #NAME}, {@link #SHORT_DESCRIPTION}, - * {@link #LONG_DESCRIPTION}, {@link #SMALL_ICON}, - * {@link #ACTION_COMMAND_KEY}, {@link #ACCELERATOR_KEY} and - * {@link #MNEMONIC_KEY}. Any existing value associated with the key will be - * overwritten. + * The standard keys are: + * + * Any existing value associated with the key will be overwritten. * * @param key the key (not null). * @param value the value (null permitted). @@ -174,7 +186,7 @@ public abstract class AbstractAction public void putValue(String key, Object value) { Object old = getValue(key); - if (old == null || !old.equals(value)) + if ((old == null && value != null) || (old != null && !old.equals(value))) { store.put(key, value); firePropertyChange(key, old, value); @@ -185,6 +197,8 @@ public abstract class AbstractAction * Returns the flag that indicates whether or not the action is enabled. * * @return The flag. + * + * @see #setEnabled(boolean) */ public boolean isEnabled() { @@ -194,9 +208,12 @@ public abstract class AbstractAction /** * Sets the flag that indicates whether or not the action is enabled and, if * the value of the flag changed from the previous setting, sends a - * {@link java.beans.PropertyChangeEvent} to all registered listeners. + * {@link java.beans.PropertyChangeEvent} to all registered listeners (using + * the property name 'enabled'). * * @param enabled the new flag value. + * + * @see #isEnabled() */ public void setEnabled(boolean enabled) { @@ -208,8 +225,11 @@ public abstract class AbstractAction } /** - * getKeys - * @returns Object[] + * Returns an array of the keys for the property values that have been + * defined via the {@link #putValue(String, Object)} method (or the class + * constructor). + * + * @return An array of keys. */ public Object[] getKeys() { @@ -217,12 +237,12 @@ public abstract class AbstractAction } /** - * This method fires a PropertyChangeEvent given the propertyName - * and the old and new values. + * Sends a {@link PropertyChangeEvent} for the named property to all + * registered listeners. * - * @param propertyName The property that changed. - * @param oldValue The old value of the property. - * @param newValue The new value of the property. + * @param propertyName the property name. + * @param oldValue the old value of the property. + * @param newValue the new value of the property. */ protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) @@ -231,22 +251,27 @@ public abstract class AbstractAction } /** - * This convenience method fires a PropertyChangeEvent given - * the propertyName and the old and new values. + * Sends a {@link PropertyChangeEvent} for the named property to all + * registered listeners. This private method is called by the + * {@link #setEnabled(boolean)} method. * - * @param propertyName The property that changed. - * @param oldValue The old value of the property. - * @param newValue The new value of the property. + * @param propertyName the property name. + * @param oldValue the old value of the property. + * @param newValue the new value of the property. */ - private void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) + private void firePropertyChange(String propertyName, boolean oldValue, + boolean newValue) { changeSupport.firePropertyChange(propertyName, oldValue, newValue); } /** - * addPropertyChangeListener + * Registers a listener to receive {@link PropertyChangeEvent} notifications + * from this action. * - * @param listener the listener to add + * @param listener the listener. + * + * @see #removePropertyChangeListener(PropertyChangeListener) */ public void addPropertyChangeListener(PropertyChangeListener listener) { @@ -254,9 +279,12 @@ public abstract class AbstractAction } /** - * removePropertyChangeListener + * Deregisters a listener so that it no longer receives + * {@link PropertyChangeEvent} notifications from this action. * - * @param listener the listener to remove + * @param listener the listener. + * + * @see #addPropertyChangeListener(PropertyChangeListener) */ public void removePropertyChangeListener(PropertyChangeListener listener) { @@ -266,7 +294,7 @@ public abstract class AbstractAction /** * Returns all registered listeners. * - * @return array of listeners. + * @return An array of listeners. * * @since 1.4 */ diff --git a/libjava/classpath/javax/swing/AbstractButton.java b/libjava/classpath/javax/swing/AbstractButton.java index 376b3a0..3d28908 100644 --- a/libjava/classpath/javax/swing/AbstractButton.java +++ b/libjava/classpath/javax/swing/AbstractButton.java @@ -159,6 +159,14 @@ public abstract class AbstractButton extends JComponent private static final long serialVersionUID = 1471056094226600578L; /** + * The spec has no public/protected constructor for this class, so do we. + */ + ButtonChangeListener() + { + // Nothing to do here. + } + + /** * Notified when the target of the listener changes its state. * * @param ev the ChangeEvent describing the change diff --git a/libjava/classpath/javax/swing/AbstractCellEditor.java b/libjava/classpath/javax/swing/AbstractCellEditor.java index 4ed1580..df0d3db 100644 --- a/libjava/classpath/javax/swing/AbstractCellEditor.java +++ b/libjava/classpath/javax/swing/AbstractCellEditor.java @@ -1,5 +1,5 @@ /* AbstractCellEditor.java -- - Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -69,10 +69,11 @@ public abstract class AbstractCellEditor /** * Creates a new instance of AbstractCellEditor. */ - public AbstractCellEditor() { + public AbstractCellEditor() + { listenerList = new EventListenerList(); changeEvent = new ChangeEvent(this); - } // AbstractCellEditor() + } /** * Returns true if the cell is editable using @@ -84,9 +85,10 @@ public abstract class AbstractCellEditor * @return true if the cell is editable using * event, false if it's not */ - public boolean isCellEditable(EventObject event) { + public boolean isCellEditable(EventObject event) + { return true; - } // isCellEditable() + } /** * Returns true if the editing cell should be selected, @@ -99,29 +101,32 @@ public abstract class AbstractCellEditor * @return true if the editing cell should be selected, * false otherwise */ - public boolean shouldSelectCell(EventObject event) { + public boolean shouldSelectCell(EventObject event) + { return true; - } // shouldSelectCell() + } /** * Stop editing the cell and accept any partial value that has been entered * into the cell. * - * @returns true if editing has been stopped successfully, + * @return true if editing has been stopped successfully, * falseotherwise */ - public boolean stopCellEditing() { + public boolean stopCellEditing() + { fireEditingStopped(); return true; - } // stopCellEditing() + } /** * Stop editing the cell and do not accept any partial value that has * been entered into the cell. */ - public void cancelCellEditing() { + public void cancelCellEditing() + { fireEditingCanceled(); - } // cancelCellEditing() + } /** * Adds a CellEditorListener to the list of CellEditorListeners of this diff --git a/libjava/classpath/javax/swing/AbstractListModel.java b/libjava/classpath/javax/swing/AbstractListModel.java index 8973e52..4b89689 100644 --- a/libjava/classpath/javax/swing/AbstractListModel.java +++ b/libjava/classpath/javax/swing/AbstractListModel.java @@ -1,5 +1,5 @@ /* AbstractListModel.java -- - Copyright (C) 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -58,6 +58,9 @@ public abstract class AbstractListModel implements ListModel, Serializable /** List of ListDataListeners called for each change to the list. */ protected EventListenerList listenerList; + /** + * Creates a new model instance - initialises the event listener list. + */ public AbstractListModel() { listenerList = new EventListenerList(); @@ -88,7 +91,7 @@ public abstract class AbstractListModel implements ListModel, Serializable /** * Call {@link ListDataListener#contentsChanged} on each element of the * {@link #listenerList} which is a {@link ListDataListener}. The event - * fired has type {@ListDataEvent.CONTENTS_CHANGED} and represents a + * fired has type {@link ListDataEvent#CONTENTS_CHANGED} and represents a * change to the data elements in the range [startIndex, endIndex] * inclusive. * @@ -110,7 +113,7 @@ public abstract class AbstractListModel implements ListModel, Serializable /** * Call {@link ListDataListener#intervalAdded} on each element of the * {@link #listenerList} which is a {@link ListDataListener}. The event - * fired has type {@ListDataEvent.INTERVAL_ADDED} and represents an + * fired has type {@link ListDataEvent#INTERVAL_ADDED} and represents an * addition of the data elements in the range [startIndex, endIndex] * inclusive. * @@ -132,7 +135,7 @@ public abstract class AbstractListModel implements ListModel, Serializable /** * Call {@link ListDataListener#intervalRemoved} on each element of the * {@link #listenerList} which is a {@link ListDataListener}. The event - * fired has type {@ListDataEvent.INTERVAL_REMOVED} and represents a + * fired has type {@link ListDataEvent#INTERVAL_REMOVED} and represents a * removal of the data elements in the range [startIndex, endIndex] * inclusive. * diff --git a/libjava/classpath/javax/swing/CellEditor.java b/libjava/classpath/javax/swing/CellEditor.java index 3d229b2..9eb083a 100644 --- a/libjava/classpath/javax/swing/CellEditor.java +++ b/libjava/classpath/javax/swing/CellEditor.java @@ -1,5 +1,5 @@ /* CellEditor.java -- - Copyright (C) 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,6 +41,7 @@ package javax.swing; import java.util.EventObject; import javax.swing.event.CellEditorListener; +import javax.swing.event.ChangeEvent; /** * Provides edit capabilities for components that display cells like @@ -51,46 +52,57 @@ import javax.swing.event.CellEditorListener; public interface CellEditor { /** - * getCellEditorValue - * @returns Object + * Returns the current value for the CellEditor. + * + * @return The value. */ Object getCellEditorValue(); /** - * isCellEditable - * @param event TODO - * @returns boolean + * Returns true if the specified event makes the editor + * editable, and false otherwise. + * + * @param event the event. + * + * @return A boolean. */ boolean isCellEditable(EventObject event); /** * shouldSelectCell * @param event TODO - * @returns boolean + * @return boolean */ boolean shouldSelectCell(EventObject event); /** - * stopCellEditing - * @returns boolean + * Signals to the CellEditor that it should stop editing, + * accepting the current cell value, and returns true if the + * editor actually stops editing, and false otherwise. + * + * @return A boolean. */ boolean stopCellEditing(); /** - * cancelCellEditing + * Signals to the CellEditor that it should cancel editing. */ void cancelCellEditing(); /** - * addCellEditorListener - * @param listener TODO + * Registers a listener to receive {@link ChangeEvent} notifications from the + * CellEditor. + * + * @param listener the listener. */ void addCellEditorListener(CellEditorListener listener); /** - * removeCellEditorListener - * @param listener TODO + * Deregisters a listener so that it no longer receives {@link ChangeEvent} + * notifications from the CellEditor. + * + * @param listener the listener. */ void removeCellEditorListener(CellEditorListener listener); -} // CellEditor +} diff --git a/libjava/classpath/javax/swing/CellRendererPane.java b/libjava/classpath/javax/swing/CellRendererPane.java index c59afd3..b3d6f6a 100644 --- a/libjava/classpath/javax/swing/CellRendererPane.java +++ b/libjava/classpath/javax/swing/CellRendererPane.java @@ -1,5 +1,5 @@ /* CellRendererPane.java -- - Copyright (C) 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -75,7 +75,7 @@ public class CellRendererPane extends Container implements Accessible /** * getAccessibleRole - * @returns AccessibleRole + * @return AccessibleRole */ public AccessibleRole getAccessibleRole() { @@ -169,24 +169,32 @@ public class CellRendererPane extends Container implements Accessible addImpl(c, null, 0); Rectangle oldClip = graphics.getClipBounds(); - // translate to (x,y) - graphics.translate(x, y); - graphics.clipRect(0, 0, w, h); - // set bounds of c - c.setBounds(0, 0, w, h); - - // validate if necessary - if (shouldValidate) + boolean translated = false; + try { - c.validate(); + // translate to (x,y) + graphics.translate(x, y); + translated = true; + graphics.clipRect(0, 0, w, h); + // set bounds of c + c.setBounds(0, 0, w, h); + + // validate if necessary + if (shouldValidate) + { + c.validate(); + } + + // paint component + c.paint(graphics); + } + finally + { + // untranslate g + if (translated) + graphics.translate(-x, -y); + graphics.setClip(oldClip); } - - // paint component - c.paint(graphics); - - // untranslate g - graphics.translate(-x, -y); - graphics.setClip(oldClip); } /** diff --git a/libjava/classpath/javax/swing/ComboBoxModel.java b/libjava/classpath/javax/swing/ComboBoxModel.java index 6968db4..6105275 100644 --- a/libjava/classpath/javax/swing/ComboBoxModel.java +++ b/libjava/classpath/javax/swing/ComboBoxModel.java @@ -1,5 +1,5 @@ /* ComboBoxModel.java -- - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -37,31 +37,33 @@ exception statement from your version. */ package javax.swing; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; /** - * The data model for {@link JComboBox}. This model keeps - * track of elements contained in the JComboBox as well as the current - * combo box selection. Whenever selection in the JComboBox changes, the - * ComboBoxModel should fire ListDataEvents to ComboBox's ListDataListeners. + * The data model for a {@link JComboBox}. This model keeps track of elements + * contained in the JComboBox as well as the current + * combo box selection. Whenever the selection in the JComboBox + * changes, the ComboBoxModel should fire a {@link ListDataEvent} + * to the model's {@link ListDataListener}s. * * @author Andrew Selkirk */ public interface ComboBoxModel extends ListModel { /** - * This method sets the selected item in the combo box. Class - * implementing this interface should fire ListDataEvents to - * all registered ListDataListeners to indicated that the - * selection has changed. + * Sets the selected item in the combo box. Classes implementing this + * interface should fire a {@link ListDataEvent} to all registered + * {@link ListDataListener}s to indicate that the selection has changed. * - * @param item item in the combo box that should be selected + * @param item the selected item (null permitted). */ void setSelectedItem(Object item); /** - * The method returns currently selected item in the combo box + * Returns the currently selected item in the combo box. * - * @returns item that is currently selected in the combo box. + * @return The selected item (possibly null). */ Object getSelectedItem(); -} // ComboBoxModel +} diff --git a/libjava/classpath/javax/swing/DefaultCellEditor.java b/libjava/classpath/javax/swing/DefaultCellEditor.java index 39e4855..7f1c395 100644 --- a/libjava/classpath/javax/swing/DefaultCellEditor.java +++ b/libjava/classpath/javax/swing/DefaultCellEditor.java @@ -1,5 +1,5 @@ /* DefaultCellEditor.java -- - Copyright (C) 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -59,8 +59,7 @@ import javax.swing.tree.TreeCellEditor; * some standard object types. * * @author Andrew Selkirk - * - * @status mostly unimplemented + * @author Audrius Meskauskas */ public class DefaultCellEditor extends AbstractCellEditor @@ -69,17 +68,26 @@ public class DefaultCellEditor private static final long serialVersionUID = 3564035141373880027L; /** - * Delegates a couple of method calls (such as {@link #isCellEditable} - * to the component it contains and listens for events that indicate - * that editing has stopped. + * This changeable module access the editor component in the component + * specific way. For instance, to set the value for JTextField, we need to + * call setText(String), and for JCheckBox we need to call + * setSelected(boolean). Each default editor has the component specific + * derivative of this class. These derivatives are private inner classes of + * the DefaultCellEditor. + * + * The editor delegate is also set for the editor component as the action + * listener. It listens for the events that indicate that editing has stopped. */ protected class EditorDelegate implements ActionListener, ItemListener, Serializable { + /** + * Use the serial version UID for interoperability. + */ private static final long serialVersionUID = -1420007406015481933L; /** - * value + * The object value (updated when getting and setting the value). */ protected Object value; @@ -90,35 +98,38 @@ public class DefaultCellEditor { // Nothing to do here. } - + /** - * setValue + * Set the value for the editor component. This method is normally + * overridden to set the value in the way, specific for the text + * component, check box or combo box. * - * @param value TODO + * @param aValue the value to set (String, Boolean or Number). */ - public void setValue(Object value) + public void setValue(Object aValue) { - // TODO: should be setting the value in the editorComp - this.value = value; + value = aValue; } - /** - * getCellEditorValue - * - * @returns Object + /** + * Get the value for the editor component. This method is normally + * overridden to obtain the value in the way, specific for the text + * component, check box or combo box. + * + * @return value the value of the component (String, Boolean or Number). */ public Object getCellEditorValue() { - // TODO: should be getting the updated value from the editorComp return value; - } // getCellEditorValue() + } /** - * isCellEditable + * The default method returns true for the {@link MouseEvent} and false + * for any other events. * - * @param event TODO + * @param event the event to check * - * @returns boolean + * @return true if the passed event is the mouse event and false otherwise. */ public boolean isCellEditable(EventObject event) { @@ -129,22 +140,27 @@ public class DefaultCellEditor } // isCellEditable() /** - * shouldSelectCell + * Returns true to indicate that the editing cell can be selected. + * + * The default method returns true without action but may be overridden + * in derived classes for more specific behavior. * - * @param event TODO + * @param event unused in default method * - * @returns boolean + * @return true always */ public boolean shouldSelectCell(EventObject event) { // return true to indicate that the editing cell may be selected return true; - } // shouldSelectCell() + } /** - * stopCellEditing + * Finish the cell editing session. This method notifies the registered + * cell editor listeners (including the table) that the editing has been + * stopped. * - * @returns boolean + * @return boolean */ public boolean stopCellEditing() { @@ -153,7 +169,11 @@ public class DefaultCellEditor } // stopCellEditing() /** - * cancelCellEditing + * Cancel the cell editing session. This method notifies the registered + * cell editor listeners (including the table) that the editing has been + * canceled. + * + * @returns boolean */ public void cancelCellEditing() { @@ -161,11 +181,13 @@ public class DefaultCellEditor } // cancelCellEditing() /** - * startCellEditing + * Start editing session and returns true to indicate the editing has begun. + * The default method returns true without action but may be overridden + * in derived classes for more specific behavior. * - * @param event TODO - * - * @returns boolean + * @param event the event. + * + * @return true, always */ public boolean startCellEditing(EventObject event) { @@ -174,9 +196,11 @@ public class DefaultCellEditor } // startCellEditing() /** - * actionPerformed + * This event is fired by the editor component (for instance, by pressing + * ENTER in the {@link JTextField}. The default method delegates call to + * the {@link #stopCellEditing}, finishing the editing session. * - * @param event TODO + * @param event unused in default method */ public void actionPerformed(ActionEvent event) { @@ -184,15 +208,20 @@ public class DefaultCellEditor } // actionPerformed() /** - * itemStateChanged + * This event is fired by the editor component.The default method delegates + * call to the {@link #stopCellEditing}, finishing the editing session. * - * @param event TODO + * @param event unused in default method */ public void itemStateChanged(ItemEvent event) { stopCellEditing(); } // itemStateChanged() + /** + * Notify the registered listeners (including the table) that the editing + * has been completed. + */ void fireEditingStopped() { CellEditorListener[] listeners = getCellEditorListeners(); @@ -201,6 +230,10 @@ public class DefaultCellEditor } + /** + * Notify the registered listeners (including the table) that the editing + * has been canceled. + */ void fireEditingCanceled() { CellEditorListener[] listeners = getCellEditorListeners(); @@ -208,59 +241,185 @@ public class DefaultCellEditor listeners[index].editingCanceled(changeEvent); } } // EditorDelegate + + /** + * Provides getter and setter methods to work with the text component. + * + * @author Audrius Meskauskas (audriusa@Bioinformatics.org) + */ + private class JTextFieldDelegate extends EditorDelegate + { + /** + * Use the serial version UID for interoperability. + */ + private static final long serialVersionUID = 1; + + /** + * Set the value for the editor component. + * + * @param aValue the value to set (toString() will be called). + */ + public void setValue(Object aValue) + { + value = aValue; + JTextField f = (JTextField) editorComponent; + if (value == null) + f.setText(""); + else + f.setText(value.toString()); + } + + /** + * Get the value for the editor component. + * + * @return value the value of the component (String) + */ + public Object getCellEditorValue() + { + JTextField f = (JTextField) editorComponent; + return value = f.getText(); + } + } + + /** + * Provides getter and setter methods to work with the combo box. + * + * @author Audrius Meskauskas (audriusa@Bioinformatics.org) + */ + private class JComboBoxDelegate extends EditorDelegate + { + /** + * Use the serial version UID for interoperability. + */ + private static final long serialVersionUID = 1; + + /** + * Set the value for the editor component. + * + * @param aValue the value to set. + */ + public void setValue(Object aValue) + { + value = aValue; + JComboBox c = (JComboBox) editorComponent; + if (value != null) + c.setSelectedItem(value); + } - /** - * editorComponent + /** + * Get the value for the editor component. + * + * @return value the value of the component (as String) + */ + public Object getCellEditorValue() + { + JComboBox c = (JComboBox) editorComponent; + return value = c.getSelectedItem(); + } + } + + /** + * Provides getter and setter methods to work with the check box. + * + * @author Audrius Meskauskas (audriusa@Bioinformatics.org) + */ + private class JCheckBoxDelegate extends EditorDelegate + { + /** + * Use the serial version UID for interoperability. + */ + private static final long serialVersionUID = 1; + + /** + * Set the value for the editor component. + * + * @param value the value to set (must be Boolean). + */ + public void setValue(Object value) + { + JCheckBox c = (JCheckBox) editorComponent; + + if (value == null) + c.setSelected(false); + else + c.setSelected( ((Boolean) value).booleanValue()); + } + + /** + * Get the value for the editor component. + * + * @return value the value of the component (must be CharSequence) + */ + public Object getCellEditorValue() + { + JCheckBox c = (JCheckBox) editorComponent; + value = c.isSelected() ? Boolean.TRUE : Boolean.FALSE; + return value; + } + } + + /** + * The Swing JComponent, performing the editing session. */ protected JComponent editorComponent; /** - * delegate + * The editor delegate, responsible for listening the {@link #editorComponent} + * events and getting/setting its value. */ protected EditorDelegate delegate; /** - * clickCountToStart + * The number of the mouse clicks, required to start the editing session. */ protected int clickCountToStart; /** - * Constructor DefaultCellEditor + * Create the DefaultCellEditor that uses the text field as its editor + * component (appropriate for the text content) * - * @param textfield TODO + * @param textfield the text field as will be used as the editor component */ public DefaultCellEditor(JTextField textfield) { editorComponent = textfield; - clickCountToStart = 3; + clickCountToStart = 2; + delegate = new JTextFieldDelegate(); + textfield.addActionListener(delegate); } // DefaultCellEditor() /** - * Constructor DefaultCellEditor + * Constructor DefaultCellEditor that uses the checkbox (appropriate + * for boolean values) * - * @param checkbox TODO + * @param checkbox the checkbox that will be used with this editor. */ public DefaultCellEditor(JCheckBox checkbox) { editorComponent = checkbox; clickCountToStart = 1; + delegate = new JCheckBoxDelegate(); + checkbox.addActionListener(delegate); } // DefaultCellEditor() /** - * Constructor DefaultCellEditor + * Constructor DefaultCellEditor that uses the combo box. * - * @param combobox TODO + * @param combobox the combo box that will be used with this editor. */ public DefaultCellEditor(JComboBox combobox) { editorComponent = combobox; clickCountToStart = 1; + delegate = new JComboBoxDelegate(); + combobox.addActionListener(delegate); } // DefaultCellEditor() /** - * getComponent + * Get the component that performs the editing sessions. It is the same + * component that was passed in constructor. * - * @returns Component + * @return the component, performing the editing sessions. */ public Component getComponent() { @@ -268,9 +427,9 @@ public class DefaultCellEditor } // getComponent() /** - * getClickCountToStart + * Get the number of mouse clicks, required to start the editing session. * - * @returns int + * @return int the number of mouse clicks, required to start the session */ public int getClickCountToStart() { @@ -278,9 +437,9 @@ public class DefaultCellEditor } // getClickCountToStart() /** - * setClickCountToStart + * Set the number of mouse clicks, required to start the editing session. * - * @param count TODO + * @param count the number of clicks, required to start the session */ public void setClickCountToStart(int count) { @@ -288,9 +447,10 @@ public class DefaultCellEditor } // setClickCountToStart() /** - * getCellEditorValue + * Get the value, currently being displayed by the editor component. The + * call is forwarded to the {@link #delegate}. * - * @returns Object + * @return Object the value (class depends on the editor component) */ public Object getCellEditorValue() { @@ -298,11 +458,11 @@ public class DefaultCellEditor } // getCellEditorValue() /** - * isCellEditable + * Forwards call to the {@link #delegate}. * - * @param event TODO + * @param event forwarded to the delegate. * - * @returns boolean + * @return boolean returned by delegate */ public boolean isCellEditable(EventObject event) { @@ -310,11 +470,11 @@ public class DefaultCellEditor } // isCellEditable() /** - * shouldSelectCell + * Forwards call to the {@link #delegate}. * - * @param event TODO + * @param event forwarded to the delegate. * - * @returns boolean + * @return boolean returned by delegate */ public boolean shouldSelectCell(EventObject event) { @@ -322,9 +482,9 @@ public class DefaultCellEditor } // shouldSelectCell() /** - * stopCellEditing + * Forwards call to the {@link #delegate}. * - * @returns boolean + * @return boolean returned by delegate */ public boolean stopCellEditing() { @@ -332,7 +492,7 @@ public class DefaultCellEditor } // stopCellEditing() /** - * cancelCellEditing + * Forwards call to the {@link #delegate}. */ public void cancelCellEditing() { @@ -356,45 +516,30 @@ public class DefaultCellEditor * @param leaf - true if the node is a leaf node * @param row - the row index of the node being edited * - * @returns Component the component for editing + * @return Component the component for editing */ public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row) { - if (editorComponent instanceof JTextField) - { - ((JTextField)editorComponent).setText(value.toString()); - delegate = new EditorDelegate(); - ((JTextField)editorComponent).addActionListener(delegate); - } - else if (editorComponent instanceof JCheckBox) - { - ((JCheckBox)editorComponent).setText(value.toString()); - delegate = new EditorDelegate(); - ((JCheckBox)editorComponent).addActionListener(delegate); - } - else if (editorComponent instanceof JComboBox) - { - ((JComboBox)editorComponent).setSelectedItem(value.toString()); - delegate = new EditorDelegate(); - ((JComboBox)editorComponent).addActionListener(delegate); - } - + delegate.setValue(value); return editorComponent; } // getTreeCellEditorComponent() /** - * getTableCellEditorComponent + * Get the cell editor component that will perform the editing session. If + * returned once, the same component is also returned on the repetetive calls + * again (reused). * - * @param table TODO - * @param value TODO - * @param isSelected TODO - * @param row TODO - * @param column TODO - * - * @returns Component + * @param table the table where the editing is performed + * @param value the current value of the table. It is set as the initial + * component value. + * @param isSelected if true, the cell is currently selected + * @param row the row of the cell being edited + * @param column the column of the cell being edited + * + * @return Component the component that will perform the editing session */ public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, @@ -402,24 +547,9 @@ public class DefaultCellEditor { // NOTE: as specified by Sun, we don't call new() everytime, we return // editorComponent on each call to getTableCellEditorComponent or - // getTreeCellEditorComponent. However, currently JTextFields have a - // problem with getting rid of old text, so without calling new() there - // are some strange results. If you edit more than one cell in the table - // text from previously edited cells may unexpectedly show up in the - // cell you are currently editing. This will be fixed automatically - // when JTextField is fixed. - if (editorComponent instanceof JTextField) - { - ((JTextField)editorComponent).setText(value.toString()); - delegate = new EditorDelegate(); - ((JTextField)editorComponent).addActionListener(delegate); - } - else - { - // TODO - } + // getTreeCellEditorComponent. + delegate.setValue(value); return editorComponent; } // getTableCellEditorComponent() - } diff --git a/libjava/classpath/javax/swing/DefaultListCellRenderer.java b/libjava/classpath/javax/swing/DefaultListCellRenderer.java index 9a8e070..598627f 100644 --- a/libjava/classpath/javax/swing/DefaultListCellRenderer.java +++ b/libjava/classpath/javax/swing/DefaultListCellRenderer.java @@ -93,7 +93,7 @@ public class DefaultListCellRenderer extends JLabel int index, boolean isSelected, boolean cellHasFocus) { - String s = value.toString(); + String s = value != null ? value.toString() : ""; setText(s); setOpaque(true); setHorizontalAlignment(LEFT); diff --git a/libjava/classpath/javax/swing/DefaultListSelectionModel.java b/libjava/classpath/javax/swing/DefaultListSelectionModel.java index ce1dfdd..7ec4e61 100644 --- a/libjava/classpath/javax/swing/DefaultListSelectionModel.java +++ b/libjava/classpath/javax/swing/DefaultListSelectionModel.java @@ -447,6 +447,9 @@ public class DefaultListSelectionModel implements Cloneable, */ public void addSelectionInterval(int index0, int index1) { + if (index0 == -1 || index1 == -1) + return; + int lo = Math.min(index0, index1); int hi = Math.max(index0, index1); oldSel = sel.clone(); @@ -508,6 +511,9 @@ public class DefaultListSelectionModel implements Cloneable, public void removeSelectionInterval(int index0, int index1) { + if (index0 == -1 || index1 == -1) + return; + oldSel = sel.clone(); int lo = Math.min(index0, index1); int hi = Math.max(index0, index1); @@ -551,6 +557,9 @@ public class DefaultListSelectionModel implements Cloneable, */ public void setSelectionInterval(int index0, int index1) { + if (index0 == -1 || index1 == -1) + return; + oldSel = sel.clone(); sel.clear(); if (selectionMode == SINGLE_SELECTION) diff --git a/libjava/classpath/javax/swing/ImageIcon.java b/libjava/classpath/javax/swing/ImageIcon.java index b6ed949..9e62658 100644 --- a/libjava/classpath/javax/swing/ImageIcon.java +++ b/libjava/classpath/javax/swing/ImageIcon.java @@ -205,13 +205,13 @@ public class ImageIcon private static final long serialVersionUID = 532615968316031794L; /** A dummy Component that is used in the MediaTracker. */ - protected static Component component = new Component() + protected static final Component component = new Component() { // No need to implement this. }; /** The MediaTracker used to monitor the loading of images. */ - protected static MediaTracker tracker = new MediaTracker(component); + protected static final MediaTracker tracker = new MediaTracker(component); /** The ID that is used in the tracker. */ private static int id; diff --git a/libjava/classpath/javax/swing/JApplet.java b/libjava/classpath/javax/swing/JApplet.java index e90c451..68eb983 100644 --- a/libjava/classpath/javax/swing/JApplet.java +++ b/libjava/classpath/javax/swing/JApplet.java @@ -66,7 +66,7 @@ public class JApplet extends Applet /** * Creates a new instance of AccessibleJApplet. */ - public AccessibleJApplet() + protected AccessibleJApplet() { super(); // Nothing to do here. diff --git a/libjava/classpath/javax/swing/JCheckBox.java b/libjava/classpath/javax/swing/JCheckBox.java index 74fda8f..26f9f6c 100644 --- a/libjava/classpath/javax/swing/JCheckBox.java +++ b/libjava/classpath/javax/swing/JCheckBox.java @@ -67,7 +67,7 @@ public class JCheckBox extends JToggleButton implements Accessible /** * Creates a new instance of AccessibleJCheckBox. */ - public AccessibleJCheckBox() + protected AccessibleJCheckBox() { // Nothing to do here. } diff --git a/libjava/classpath/javax/swing/JComponent.java b/libjava/classpath/javax/swing/JComponent.java index 747eba5..ddd7086 100644 --- a/libjava/classpath/javax/swing/JComponent.java +++ b/libjava/classpath/javax/swing/JComponent.java @@ -1,5 +1,5 @@ /* JComponent.java -- Every component in swing inherits from this class. - Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -64,10 +64,10 @@ import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; -import java.awt.geom.Rectangle2D; import java.awt.peer.LightweightPeer; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; import java.beans.PropertyVetoException; import java.beans.VetoableChangeListener; import java.io.Serializable; @@ -88,7 +88,6 @@ import javax.swing.border.TitledBorder; import javax.swing.event.AncestorEvent; import javax.swing.event.AncestorListener; import javax.swing.event.EventListenerList; -import javax.swing.event.SwingPropertyChangeSupport; import javax.swing.plaf.ComponentUI; /** @@ -165,11 +164,11 @@ public abstract class JComponent extends Container implements Serializable /** * Manages the property change listeners; */ - private SwingPropertyChangeSupport changeSupport; + private PropertyChangeSupport changeSupport; protected AccessibleJComponent() { - changeSupport = new SwingPropertyChangeSupport(this); + changeSupport = new PropertyChangeSupport(this); } /** @@ -528,14 +527,6 @@ public abstract class JComponent extends Container implements Serializable protected EventListenerList listenerList = new EventListenerList(); /** - * Support for {@link PropertyChangeEvent} events. This is constructed - * lazily when the component gets its first {@link - * PropertyChangeListener} subscription; until then it's an empty slot. - */ - private SwingPropertyChangeSupport changeSupport; - - - /** * Storage for "client properties", which are key/value pairs associated * with this component by a "client", such as a user application or a * layout manager. This is lazily constructed when the component gets its @@ -697,36 +688,6 @@ public abstract class JComponent extends Container implements Serializable } /** - * Unregister a PropertyChangeListener. - * - * @param listener The listener to register - * - * @see #addPropertyChangeListener(PropertyChangeListener) - * @see #changeSupport - */ - public void removePropertyChangeListener(PropertyChangeListener listener) - { - if (changeSupport != null) - changeSupport.removePropertyChangeListener(listener); - } - - /** - * Unregister a PropertyChangeListener. - * - * @param propertyName The property name to unregister the listener from - * @param listener The listener to unregister - * - * @see #addPropertyChangeListener(String, PropertyChangeListener) - * @see #changeSupport - */ - public void removePropertyChangeListener(String propertyName, - PropertyChangeListener listener) - { - if (changeSupport != null) - changeSupport.removePropertyChangeListener(propertyName, listener); - } - - /** * Unregister a VetoableChangeChangeListener. * * @param listener The listener to unregister @@ -751,24 +712,6 @@ public abstract class JComponent extends Container implements Serializable } /** - * Register a PropertyChangeListener. This listener will - * receive any PropertyChangeEvent, regardless of property name. To - * listen to a specific property name, use {@link - * #addPropertyChangeListener(String,PropertyChangeListener)} instead. - * - * @param listener The listener to register - * - * @see #removePropertyChangeListener(PropertyChangeListener) - * @see #changeSupport - */ - public void addPropertyChangeListener(PropertyChangeListener listener) - { - if (changeSupport == null) - changeSupport = new SwingPropertyChangeSupport(this); - changeSupport.addPropertyChangeListener(listener); - } - - /** * Register a PropertyChangeListener for a specific, named * property. To listen to all property changes, regardless of name, use * {@link #addPropertyChangeListener(PropertyChangeListener)} instead. @@ -819,7 +762,10 @@ public abstract class JComponent extends Container implements Serializable */ public EventListener[] getListeners(Class listenerType) { - return listenerList.getListeners(listenerType); + if (listenerType == PropertyChangeListener.class) + return getPropertyChangeListeners(); + else + return listenerList.getListeners(listenerType); } /** @@ -845,134 +791,48 @@ public abstract class JComponent extends Container implements Serializable } /** - * Return all PropertyChangeListener objects registered to listen - * for a particular property. - * - * @param property The property to return the listeners of - * - * @return The set of PropertyChangeListener objects in - * {@link #changeSupport} registered to listen on the specified property - */ - public PropertyChangeListener[] getPropertyChangeListeners(String property) - { - return changeSupport == null ? new PropertyChangeListener[0] - : changeSupport.getPropertyChangeListeners(property); - } - - /** * A variant of {@link #firePropertyChange(String,Object,Object)} * for properties with boolean values. + * + * @specnote It seems that in JDK1.5 all property related methods have been + * moved to java.awt.Component, except this and 2 others. We call + * super here. I guess this will also be removed in one of the next + * releases. */ public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) { - if (changeSupport != null) - changeSupport.firePropertyChange(propertyName, Boolean.valueOf(oldValue), - Boolean.valueOf(newValue)); - } - - /** - * A variant of {@link #firePropertyChange(String,Object,Object)} - * for properties with byte values. - */ - public void firePropertyChange(String propertyName, byte oldValue, - byte newValue) - { - if (changeSupport != null) - changeSupport.firePropertyChange(propertyName, new Byte(oldValue), - new Byte(newValue)); + super.firePropertyChange(propertyName, oldValue, newValue); } /** * A variant of {@link #firePropertyChange(String,Object,Object)} * for properties with char values. + * + * @specnote It seems that in JDK1.5 all property related methods have been + * moved to java.awt.Component, except this and 2 others. We call + * super here. I guess this will also be removed in one of the next + * releases. */ public void firePropertyChange(String propertyName, char oldValue, char newValue) { - if (changeSupport != null) - changeSupport.firePropertyChange(propertyName, new Character(oldValue), - new Character(newValue)); - } - - /** - * A variant of {@link #firePropertyChange(String,Object,Object)} - * for properties with double values. - */ - public void firePropertyChange(String propertyName, double oldValue, - double newValue) - { - if (changeSupport != null) - changeSupport.firePropertyChange(propertyName, new Double(oldValue), - new Double(newValue)); - } - - /** - * A variant of {@link #firePropertyChange(String,Object,Object)} - * for properties with float values. - */ - public void firePropertyChange(String propertyName, float oldValue, - float newValue) - { - if (changeSupport != null) - changeSupport.firePropertyChange(propertyName, new Float(oldValue), - new Float(newValue)); + super.firePropertyChange(propertyName, oldValue, newValue); } /** * A variant of {@link #firePropertyChange(String,Object,Object)} * for properties with int values. + * + * @specnote It seems that in JDK1.5 all property related methods have been + * moved to java.awt.Component, except this and 2 others. We call + * super here. I guess this will also be removed in one of the next + * releases. */ public void firePropertyChange(String propertyName, int oldValue, int newValue) { - if (changeSupport != null) - changeSupport.firePropertyChange(propertyName, new Integer(oldValue), - new Integer(newValue)); - } - - /** - * A variant of {@link #firePropertyChange(String,Object,Object)} - * for properties with long values. - */ - public void firePropertyChange(String propertyName, long oldValue, - long newValue) - { - if (changeSupport != null) - changeSupport.firePropertyChange(propertyName, new Long(oldValue), - new Long(newValue)); - } - - /** - * Call {@link PropertyChangeListener#propertyChange} on all listeners - * registered to listen to a given property. Any method which changes - * the specified property of this component should call this method. - * - * @param propertyName The property which changed - * @param oldValue The old value of the property - * @param newValue The new value of the property - * - * @see #changeSupport - * @see #addPropertyChangeListener(PropertyChangeListener) - * @see #removePropertyChangeListener(PropertyChangeListener) - */ - protected void firePropertyChange(String propertyName, Object oldValue, - Object newValue) - { - if (changeSupport != null) - changeSupport.firePropertyChange(propertyName, oldValue, newValue); - } - - /** - * A variant of {@link #firePropertyChange(String,Object,Object)} - * for properties with short values. - */ - public void firePropertyChange(String propertyName, short oldValue, - short newValue) - { - if (changeSupport != null) - changeSupport.firePropertyChange(propertyName, new Short(oldValue), - new Short(newValue)); + super.firePropertyChange(propertyName, oldValue, newValue); } /** @@ -1518,9 +1378,8 @@ public abstract class JComponent extends Container implements Serializable { ((JComponent) c).computeVisibleRect(rect); rect.translate(-getX(), -getY()); - Rectangle2D.intersect(rect, - new Rectangle(0, 0, getWidth(), getHeight()), - rect); + rect = SwingUtilities.computeIntersection(0, 0, getWidth(), + getHeight(), rect); } else rect.setRect(0, 0, getWidth(), getHeight()); @@ -1530,7 +1389,7 @@ public abstract class JComponent extends Container implements Serializable * Return the component's visible rectangle in a new {@link Rectangle}, * rather than via a return slot. * - * @return The component's visible rectangle + * @return the component's visible rectangle * * @see #computeVisibleRect(Rectangle) */ @@ -1691,7 +1550,10 @@ public abstract class JComponent extends Container implements Serializable // screen. if (!isPaintingDoubleBuffered && isDoubleBuffered() && rm.isDoubleBufferingEnabled()) - paintDoubleBuffered(g); + { + Rectangle clip = g.getClipBounds(); + paintDoubleBuffered(clip); + } else { if (g.getClip() == null) @@ -1755,11 +1617,10 @@ public abstract class JComponent extends Container implements Serializable // optimizedDrawingEnabled (== it tiles its children). if (! isOptimizedDrawingEnabled()) { - Rectangle clip = g.getClipBounds(); for (int i = 0; i < children.length; i++) { Rectangle childBounds = children[i].getBounds(); - if (children[i].isOpaque() + if (children[i].isOpaque() && children[i].isVisible() && SwingUtilities.isRectangleContainingRectangle(childBounds, g.getClipBounds())) { @@ -1892,33 +1753,29 @@ public abstract class JComponent extends Container implements Serializable void paintImmediately2(Rectangle r) { RepaintManager rm = RepaintManager.currentManager(this); - Graphics g = getGraphics(); - g.setClip(r.x, r.y, r.width, r.height); if (rm.isDoubleBufferingEnabled() && isDoubleBuffered()) - paintDoubleBuffered(g); + paintDoubleBuffered(r); else - paintSimple(g); - g.dispose(); + paintSimple(r); } /** * Performs double buffered repainting. - * - * @param g the graphics context to paint to */ - void paintDoubleBuffered(Graphics g) + private void paintDoubleBuffered(Rectangle r) { - - Rectangle r = g.getClipBounds(); - if (r == null) - r = new Rectangle(0, 0, getWidth(), getHeight()); RepaintManager rm = RepaintManager.currentManager(this); // Paint on the offscreen buffer. - Image buffer = rm.getOffscreenBuffer(this, getWidth(), getHeight()); + Component root = SwingUtilities.getRoot(this); + Image buffer = rm.getOffscreenBuffer(this, root.getWidth(), + root.getHeight()); + //Rectangle targetClip = SwingUtilities.convertRectangle(this, r, root); + Point translation = SwingUtilities.convertPoint(this, 0, 0, root); Graphics g2 = buffer.getGraphics(); - g2 = getComponentGraphics(g2); + g2.translate(translation.x, translation.y); g2.setClip(r.x, r.y, r.width, r.height); + g2 = getComponentGraphics(g2); isPaintingDoubleBuffered = true; try { @@ -1929,20 +1786,27 @@ public abstract class JComponent extends Container implements Serializable isPaintingDoubleBuffered = false; g2.dispose(); } - + // Paint the buffer contents on screen. - g.drawImage(buffer, 0, 0, this); + rm.commitBuffer(root, new Rectangle(translation.x + r.x, + translation.y + r.y, r.width, + r.height)); } /** * Performs normal painting without double buffering. * - * @param g the graphics context to use + * @param r the area that should be repainted */ - void paintSimple(Graphics g) + void paintSimple(Rectangle r) { + Graphics g = getGraphics(); Graphics g2 = getComponentGraphics(g); + g2.setClip(r); paint(g2); + g2.dispose(); + if (g != g2) + g.dispose(); } /** @@ -2339,12 +2203,8 @@ public abstract class JComponent extends Container implements Serializable */ public void repaint(long tm, int x, int y, int width, int height) { - Rectangle dirty = new Rectangle(x, y, width, height); - Rectangle vis = getVisibleRect(); - dirty = dirty.intersection(vis); - RepaintManager.currentManager(this).addDirtyRegion(this, dirty.x, dirty.y, - dirty.width, - dirty.height); + RepaintManager.currentManager(this).addDirtyRegion(this, x, y, width, + height); } /** @@ -2356,8 +2216,8 @@ public abstract class JComponent extends Container implements Serializable */ public void repaint(Rectangle r) { - repaint((long) 0, (int) r.getX(), (int) r.getY(), (int) r.getWidth(), - (int) r.getHeight()); + RepaintManager.currentManager(this).addDirtyRegion(this, r.x, r.y, r.width, + r.height); } /** @@ -2879,7 +2739,7 @@ public abstract class JComponent extends Container implements Serializable * * @since 1.4 */ - public boolean requestFocusInWindow(boolean temporary) + protected boolean requestFocusInWindow(boolean temporary) { return super.requestFocusInWindow(temporary); } @@ -3046,19 +2906,6 @@ public abstract class JComponent extends Container implements Serializable } /** - * Return all PropertyChangeListener objects registered. - * - * @return The set of PropertyChangeListener objects - */ - public PropertyChangeListener[] getPropertyChangeListeners() - { - if (changeSupport == null) - return new PropertyChangeListener[0]; - else - return changeSupport.getPropertyChangeListeners(); - } - - /** * Prints this component to the given Graphics context. A call to this * method results in calls to the methods {@link #printComponent}, * {@link #printBorder} and {@link #printChildren} in this order. @@ -3098,7 +2945,7 @@ public abstract class JComponent extends Container implements Serializable * * @since 1.3 */ - public void printComponent(Graphics g) + protected void printComponent(Graphics g) { paintComponent(g); } @@ -3112,7 +2959,7 @@ public abstract class JComponent extends Container implements Serializable * * @since 1.3 */ - public void printChildren(Graphics g) + protected void printChildren(Graphics g) { paintChildren(g); } @@ -3126,7 +2973,7 @@ public abstract class JComponent extends Container implements Serializable * * @since 1.3 */ - public void printBorder(Graphics g) + protected void printBorder(Graphics g) { paintBorder(g); } @@ -3245,62 +3092,25 @@ public abstract class JComponent extends Container implements Serializable while (parent != null && !(parent instanceof Window)) { Container newParent = parent.getParent(); - if (newParent == null) + if (newParent == null || newParent instanceof Window) break; // If the parent is optimizedDrawingEnabled, then its children are // tiled and cannot have an overlapping child. Go directly to next // parent. - if (newParent instanceof JComponent - && ((JComponent) newParent).isOptimizedDrawingEnabled()) + if ((newParent instanceof JComponent + && ((JComponent) newParent).isOptimizedDrawingEnabled())) + { parent = newParent; continue; } - - // First we must check if the new parent itself somehow clips the - // target rectangle. This can happen in JViewports. - Rectangle parRect = new Rectangle(0, 0, newParent.getWidth(), - newParent.getHeight()); + // If the parent is not optimizedDrawingEnabled, we must paint the + // parent. Rectangle target = SwingUtilities.convertRectangle(found, currentClip, newParent); - if (! target.intersection(parRect).equals(target)) - { - found = newParent; - currentClip = target; - parent = newParent; - continue; - } - - // Otherwise we must check if one of the children of this parent - // overlaps with the current component. - Component[] children = newParent.getComponents(); - // This flag is used to skip components that are 'below' the component - // in question. - boolean skip = true; - for (int i = children.length - 1; i >= 0; i--) - { - boolean nextSkip = skip; - if (children[i] == parent) - nextSkip = false; - if (skip) - continue; - skip = nextSkip; - Component c = children[i]; - Rectangle compBounds = c.getBounds(); - // If the component completely overlaps the clip in question, we - // don't need to repaint. Return null. - if (compBounds.contains(target)) - return null; - if (compBounds.intersects(target)) - { - // We found a parent whose children overlap with our current - // component. Make this the current component. - found = newParent; - currentClip = target; - break; - } - } + found = newParent; + currentClip = target; parent = newParent; } return found; diff --git a/libjava/classpath/javax/swing/JDialog.java b/libjava/classpath/javax/swing/JDialog.java index b3f7c01..08dada2 100644 --- a/libjava/classpath/javax/swing/JDialog.java +++ b/libjava/classpath/javax/swing/JDialog.java @@ -74,7 +74,7 @@ public class JDialog extends Dialog implements Accessible, WindowConstants, /** * Creates a new instance of AccessibleJDialog. */ - public AccessibleJDialog() + protected AccessibleJDialog() { super(); // Nothing to do here. @@ -107,7 +107,7 @@ public class JDialog extends Dialog implements Accessible, WindowConstants, */ public JDialog() { - this(SwingUtilities.getOwnerFrame(), "", false, null); + this((Frame) SwingUtilities.getOwnerFrame(null), "", false, null); } /** @@ -234,8 +234,7 @@ public class JDialog extends Dialog implements Accessible, WindowConstants, public JDialog(Frame owner, String title, boolean modal, GraphicsConfiguration gc) { - super((owner == null) ? SwingUtilities.getOwnerFrame() : owner, - title, modal, gc); + super((Frame) SwingUtilities.getOwnerFrame(owner), title, modal, gc); dialogInit(); } diff --git a/libjava/classpath/javax/swing/JEditorPane.java b/libjava/classpath/javax/swing/JEditorPane.java index 3560ffd..73b7757 100644 --- a/libjava/classpath/javax/swing/JEditorPane.java +++ b/libjava/classpath/javax/swing/JEditorPane.java @@ -38,6 +38,7 @@ exception statement from your version. */ package javax.swing; +import java.awt.Container; import java.awt.Dimension; import java.io.IOException; import java.io.InputStream; @@ -682,27 +683,59 @@ public class JEditorPane extends JTextComponent } /** - * Returns the preferred size for the JEditorPane. + * Returns the preferred size for the JEditorPane. This is implemented to + * return the super's preferred size, unless one of + * {@link #getScrollableTracksViewportHeight()} or + * {@link #getScrollableTracksViewportWidth()} returns true, + * in which case the preferred width and/or height is replaced by the UI's + * minimum size. + * + * @return the preferred size for the JEditorPane */ public Dimension getPreferredSize() { - return super.getPreferredSize(); + Dimension pref = super.getPreferredSize(); + if (getScrollableTracksViewportWidth()) + pref.width = getUI().getMinimumSize(this).width; + if (getScrollableTracksViewportHeight()) + pref.height = getUI().getMinimumSize(this).height; + return pref; } + /** + * Returns true when a Viewport should force the height of + * this component to match the viewport height. This is implemented to return + * true when the parent is an instance of JViewport and + * the viewport height > the UI's minimum height. + * + * @return true when a Viewport should force the height of + * this component to match the viewport height + */ public boolean getScrollableTracksViewportHeight() { - /* Container parent = getParent(); - return (parent instanceof JViewport && - parent.isValid());*/ - return isValid(); + // Tests show that this returns true when the parent is a JViewport + // and has a height > minimum UI height. + Container parent = getParent(); + return parent instanceof JViewport + && parent.getHeight() > getUI().getMinimumSize(this).height; } + /** + * Returns true when a Viewport should force the width of + * this component to match the viewport width. This is implemented to return + * true when the parent is an instance of JViewport and + * the viewport width > the UI's minimum width. + * + * @return true when a Viewport should force the width of + * this component to match the viewport width + */ public boolean getScrollableTracksViewportWidth() { - /*Container parent = getParent(); - return (parent instanceof JViewport && - parent.isValid());*/ - return isValid(); + // Tests show that this returns true when the parent is a JViewport + // and has a width > minimum UI width. + Container parent = getParent(); + return parent != null && parent instanceof JViewport + && parent.getWidth() > getUI().getMinimumSize(this).width; } public URL getPage() @@ -893,7 +926,7 @@ public class JEditorPane extends JTextComponent // Remove the current content. Document doc = getDocument(); doc.remove(0, doc.getLength()); - if (t == null || t == "") + if (t == null || t.equals("")) return; // Let the EditorKit read the text into the Document. diff --git a/libjava/classpath/javax/swing/JFileChooser.java b/libjava/classpath/javax/swing/JFileChooser.java index 3a9d6a0..72bd2bb 100644 --- a/libjava/classpath/javax/swing/JFileChooser.java +++ b/libjava/classpath/javax/swing/JFileChooser.java @@ -40,7 +40,6 @@ package javax.swing; import java.awt.Component; import java.awt.Frame; import java.awt.HeadlessException; -import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; @@ -658,8 +657,7 @@ public class JFileChooser extends JComponent implements Accessible retval = ERROR_OPTION; - Insets i = d.getInsets(); - d.setSize(500 + i.top + i.bottom, d.getPreferredSize().height); + d.pack(); d.show(); return retval; } @@ -683,8 +681,7 @@ public class JFileChooser extends JComponent implements Accessible retval = ERROR_OPTION; - Insets i = d.getInsets(); - d.setSize(500 + i.top + i.bottom, d.getPreferredSize().height); + d.pack(); d.show(); return retval; } @@ -710,8 +707,7 @@ public class JFileChooser extends JComponent implements Accessible retval = ERROR_OPTION; - Insets i = d.getInsets(); - d.setSize(500 + i.top + i.bottom, d.getPreferredSize().height); + d.pack(); d.show(); return retval; } @@ -729,7 +725,7 @@ public class JFileChooser extends JComponent implements Accessible { Frame toUse = (Frame) SwingUtilities.getAncestorOfClass(Frame.class, parent); if (toUse == null) - toUse = SwingUtilities.getOwnerFrame(); + toUse = (Frame) SwingUtilities.getOwnerFrame(null); JDialog dialog = new JDialog(toUse); setSelectedFile(null); diff --git a/libjava/classpath/javax/swing/JFrame.java b/libjava/classpath/javax/swing/JFrame.java index 8d4dcb5..d251205 100644 --- a/libjava/classpath/javax/swing/JFrame.java +++ b/libjava/classpath/javax/swing/JFrame.java @@ -76,7 +76,7 @@ public class JFrame extends Frame /** * Creates a new instance of AccessibleJFrame. */ - public AccessibleJFrame() + protected AccessibleJFrame() { super(); // Nothing to do here. @@ -150,6 +150,15 @@ public class JFrame extends Frame super.setLayout(new BorderLayout(1, 1)); enableEvents(AWTEvent.WINDOW_EVENT_MASK); getRootPane(); // will do set/create + + // Setup the defaultLookAndFeelDecoration if requested. + if (isDefaultLookAndFeelDecorated() + && UIManager.getLookAndFeel().getSupportsWindowDecorations()) + { + setUndecorated(true); + getRootPane().setWindowDecorationStyle(JRootPane.FRAME); + } + // We're now done the init stage. setRootPaneCheckingEnabled(true); } diff --git a/libjava/classpath/javax/swing/JInternalFrame.java b/libjava/classpath/javax/swing/JInternalFrame.java index 948988c..5bd6f78 100644 --- a/libjava/classpath/javax/swing/JInternalFrame.java +++ b/libjava/classpath/javax/swing/JInternalFrame.java @@ -559,6 +559,8 @@ public class JInternalFrame extends JComponent implements Accessible, this.iconable = iconifiable; storedBounds = new Rectangle(); setRootPane(createRootPane()); + // JInternalFrames are invisible by default. + setVisible(false); updateUI(); setRootPaneCheckingEnabled(true); // Done the init stage, now adds go to content pane. } @@ -616,7 +618,7 @@ public class JInternalFrame extends JComponent implements Accessible, */ public void dispose() { - hide(); + setVisible(false); JDesktopPane pane = getDesktopPane(); if (pane != null) pane.setSelectedFrame(null); @@ -647,11 +649,11 @@ public class JInternalFrame extends JComponent implements Accessible, switch (getDefaultCloseOperation()) { case HIDE_ON_CLOSE: - hide(); - break; + setVisible(false); + break; case DISPOSE_ON_CLOSE: - dispose(); - break; + dispose(); + break; } } @@ -1257,13 +1259,14 @@ public class JInternalFrame extends JComponent implements Accessible, { if (b && ! isClosed()) { - fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSING); - fireVetoableChange(IS_CLOSED_PROPERTY, false, true); + fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSING); + fireVetoableChange(IS_CLOSED_PROPERTY, false, true); - isClosed = b; + isClosed = b; + dispose(); - firePropertyChange(IS_CLOSED_PROPERTY, false, true); - fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSED); + firePropertyChange(IS_CLOSED_PROPERTY, false, true); + fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSED); } } @@ -1628,27 +1631,27 @@ public class JInternalFrame extends JComponent implements Accessible, { if (! isVisible()) { - super.show(); - - JDesktopPane pane = getDesktopPane(); - if (pane != null) - pane.setSelectedFrame(this); - else - { - try - { - setSelected(true); - } - catch (PropertyVetoException e) - { - // Do nothing. if they don't want to be selected. - } - } - if (isFirstTimeVisible) - { - isFirstTimeVisible = false; - fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_OPENED); - } + super.show(); + + JDesktopPane pane = getDesktopPane(); + if (pane != null) + pane.setSelectedFrame(this); + else + { + try + { + setSelected(true); + } + catch (PropertyVetoException e) + { + // Do nothing. if they don't want to be selected. + } + } + if (isFirstTimeVisible) + { + isFirstTimeVisible = false; + fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_OPENED); + } } } diff --git a/libjava/classpath/javax/swing/JLayeredPane.java b/libjava/classpath/javax/swing/JLayeredPane.java index dc8b10d..ffd803c 100644 --- a/libjava/classpath/javax/swing/JLayeredPane.java +++ b/libjava/classpath/javax/swing/JLayeredPane.java @@ -43,11 +43,7 @@ import java.awt.Component; import java.awt.Container; import java.awt.Graphics; import java.awt.Rectangle; -import java.awt.Shape; import java.util.Hashtable; -import java.util.Iterator; -import java.util.Map; -import java.util.TreeMap; import javax.accessibility.Accessible; import javax.accessibility.AccessibleContext; @@ -119,6 +115,7 @@ import javax.accessibility.AccessibleRole; * component indexing and position order

* * @author Graydon Hoare (graydon@redhat.com) + * @author Roman Kennke (kennke@aicas.com) */ public class JLayeredPane extends JComponent implements Accessible { @@ -131,7 +128,7 @@ public class JLayeredPane extends JComponent implements Accessible /** * Creates a new instance of AccessibleJLayeredPane. */ - public AccessibleJLayeredPane() + protected AccessibleJLayeredPane() { // Nothing to do here. } @@ -150,22 +147,18 @@ public class JLayeredPane extends JComponent implements Accessible public static final String LAYER_PROPERTY = "layeredContainerLayer"; - public static Integer FRAME_CONTENT_LAYER = new Integer (-30000); + public static final Integer FRAME_CONTENT_LAYER = new Integer (-30000); - public static Integer DEFAULT_LAYER = new Integer (0); - public static Integer PALETTE_LAYER = new Integer (100); - public static Integer MODAL_LAYER = new Integer (200); - public static Integer POPUP_LAYER = new Integer (300); - public static Integer DRAG_LAYER = new Integer (400); + public static final Integer DEFAULT_LAYER = new Integer (0); + public static final Integer PALETTE_LAYER = new Integer (100); + public static final Integer MODAL_LAYER = new Integer (200); + public static final Integer POPUP_LAYER = new Integer (300); + public static final Integer DRAG_LAYER = new Integer (400); - TreeMap layers; // Layer Number (Integer) -> Layer Size (Integer) - Hashtable componentToLayer; // Component -> Layer Number (Integer) + private Hashtable componentToLayer; // Component -> Layer Number (Integer) - private transient Rectangle rectCache; - public JLayeredPane() { - layers = new TreeMap (); componentToLayer = new Hashtable (); setLayout(null); } @@ -173,47 +166,50 @@ public class JLayeredPane extends JComponent implements Accessible /** * Looks up the layer a child component is currently assigned to. * + * If c is an instance of {@link JComponent}, then the layer + * is fetched from the client property with the key {@link #LAYER_PROPERTY}. + * Otherwise it is looked up in an internal hashtable that maps + * non-JComponent components to layers. If the components cannot be found + * in either way, the {@link #DEFAULT_LAYER} is returned. + * * @param c the component to look up. - * @return the layer the component is currently assigned to, in this container. - * @throws IllegalArgumentException if the component is not a child of this container. + * + * @return the layer the component is currently assigned to; if the component + * is not in this layered pane, then 0 (DEFAULT_LAYER) is returned */ public int getLayer(Component c) { - Component myComp = c; - while(! componentToLayer.containsKey(myComp)) + Integer layerObj; + if (c instanceof JComponent) { - myComp = myComp.getParent(); - if (myComp == null) - break; + JComponent jc = (JComponent) c; + layerObj = (Integer) jc.getClientProperty(LAYER_PROPERTY); } - if (myComp == null) - throw new IllegalArgumentException - ("component is not in this JLayeredPane"); - Integer layerObj = (Integer) componentToLayer.get(myComp); + else + layerObj = (Integer) componentToLayer.get(c); + + if (layerObj == null) + layerObj = DEFAULT_LAYER; + return layerObj.intValue(); } /** - * Looks up the layer of comp in the component's nearest - * JLayeredPane ancestor. If comp is not contained - * in a JLayeredPane, the value 0 (default layer) is returned. - * + * Looks up the layer in the client property with the key + * {@link #LAYER_PROPERTY} of comp. If no such property can be + * found, we return 0 ({@link #DEFAULT_LAYER}). + * * @param comp the component for which the layer is looked up * - * @return the layer of comp in its nearest JLayeredPane - * ancestor + * @return the layer of comp as stored in the corresponding + * client property, or 0 if there is no such property */ public static int getLayer(JComponent comp) { - JLayeredPane lp = (JLayeredPane) SwingUtilities.getAncestorOfClass - (JLayeredPane.class, comp); - if (lp == null) - return 0; - else - // The cast here forces the call to the instance method getLayer() - // instead of the static method (this would lead to infinite - // recursion). - return lp.getLayer((Component) comp); + Integer layerObj = (Integer) comp.getClientProperty(LAYER_PROPERTY); + if (layerObj == null) + layerObj = DEFAULT_LAYER; + return layerObj.intValue(); } /** @@ -236,105 +232,49 @@ public class JLayeredPane extends JComponent implements Accessible } /** - *

Returns a pair of ints representing a half-open interval - * [top, bottom), which is the range of component indices - * the provided layer number corresponds to.

- * - *

Note that "bottom" is not included in the interval of - * component indices in this layer: a layer with 0 elements in it has - * ret[0] == ret[1].

- * - * @param layer the layer to look up. - * @return the half-open range of indices this layer spans. - * @throws IllegalArgumentException if layer does not refer to an active layer - * in this container. - */ - private int[] layerToRange (Integer layer) - { - int[] ret = new int[2]; - ret[1] = getComponents ().length; - Iterator i = layers.entrySet ().iterator (); - while (i.hasNext()) - { - Map.Entry pair = (Map.Entry) i.next(); - Integer layerNum = (Integer) pair.getKey (); - Integer layerSz = (Integer) pair.getValue (); - int layerInt = layerNum.intValue(); - if (layerInt == layer.intValue()) - { - ret[0] = ret[1] - layerSz.intValue (); - break; - } - // In the following case there exists no layer with the specified - // number, so we return an empty interval here with the index at which - // such a layer would be inserted - else if (layerInt > layer.intValue()) - { - ret[1] = ret[0]; - break; - } - else - { - ret[1] -= layerSz.intValue (); - } - } - return ret; - } - - /** - * Increments the recorded size of a given layer. - * - * @param layer the layer number to increment. - * @see #incrLayer - */ - private void incrLayer(Integer layer) - { - int sz = 1; - if (layers.containsKey (layer)) - sz += ((Integer)(layers.get (layer))).intValue (); - layers.put (layer, new Integer(sz)); - } - - /** - * Decrements the recorded size of a given layer. - * - * @param layer the layer number to decrement. - * @see #incrLayer - */ - private void decrLayer(Integer layer) - { - int sz = 0; - if (layers.containsKey (layer)) - sz = ((Integer)(layers.get (layer))).intValue () - 1; - layers.put (layer, new Integer(sz)); - } - - /** * Return the greatest layer number currently in use, in this container. * This number may legally be positive or negative. * - * @return the least layer number. + * @return the highest layer number + * * @see #lowestLayer() */ public int highestLayer() { - if (layers.size() == 0) - return 0; - return ((Integer)(layers.lastKey ())).intValue (); + Component[] components = getComponents(); + int highest; + if (components.length == 0) + highest = 0; + else + { + highest = Integer.MIN_VALUE; + for (int i = 0; i < components.length; i++) + highest = Math.max(highest, getLayer(components[i])); + } + return highest; } /** * Return the least layer number currently in use, in this container. * This number may legally be positive or negative. * - * @return the least layer number. + * @return the least layer number + * * @see #highestLayer() */ public int lowestLayer() { - if (layers.size() == 0) - return 0; - return ((Integer)(layers.firstKey ())).intValue (); + Component[] components = getComponents(); + int lowest; + if (components.length == 0) + lowest = 0; + else + { + lowest = Integer.MAX_VALUE; + for (int i = 0; i < components.length; i++) + lowest = Math.max(lowest, getLayer(components[i])); + } + return lowest; } /** @@ -343,9 +283,8 @@ public class JLayeredPane extends JComponent implements Accessible * layer, so is usually the component which occludes the most other * components in its layer. * - * @param c the component to move to the front of its layer. - * @throws IllegalArgumentException if the component is not a child of - * this container. + * @param c the component to move to the front of its layer + * * @see #moveToBack */ public void moveToFront(Component c) @@ -363,8 +302,7 @@ public class JLayeredPane extends JComponent implements Accessible * other components in its layer.

* * @param c the component to move to the back of its layer. - * @throws IllegalArgumentException if the component is not a child of - * this container. + * * @see #moveToFront */ public void moveToBack(Component c) @@ -377,25 +315,30 @@ public class JLayeredPane extends JComponent implements Accessible * from the "front" (position 0) to the "back" (position N-1), and drawn from * the back towards the front. * - * @param c the component to get the position of. - * @throws IllegalArgumentException if the component is not a child of - * this container. + * @param c the component to get the position of + * + * @return the position of c within its layer or -1 if + * c is not a child of this layered pane + * * @see #setPosition */ public int getPosition(Component c) { - int layer = getLayer (c); - int[] range = layerToRange(new Integer(layer)); - int top = range[0]; - int bot = range[1]; - Component[] comps = getComponents (); - for (int i = top; i < bot; ++i) - { - if (comps[i] == c) - return i - top; - } - // should have found it - throw new IllegalArgumentException (); + int pos = -1; + int index = getIndexOf(c); + Component[] components = getComponents(); + int layer = getLayer(c); + if (index >= 0) + { + for (int i = index; i >= 0; --i) + { + if (layer == getLayer(components[i])) + pos++; + else + break; + } + } + return pos; } /** @@ -403,47 +346,16 @@ public class JLayeredPane extends JComponent implements Accessible * from the "front" (position 0) to the "back" (position N-1), and drawn from * the back towards the front. * - * @param c the component to change the position of. - * @param position the position to assign the component to. - * @throws IllegalArgumentException if the component is not a child of - * this container. + * @param c the component to change the position of + * @param position the position to assign the component to + * * @see #getPosition */ public void setPosition(Component c, int position) { - int layer = getLayer (c); - int[] range = layerToRange(new Integer(layer)); - if (range[0] == range[1]) - throw new IllegalArgumentException (); - - int top = range[0]; - int bot = range[1]; - if (position == -1) - position = (bot - top) - 1; - int targ = Math.min(top + position, bot-1); - int curr = -1; - - Component[] comps = getComponents(); - for (int i = top; i < bot; ++i) - { - if (comps[i] == c) - { - curr = i; - break; - } - } - if (curr == -1) - // should have found it - throw new IllegalArgumentException(); - - if (curr == 0) - super.swapComponents(curr, targ); - else - while (curr > 0) - super.swapComponents (curr, --curr); - - revalidate(); - repaint(); + int layer = getLayer(c); + int index = insertIndexForLayer(layer, position); + setComponentZOrder(c, index); } /** @@ -451,39 +363,44 @@ public class JLayeredPane extends JComponent implements Accessible * container. Components are ordered front-to-back, with the "front" * element (which draws last) at position 0 of the returned array. * - * @param layer the layer to return components from. - * @return the components in the layer. + * @param layer the layer to return components from + * + * @return the components in the layer */ public Component[] getComponentsInLayer(int layer) { - int[] range = layerToRange (getObjectForLayer (layer)); - if (range[0] == range[1]) - return new Component[0]; - else - { - Component[] comps = getComponents (); - int sz = range[1] - range[0]; - Component[] nc = new Component[sz]; - for (int i = 0; i < sz; ++i) - nc[i] = comps[range[0] + i]; - return nc; - } + Component[] inLayer = new Component[getComponentCountInLayer(layer)]; + Component[] components = getComponents(); + int j = 0; + for (int i = 0; i < components.length; ++i) + { + if (layer == getLayer(components[i])) + { + inLayer[j] = components[i]; + j++; + } + } + return inLayer; } /** * Return the number of components within a layer of this * container. * - * @param layer the layer count components in. - * @return the number of components in the layer. + * @param layer the layer count components in + * + * @return the number of components in the layer */ public int getComponentCountInLayer(int layer) { - int[] range = layerToRange (getObjectForLayer (layer)); - if (range[0] == range[1]) - return 0; - else - return (range[1] - range[0]); + Component[] components = getComponents(); + int count = 0; + for (int i = components.length - 1; i >= 0; --i) + { + if (getLayer(components[i]) == layer) + count++; + } + return count; } /** @@ -502,23 +419,14 @@ public class JLayeredPane extends JComponent implements Accessible * drawing order of all children of the container. * * @param c the component to look up. - * @return the external index of the component. - * @throws IllegalArgumentException if the component is not a child of - * this container. + * + * @return the external index of the component or -1 if + * c is not a child of this layered pane */ public int getIndexOf(Component c) { - int layer = getLayer (c); - int[] range = layerToRange(new Integer(layer)); - Component[] comps = getComponents(); - for (int i = range[0]; i < range[1]; ++i) - { - if (comps[i] == c) - return i; - } - // should have found the component during iteration - throw new IllegalArgumentException (); - } + return getComponentZOrder(c); + } /** * Return an Integer object which holds the same int value as the @@ -526,6 +434,7 @@ public class JLayeredPane extends JComponent implements Accessible * identical Integer objects which we allocate. * * @param layer the layer number as an int. + * * @return the layer number as an Integer, possibly shared. */ protected Integer getObjectForLayer(int layer) @@ -564,25 +473,39 @@ public class JLayeredPane extends JComponent implements Accessible * * @param layer the layer in which to insert a component. * @param position the position in the layer at which to insert a component. + * * @return the index at which to insert the component. */ protected int insertIndexForLayer(int layer, int position) { + // position < 0 means insert at greatest position within layer. + if (position < 0) + position = Integer.MAX_VALUE; - Integer lobj = getObjectForLayer (layer); - if (! layers.containsKey(lobj)) - layers.put (lobj, new Integer (0)); - int[] range = layerToRange (lobj); - if (range[0] == range[1]) - return range[0]; - - int top = range[0]; - int bot = range[1]; - - if (position == -1 || position > (bot - top)) - return bot; - else - return top + position; + Component[] components = getComponents(); + int index = 0; + + // Try to find the start index of the specified layer. + int p = -1; + for (int i = 0; i < components.length; i++) + { + int l = getLayer(components[i]); + if (l > layer) + index++; + // If we are in the layer we look for, try to find the position. + else if (l == layer) + { + p++; + if (p < position) + index++; + else + break; + } + // No need to look further if the layer at i is smaller than layer. + else + break; + } + return index; } /** @@ -594,12 +517,20 @@ public class JLayeredPane extends JComponent implements Accessible public void remove(int index) { Component c = getComponent(index); - int layer = getLayer(c); - decrLayer(new Integer(layer)); - componentToLayer.remove(c); + if (! (c instanceof JComponent)) + componentToLayer.remove(c); super.remove(index); - // FIXME: Figure out if this call is correct. - revalidate(); + } + + /** + * Removes all components from this container. + * + * @since 1.5 + */ + public void removeAll() + { + componentToLayer.clear(); + super.removeAll(); } /** @@ -615,7 +546,7 @@ public class JLayeredPane extends JComponent implements Accessible */ public void setLayer(Component c, int layer) { - componentToLayer.put (c, getObjectForLayer (layer)); + setLayer(c, layer, -1); } /** @@ -625,15 +556,20 @@ public class JLayeredPane extends JComponent implements Accessible * @param layer the layer number to assign to the component. * @param position the position number to assign to the component. */ - public void setLayer(Component c, - int layer, - int position) + public void setLayer(Component c, int layer, int position) { - remove(c); - add(c, getObjectForLayer (layer)); - setPosition(c, position); - revalidate(); - repaint(); + Integer layerObj = getObjectForLayer(layer); + if (c instanceof JComponent) + { + JComponent jc = (JComponent) c; + jc.putClientProperty(LAYER_PROPERTY, layerObj); + } + else + componentToLayer.put (c, layerObj); + + // Set position only of component is already added to this layered pane. + if (getIndexOf(c) != -1) + setPosition(c, position); } /** @@ -642,26 +578,27 @@ public class JLayeredPane extends JComponent implements Accessible * Integer}, specifying the layer to which the component will be added * (at the bottom position). * - * @param comp the component to add. - * @param layerConstraint an integer specifying the layer to add the component to. - * @param index an ignored parameter, for compatibility. + * The argument index specifies the position within the layer + * at which the component should be added, where 0 is the top + * position greater values specify positions below that and -1 + * specifies the bottom position. + * + * @param comp the component to add + * @param layerConstraint an integer specifying the layer to add the + * component to + * @param index the position within the layer */ protected void addImpl(Component comp, Object layerConstraint, int index) { - Integer layer; + int layer; if (layerConstraint != null && layerConstraint instanceof Integer) - layer = (Integer) layerConstraint; - else if (componentToLayer.containsKey (comp)) - layer = (Integer) componentToLayer.remove (comp); + layer = ((Integer) layerConstraint).intValue(); else - layer = DEFAULT_LAYER; - - int newIdx = insertIndexForLayer(layer.intValue (), index); + layer = getLayer(comp); - componentToLayer.put (comp, layer); - incrLayer (layer); - - super.addImpl(comp, null, newIdx); + int newIdx = insertIndexForLayer(layer, index); + setLayer(comp, layer); + super.addImpl(comp, layerConstraint, newIdx); } /** @@ -672,7 +609,7 @@ public class JLayeredPane extends JComponent implements Accessible */ public static void putLayer(JComponent component, int layer) { - getLayeredPaneAbove(component).setLayer(component, layer); + component.putClientProperty(LAYER_PROPERTY, new Integer(layer)); } /** @@ -711,13 +648,42 @@ public class JLayeredPane extends JComponent implements Accessible } /** - * Overridden to return false, since JLayeredPane - * cannot guarantee that its children don't overlap. + * Returns false if components in this layered pane can overlap, + * otherwise true. * - * @return false + * @return false if components in this layered pane can overlap, + * otherwise true */ public boolean isOptimizedDrawingEnabled() { - return false; + int numChildren = getComponentCount(); + boolean result = true; + for (int i = 0; i < numChildren; ++i) + { + Component c1 = getComponent(i); + if (! c1.isVisible()) + continue; + Rectangle r1 = c1.getBounds(); + if (r1.isEmpty()) + continue; + + for (int j = i + 1; j < numChildren; ++j) + { + Component c2 = getComponent(j); + if (! c2.isVisible()) + continue; + Rectangle r2 = c2.getBounds(); + if (r2.isEmpty()) + continue; + if (r1.intersects(r2)) + { + result = false; + break; + } + if (result == false) + break; + } + } + return result; } } diff --git a/libjava/classpath/javax/swing/JMenu.java b/libjava/classpath/javax/swing/JMenu.java index 369c44d..a160dd4 100644 --- a/libjava/classpath/javax/swing/JMenu.java +++ b/libjava/classpath/javax/swing/JMenu.java @@ -906,7 +906,7 @@ public class JMenu extends JMenuItem implements Accessible, MenuElement /** * This class listens to PropertyChangeEvents occuring in menu's action */ - protected class ActionChangedListener implements PropertyChangeListener + private class ActionChangedListener implements PropertyChangeListener { /** menu item associated with the action */ private JMenuItem menuItem; diff --git a/libjava/classpath/javax/swing/JMenuBar.java b/libjava/classpath/javax/swing/JMenuBar.java index f018daa..60726fb 100644 --- a/libjava/classpath/javax/swing/JMenuBar.java +++ b/libjava/classpath/javax/swing/JMenuBar.java @@ -1,5 +1,5 @@ /* JMenuBar.java -- - Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -51,6 +51,8 @@ import javax.accessibility.AccessibleSelection; import javax.accessibility.AccessibleStateSet; import javax.swing.plaf.MenuBarUI; +import javax.swing.border.Border; + /** * JMenuBar is a container for menu's. For a menu bar to be seen on the * screen, at least one menu should be added to it. Just like adding @@ -437,8 +439,12 @@ public class JMenuBar extends JComponent implements Accessible, MenuElement protected void paintBorder(Graphics g) { if (borderPainted) - getBorder().paintBorder(this, g, 0, 0, getSize(null).width, - getSize(null).height); + { + Border border = getBorder(); + if (border != null) + getBorder().paintBorder(this, g, 0, 0, getSize(null).width, + getSize(null).height); + } } /** diff --git a/libjava/classpath/javax/swing/JOptionPane.java b/libjava/classpath/javax/swing/JOptionPane.java index 057326c..705eca8 100644 --- a/libjava/classpath/javax/swing/JOptionPane.java +++ b/libjava/classpath/javax/swing/JOptionPane.java @@ -197,7 +197,7 @@ public class JOptionPane extends JComponent implements Accessible public static final String WANTS_INPUT_PROPERTY = "wantsInput"; /** The value returned when the inputValue is uninitialized. */ - public static Object UNINITIALIZED_VALUE = "uninitializedValue"; + public static final Object UNINITIALIZED_VALUE = "uninitializedValue"; /** The icon displayed in the dialog/internal frame. */ protected Icon icon; @@ -236,7 +236,7 @@ public class JOptionPane extends JComponent implements Accessible protected boolean wantsInput; /** The common frame used when no parent is provided. */ - private static Frame privFrame = SwingUtilities.getOwnerFrame(); + private static Frame privFrame = (Frame) SwingUtilities.getOwnerFrame(null); /** * Creates a new JOptionPane object using a message of "JOptionPane diff --git a/libjava/classpath/javax/swing/JPanel.java b/libjava/classpath/javax/swing/JPanel.java index c02a9cf..815e452 100644 --- a/libjava/classpath/javax/swing/JPanel.java +++ b/libjava/classpath/javax/swing/JPanel.java @@ -63,7 +63,7 @@ public class JPanel extends JComponent implements Accessible /** * Creates a new instance of AccessibleJPanel. */ - public AccessibleJPanel() + protected AccessibleJPanel() { // Nothing to do here. } diff --git a/libjava/classpath/javax/swing/JPopupMenu.java b/libjava/classpath/javax/swing/JPopupMenu.java index 1f2282e..74f733e 100644 --- a/libjava/classpath/javax/swing/JPopupMenu.java +++ b/libjava/classpath/javax/swing/JPopupMenu.java @@ -866,7 +866,7 @@ public class JPopupMenu extends JComponent implements Accessible, MenuElement /* This class resizes popup menu and repaints popup menu appropriately if one of item's action has changed */ - protected class ActionChangeListener implements PropertyChangeListener + private class ActionChangeListener implements PropertyChangeListener { public void propertyChange(PropertyChangeEvent evt) { diff --git a/libjava/classpath/javax/swing/JProgressBar.java b/libjava/classpath/javax/swing/JProgressBar.java index abca3e7..e7ee800 100644 --- a/libjava/classpath/javax/swing/JProgressBar.java +++ b/libjava/classpath/javax/swing/JProgressBar.java @@ -1,5 +1,5 @@ /* JProgressBar.java -- - Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -174,8 +174,8 @@ public class JProgressBar extends JComponent implements SwingConstants, /** Whether the ProgressBar is determinate. */ private transient boolean indeterminate = false; - /** The orientation of the ProgressBar */ - protected int orientation = HORIZONTAL; + /** The orientation of the ProgressBar. Always set by constructor. */ + protected int orientation; /** Whether borders should be painted. */ protected boolean paintBorder = true; @@ -245,8 +245,9 @@ public class JProgressBar extends JComponent implements SwingConstants, { model = new DefaultBoundedRangeModel(minimum, 0, minimum, maximum); if (orientation != HORIZONTAL && orientation != VERTICAL) - throw new IllegalArgumentException(orientation + " is not a legal orientation"); - setOrientation(orientation); + throw new IllegalArgumentException(orientation + + " is not a legal orientation"); + this.orientation = orientation; changeListener = createChangeListener(); model.addChangeListener(changeListener); updateUI(); @@ -316,11 +317,14 @@ public class JProgressBar extends JComponent implements SwingConstants, * JProgressBar can be either horizontal or vertical. * * @param orientation The orientation of the JProgressBar. + * @throws IllegalArgumentException if orientation is not + * either {@link #HORIZONTAL} or {@link #VERTICAL}. */ public void setOrientation(int orientation) { if (orientation != VERTICAL && orientation != HORIZONTAL) - throw new IllegalArgumentException("orientation must be one of VERTICAL or HORIZONTAL"); + throw new IllegalArgumentException(orientation + + " is not a legal orientation"); if (this.orientation != orientation) { int oldOrientation = this.orientation; diff --git a/libjava/classpath/javax/swing/JRootPane.java b/libjava/classpath/javax/swing/JRootPane.java index dea4ee4..dec4395 100644 --- a/libjava/classpath/javax/swing/JRootPane.java +++ b/libjava/classpath/javax/swing/JRootPane.java @@ -120,11 +120,6 @@ public class JRootPane extends JComponent implements Accessible private Rectangle menuBarBounds; /** - * The cached preferred size. - */ - private Dimension prefSize; - - /** * Creates a new RootLayout object. */ protected RootLayout() @@ -191,7 +186,6 @@ public class JRootPane extends JComponent implements Accessible layeredPaneBounds = null; contentPaneBounds = null; menuBarBounds = null; - prefSize = null; } } @@ -251,7 +245,7 @@ public class JRootPane extends JComponent implements Accessible layeredPane.setBounds(layeredPaneBounds); if (menuBar != null) menuBar.setBounds(menuBarBounds); - contentPane.setBounds(contentPaneBounds); + getContentPane().setBounds(contentPaneBounds); } /** @@ -287,29 +281,20 @@ public class JRootPane extends JComponent implements Accessible */ public Dimension preferredLayoutSize(Container c) { - // We must synchronize here, otherwise we cannot guarantee that the - // prefSize is still non-null when returning. - synchronized (this) + Dimension prefSize = new Dimension(); + Insets i = getInsets(); + prefSize = new Dimension(i.left + i.right, i.top + i.bottom); + Dimension contentPrefSize = getContentPane().getPreferredSize(); + prefSize.width += contentPrefSize.width; + prefSize.height += contentPrefSize.height; + if (menuBar != null) { - if (prefSize == null) - { - Insets i = getInsets(); - prefSize = new Dimension(i.left + i.right, i.top + i.bottom); - Dimension contentPrefSize = contentPane.getPreferredSize(); - prefSize.width += contentPrefSize.width; - prefSize.height += contentPrefSize.height; - if (menuBar != null) - { - Dimension menuBarSize = menuBar.getPreferredSize(); - if (menuBarSize.width > contentPrefSize.width) - prefSize.width += menuBarSize.width - contentPrefSize.width; - prefSize.height += menuBarSize.height; - } - } - // Return a copy here so the cached value won't get trashed by some - // other component. - return new Dimension(prefSize); - } + Dimension menuBarSize = menuBar.getPreferredSize(); + if (menuBarSize.width > contentPrefSize.width) + prefSize.width += menuBarSize.width - contentPrefSize.width; + prefSize.height += menuBarSize.height; + } + return prefSize; } /** @@ -541,6 +526,7 @@ public class JRootPane extends JComponent implements Accessible getGlassPane(); getLayeredPane(); getContentPane(); + setOpaque(true); updateUI(); } @@ -674,4 +660,18 @@ public class JRootPane extends JComponent implements Accessible windowDecorationStyle = style; firePropertyChange("windowDecorationStyle", oldStyle, style); } + + /** + * This returns true if the glassPane is not + * visible because then the root pane can guarantee to tile its children + * (the only other direct child is a JLayeredPane which must figure its + * optimizeDrawingEnabled state on its own). + * + * @return true if the glassPane is not + * visible + */ + public boolean isOptimizedDrawingEnable() + { + return ! glassPane.isVisible(); + } } diff --git a/libjava/classpath/javax/swing/JSpinner.java b/libjava/classpath/javax/swing/JSpinner.java index af34d9c..882d216 100644 --- a/libjava/classpath/javax/swing/JSpinner.java +++ b/libjava/classpath/javax/swing/JSpinner.java @@ -1,5 +1,5 @@ /* JSpinner.java -- - Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -45,7 +45,9 @@ import java.awt.Insets; import java.awt.LayoutManager; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.text.DateFormat; import java.text.DecimalFormat; +import java.text.NumberFormat; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -53,10 +55,15 @@ import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.plaf.SpinnerUI; import javax.swing.text.DateFormatter; +import javax.swing.text.DefaultFormatterFactory; +import javax.swing.text.NumberFormatter; /** - * A JSpinner is a component which typically contains a numeric value and a - * way to manipulate the value. + * A JSpinner is a component that displays a single value from + * a sequence of values, and provides a convenient means for selecting the + * previous and next values in the sequence. Typically the spinner displays + * a numeric value, but it is possible to display dates or arbitrary items + * from a list. * * @author Ka-Hing Cheung * @@ -65,12 +72,15 @@ import javax.swing.text.DateFormatter; public class JSpinner extends JComponent { /** - * DOCUMENT ME! + * The base class for the editor used by the {@link JSpinner} component. + * The editor is in fact a panel containing a {@link JFormattedTextField} + * component. */ - public static class DefaultEditor extends JPanel implements ChangeListener, - PropertyChangeListener, - LayoutManager + public static class DefaultEditor + extends JPanel + implements ChangeListener, PropertyChangeListener, LayoutManager { + /** The spinner that the editor is allocated to. */ private JSpinner spinner; /** The JFormattedTextField that backs the editor. */ @@ -82,7 +92,8 @@ public class JSpinner extends JComponent private static final long serialVersionUID = -5317788736173368172L; /** - * Creates a new DefaultEditor object. + * Creates a new DefaultEditor object. The editor is + * registered with the spinner as a {@link ChangeListener} here. * * @param spinner the JSpinner associated with this editor */ @@ -94,11 +105,15 @@ public class JSpinner extends JComponent ftf = new JFormattedTextField(); add(ftf); ftf.setValue(spinner.getValue()); + ftf.addPropertyChangeListener(this); spinner.addChangeListener(this); } /** - * Returns the JSpinner object for this editor. + * Returns the JSpinner component that the editor is assigned + * to. + * + * @return The spinner that the editor is assigned to. */ public JSpinner getSpinner() { @@ -114,9 +129,10 @@ public class JSpinner extends JComponent } /** - * DOCUMENT ME! + * Removes the editor from the {@link ChangeListener} list maintained by + * the specified spinner. * - * @param spinner DOCUMENT ME! + * @param spinner the spinner (null not permitted). */ public void dismiss(JSpinner spinner) { @@ -124,9 +140,10 @@ public class JSpinner extends JComponent } /** - * DOCUMENT ME! + * Returns the text field used to display and edit the current value in + * the spinner. * - * @return DOCUMENT ME! + * @return The text field. */ public JFormattedTextField getTextField() { @@ -134,9 +151,10 @@ public class JSpinner extends JComponent } /** - * DOCUMENT ME! + * Sets the bounds for the child components in this container. In this + * case, the text field is the only component to be laid out. * - * @param parent DOCUMENT ME! + * @param parent the parent container. */ public void layoutContainer(Container parent) { @@ -148,11 +166,13 @@ public class JSpinner extends JComponent } /** - * DOCUMENT ME! + * Calculates the minimum size for this component. In this case, the + * text field is the only subcomponent, so the return value is the minimum + * size of the text field plus the insets of this component. * - * @param parent DOCUMENT ME! + * @param parent the parent container. * - * @return DOCUMENT ME! + * @return The minimum size. */ public Dimension minimumLayoutSize(Container parent) { @@ -163,11 +183,13 @@ public class JSpinner extends JComponent } /** - * DOCUMENT ME! + * Calculates the preferred size for this component. In this case, the + * text field is the only subcomponent, so the return value is the + * preferred size of the text field plus the insets of this component. * - * @param parent DOCUMENT ME! + * @param parent the parent container. * - * @return DOCUMENT ME! + * @return The preferred size. */ public Dimension preferredLayoutSize(Container parent) { @@ -178,35 +200,51 @@ public class JSpinner extends JComponent } /** - * DOCUMENT ME! + * Receives notification of property changes. If the text field's 'value' + * property changes, the spinner's model is updated accordingly. * - * @param event DOCUMENT ME! + * @param event the event. */ public void propertyChange(PropertyChangeEvent event) { - // TODO: Implement this properly. + if (event.getSource() == ftf) + { + if (event.getPropertyName().equals("value")) + spinner.getModel().setValue(event.getNewValue()); + } } /** - * DOCUMENT ME! + * Receives notification of changes in the state of the {@link JSpinner} + * that the editor belongs to - the content of the text field is updated + * accordingly. * - * @param event DOCUMENT ME! + * @param event the change event. */ public void stateChanged(ChangeEvent event) { - // TODO: Implement this properly. + ftf.setValue(spinner.getValue()); } + /** + * This method does nothing. It is required by the {@link LayoutManager} + * interface, but since this component has a single child, there is no + * need to use this method. + * + * @param child the child component to remove. + */ public void removeLayoutComponent(Component child) { // Nothing to do here. } /** - * DOCUMENT ME! - * - * @param name DOCUMENT ME! - * @param child DOCUMENT ME! + * This method does nothing. It is required by the {@link LayoutManager} + * interface, but since this component has a single child, there is no + * need to use this method. + * + * @param name the name. + * @param child the child component to add. */ public void addLayoutComponent(String name, Component child) { @@ -215,7 +253,11 @@ public class JSpinner extends JComponent } /** - * DOCUMENT ME! + * A panel containing a {@link JFormattedTextField} that is configured for + * displaying and editing numbers. The panel is used as a subcomponent of + * a {@link JSpinner}. + * + * @see JSpinner#createEditor(SpinnerModel) */ public static class NumberEditor extends DefaultEditor { @@ -225,40 +267,72 @@ public class JSpinner extends JComponent private static final long serialVersionUID = 3791956183098282942L; /** - * Creates a new NumberEditor object. + * Creates a new NumberEditor object for the specified + * spinner. The editor is registered with the spinner as a + * {@link ChangeListener}. * - * @param spinner DOCUMENT ME! + * @param spinner the component the editor will be used with. */ public NumberEditor(JSpinner spinner) { super(spinner); + NumberEditorFormatter nef = new NumberEditorFormatter(); + nef.setMinimum(getModel().getMinimum()); + nef.setMaximum(getModel().getMaximum()); + ftf.setFormatterFactory(new DefaultFormatterFactory(nef)); } /** - * Creates a new NumberEditor object. + * Creates a new NumberEditor object. * - * @param spinner DOCUMENT ME! + * @param spinner the spinner. + * @param decimalFormatPattern the number format pattern. */ public NumberEditor(JSpinner spinner, String decimalFormatPattern) { super(spinner); + NumberEditorFormatter nef + = new NumberEditorFormatter(decimalFormatPattern); + nef.setMinimum(getModel().getMinimum()); + nef.setMaximum(getModel().getMaximum()); + ftf.setFormatterFactory(new DefaultFormatterFactory(nef)); } /** - * DOCUMENT ME! + * Returns the format used by the text field. * - * @return DOCUMENT ME! + * @return The format used by the text field. */ public DecimalFormat getFormat() { - return null; + NumberFormatter formatter = (NumberFormatter) ftf.getFormatter(); + return (DecimalFormat) formatter.getFormat(); } + /** + * Returns the model used by the editor's {@link JSpinner} component, + * cast to a {@link SpinnerNumberModel}. + * + * @return The model. + */ public SpinnerNumberModel getModel() { return (SpinnerNumberModel) getSpinner().getModel(); } } + + static class NumberEditorFormatter + extends NumberFormatter + { + public NumberEditorFormatter() + { + super(NumberFormat.getInstance()); + } + public NumberEditorFormatter(String decimalFormatPattern) + { + super(new DecimalFormat(decimalFormatPattern)); + } + } /** * A JSpinner editor used for the {@link SpinnerListModel}. @@ -279,6 +353,11 @@ public class JSpinner extends JComponent super(spinner); } + /** + * Returns the spinner's model cast as a {@link SpinnerListModel}. + * + * @return The spinner's model. + */ public SpinnerListModel getModel() { return (SpinnerListModel) getSpinner().getModel(); @@ -299,9 +378,6 @@ public class JSpinner extends JComponent /** The serialVersionUID. */ private static final long serialVersionUID = -4279356973770397815L; - /** The DateFormat instance used to format the date. */ - SimpleDateFormat dateFormat; - /** * Creates a new instance of DateEditor for the specified * JSpinner. @@ -312,7 +388,10 @@ public class JSpinner extends JComponent public DateEditor(JSpinner spinner) { super(spinner); - init(new SimpleDateFormat()); + DateEditorFormatter nef = new DateEditorFormatter(); + nef.setMinimum(getModel().getStart()); + nef.setMaximum(getModel().getEnd()); + ftf.setFormatterFactory(new DefaultFormatterFactory(nef)); } /** @@ -329,26 +408,10 @@ public class JSpinner extends JComponent public DateEditor(JSpinner spinner, String dateFormatPattern) { super(spinner); - init(new SimpleDateFormat(dateFormatPattern)); - } - - /** - * Initializes the JFormattedTextField for this editor. - * - * @param format the date format to use in the formatted text field - */ - private void init(SimpleDateFormat format) - { - dateFormat = format; - getTextField().setFormatterFactory( - new JFormattedTextField.AbstractFormatterFactory() - { - public JFormattedTextField.AbstractFormatter - getFormatter(JFormattedTextField ftf) - { - return new DateFormatter(dateFormat); - } - }); + DateEditorFormatter nef = new DateEditorFormatter(dateFormatPattern); + nef.setMinimum(getModel().getStart()); + nef.setMaximum(getModel().getEnd()); + ftf.setFormatterFactory(new DefaultFormatterFactory(nef)); } /** @@ -360,7 +423,8 @@ public class JSpinner extends JComponent */ public SimpleDateFormat getFormat() { - return dateFormat; + DateFormatter formatter = (DateFormatter) ftf.getFormatter(); + return (SimpleDateFormat) formatter.getFormat(); } /** @@ -374,25 +438,59 @@ public class JSpinner extends JComponent } } - private static final long serialVersionUID = 3412663575706551720L; + static class DateEditorFormatter + extends DateFormatter + { + public DateEditorFormatter() + { + super(DateFormat.getInstance()); + } + public DateEditorFormatter(String dateFormatPattern) + { + super(new SimpleDateFormat(dateFormatPattern)); + } + } + + /** + * A listener that forwards {@link ChangeEvent} notifications from the model + * to the {@link JSpinner}'s listeners. + */ + class ModelListener implements ChangeListener + { + /** + * Creates a new listener. + */ + public ModelListener() + { + // nothing to do here + } + + /** + * Receives notification from the model that its state has changed. + * + * @param event the event (ignored). + */ + public void stateChanged(ChangeEvent event) + { + fireStateChanged(); + } + } - /** DOCUMENT ME! */ + /** + * The model that defines the current value and permitted values for the + * spinner. + */ private SpinnerModel model; - /** DOCUMENT ME! */ + /** The current editor. */ private JComponent editor; - /** DOCUMENT ME! */ - private ChangeListener listener = new ChangeListener() - { - public void stateChanged(ChangeEvent evt) - { - fireStateChanged(); - } - }; + private static final long serialVersionUID = 3412663575706551720L; /** - * Creates a JSpinner with SpinnerNumberModel + * Creates a new JSpinner with default instance of + * {@link SpinnerNumberModel} (that is, a model with value 0, step size 1, + * and no upper or lower limit). * * @see javax.swing.SpinnerNumberModel */ @@ -402,15 +500,19 @@ public class JSpinner extends JComponent } /** - * Creates a JSpinner with the specific model and sets the default editor + * Creates a new JSpinner with the specified model. The + * {@link #createEditor(SpinnerModel)} method is used to create an editor + * that is suitable for the model. * - * @param model DOCUMENT ME! + * @param model the model (null not permitted). + * + * @throws NullPointerException if model is null. */ public JSpinner(SpinnerModel model) { this.model = model; - model.addChangeListener(listener); - setEditor(createEditor(model)); + this.editor = createEditor(model); + model.addChangeListener(new ModelListener()); updateUI(); } @@ -439,12 +541,13 @@ public class JSpinner extends JComponent } /** - * Changes the current editor to the new editor. This methods should remove - * the old listeners (if any) and adds the new listeners (if any). + * Changes the current editor to the new editor. The old editor is + * removed from the spinner's {@link ChangeEvent} list. * - * @param editor the new editor + * @param editor the new editor (null not permitted. * - * @throws IllegalArgumentException DOCUMENT ME! + * @throws IllegalArgumentException if editor is + * null. * * @see #getEditor */ @@ -453,21 +556,22 @@ public class JSpinner extends JComponent if (editor == null) throw new IllegalArgumentException("editor may not be null"); - if (this.editor instanceof DefaultEditor) - ((DefaultEditor) editor).dismiss(this); - else if (this.editor instanceof ChangeListener) - removeChangeListener((ChangeListener) this.editor); - - if (editor instanceof ChangeListener) - addChangeListener((ChangeListener) editor); - + JComponent oldEditor = this.editor; + if (oldEditor instanceof DefaultEditor) + ((DefaultEditor) oldEditor).dismiss(this); + else if (oldEditor instanceof ChangeListener) + removeChangeListener((ChangeListener) oldEditor); + this.editor = editor; + firePropertyChange("editor", oldEditor, editor); } /** - * Gets the underly model. + * Returns the model used by the {@link JSpinner} component. * - * @return the underly model + * @return The model. + * + * @see #setModel(SpinnerModel) */ public SpinnerModel getModel() { @@ -492,9 +596,7 @@ public class JSpinner extends JComponent SpinnerModel oldModel = model; model = newModel; firePropertyChange("model", oldModel, newModel); - - if (editor == null) - setEditor(createEditor(model)); + setEditor(createEditor(model)); } /** @@ -545,9 +647,9 @@ public class JSpinner extends JComponent } /** - * DOCUMENT ME! + * Sets the value in the model. * - * @param value DOCUMENT ME! + * @param value the new value. */ public void setValue(Object value) { @@ -555,10 +657,10 @@ public class JSpinner extends JComponent } /** - * This method returns a name to identify which look and feel class will be + * Returns the ID that identifies which look and feel class will be * the UI delegate for this spinner. * - * @return The UIClass identifier. "SpinnerUI" + * @return "SpinnerUI". */ public String getUIClassID() { @@ -575,7 +677,7 @@ public class JSpinner extends JComponent } /** - * This method sets the spinner's UI delegate. + * Sets the UI delegate for the component. * * @param ui The spinner's UI delegate. */ @@ -628,14 +730,11 @@ public class JSpinner extends JComponent } /** - * Creates an editor for this JSpinner. Really, it should be a - * JSpinner.DefaultEditor, but since that should be - * implemented by a JFormattedTextField, and one is not written, I am just - * using a dummy one backed by a JLabel. + * Creates an editor that is appropriate for the specified model. * - * @param model DOCUMENT ME! + * @param model the model. * - * @return the default editor + * @return The editor. */ protected JComponent createEditor(SpinnerModel model) { @@ -643,6 +742,8 @@ public class JSpinner extends JComponent return new DateEditor(this); else if (model instanceof SpinnerNumberModel) return new NumberEditor(this); + else if (model instanceof SpinnerListModel) + return new ListEditor(this); else return new DefaultEditor(this); } diff --git a/libjava/classpath/javax/swing/JSplitPane.java b/libjava/classpath/javax/swing/JSplitPane.java index 70feefa..dc75dfe 100644 --- a/libjava/classpath/javax/swing/JSplitPane.java +++ b/libjava/classpath/javax/swing/JSplitPane.java @@ -343,10 +343,13 @@ public class JSplitPane extends JComponent implements Accessible throw new IllegalArgumentException("Constraints is not a known identifier."); + // If no dividerLocation has been set, then we need to trigger an + // initial layout. + if (getDividerLocation() != -1) + resetToPreferredSizes(); + super.addImpl(comp, constraints, index); } - invalidate(); - layout(); } /** diff --git a/libjava/classpath/javax/swing/JTabbedPane.java b/libjava/classpath/javax/swing/JTabbedPane.java index 8a7d4c0..3c91a5e 100644 --- a/libjava/classpath/javax/swing/JTabbedPane.java +++ b/libjava/classpath/javax/swing/JTabbedPane.java @@ -44,12 +44,14 @@ import java.awt.Point; import java.awt.Rectangle; import java.awt.event.MouseEvent; import java.io.Serializable; +import java.util.Locale; import java.util.Vector; import javax.accessibility.Accessible; import javax.accessibility.AccessibleContext; import javax.accessibility.AccessibleRole; import javax.accessibility.AccessibleSelection; +import javax.accessibility.AccessibleStateSet; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.plaf.TabbedPaneUI; @@ -136,7 +138,12 @@ public class JTabbedPane extends JComponent implements Serializable, */ public Accessible getAccessibleChild(int i) { - return null; + // Testing shows that the reference implementation returns instances + // of page here. + Accessible child = null; + if (i >= 0 && i < tabs.size()) + child = (Page) tabs.get(i); + return child; } /** @@ -273,6 +280,8 @@ public class JTabbedPane extends JComponent implements Serializable, * A private class that holds all the information for each tab. */ private class Page + extends AccessibleContext + implements Accessible { /** The tooltip string. */ private String tip; @@ -553,6 +562,74 @@ public class JTabbedPane extends JComponent implements Serializable, underlinedChar = index; } + + /** + * Returns the accessible context, which is this object itself. + * + * @return the accessible context, which is this object itself + */ + public AccessibleContext getAccessibleContext() + { + return this; + } + + /** + * Returns the accessible role of this tab, which is always + * {@link AccessibleRole#PAGE_TAB}. + * + * @return the accessible role of this tab + */ + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.PAGE_TAB; + } + + public AccessibleStateSet getAccessibleStateSet() + { + // FIXME: Implement this properly. + return null; + } + + public int getAccessibleIndexInParent() + { + // FIXME: Implement this properly. + return 0; + } + + /** + * Returns the number of accessible children, which is always one (the + * component of this tab). + * + * @return the number of accessible children + */ + public int getAccessibleChildrenCount() + { + return 1; + } + + /** + * Returns the accessible child of this tab, which is the component + * displayed by the tab. + * + * @return the accessible child of this tab + */ + public Accessible getAccessibleChild(int i) + { + // A quick test shows that this method always returns the component + // displayed by the tab, regardless of the index. + return (Accessible) component; + } + + /** + * Returns the locale of this accessible object. + * + * @return the locale of this accessible object + */ + public Locale getLocale() + { + // TODO: Is this ok? + return Locale.getDefault(); + } } private static final long serialVersionUID = 1614381073220130939L; @@ -1088,7 +1165,7 @@ public class JTabbedPane extends JComponent implements Serializable, */ public void remove(int index) { - remove(getComponentAt(index)); + super.remove(index); removeTabAt(index); } diff --git a/libjava/classpath/javax/swing/JTable.java b/libjava/classpath/javax/swing/JTable.java index 0875306..fbf7493 100644 --- a/libjava/classpath/javax/swing/JTable.java +++ b/libjava/classpath/javax/swing/JTable.java @@ -1,5 +1,5 @@ /* JTable.java -- - Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -46,8 +46,6 @@ import java.awt.Font; import java.awt.FontMetrics; import java.awt.Point; import java.awt.Rectangle; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.awt.event.FocusListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; @@ -86,8 +84,16 @@ import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; import javax.swing.table.TableModel; -import javax.swing.text.Caret; +/** + * The table component, displaying information, organized in rows and columns. + * The table can be placed in the scroll bar and have the optional header + * that is always visible. Cell values may be editable after double clicking + * on the cell. Cell columns may have various data types, that are + * displayed and edited by the different renderers and editors. It is possible + * to set different column width. The columns are also resizeable by + * dragging the column boundary in the header. + */ public class JTable extends JComponent implements TableModelListener, Scrollable, TableColumnModelListener, @@ -588,7 +594,7 @@ public class JTable return lastColumn; } } - + /** * Creates a new AccessibleJTable. * @@ -979,9 +985,9 @@ public class JTable class TableColumnPropertyChangeHandler implements PropertyChangeListener { /** - * Receives notification that a property of the observed TableColumns - * has changed. - * + * Receives notification that a property of the observed TableColumns has + * changed. + * * @param ev the property change event */ public void propertyChange(PropertyChangeEvent ev) @@ -989,13 +995,15 @@ public class JTable if (ev.getPropertyName().equals("preferredWidth")) { JTableHeader header = getTableHeader(); - if (header != null) - { - TableColumn col = (TableColumn) ev.getSource(); - header.setResizingColumn(col); - doLayout(); - header.setResizingColumn(null); - } + if (header != null) + // Do nothing if the table is in the resizing mode. + if (header.getResizingColumn() == null) + { + TableColumn col = (TableColumn) ev.getSource(); + header.setResizingColumn(col); + doLayout(); + header.setResizingColumn(null); + } } } } @@ -1006,11 +1014,30 @@ public class JTable private class BooleanCellRenderer extends DefaultTableCellRenderer { - /** * The CheckBox that is used for rendering. */ - private JCheckBox checkBox = new JCheckBox(); + private final JCheckBox checkBox = new JCheckBox(); + + /** + * The check box must have the text field background and be centered. + */ + private BooleanCellRenderer() + { + // Render the checkbox identically as the text field. + JTextField f = new JTextField(); + checkBox.setForeground(f.getForeground()); + checkBox.setBackground(f.getBackground()); + checkBox.setHorizontalAlignment(SwingConstants.CENTER); + } + + /** + * Get the check box. + */ + JCheckBox getCheckBox() + { + return checkBox; + } /** * Returns the component that is used for rendering the value. @@ -1029,8 +1056,14 @@ public class JTable boolean hasFocus, int row, int column) { - Boolean boolValue = (Boolean) value; - checkBox.setSelected(boolValue.booleanValue()); + // Null is rendered as false. + if (value == null) + checkBox.setSelected(false); + else + { + Boolean boolValue = (Boolean) value; + checkBox.setSelected(boolValue.booleanValue()); + } return checkBox; } } @@ -1200,12 +1233,52 @@ public class JTable { Icon iconValue = (Icon) value; setIcon(iconValue); + setText(""); } return this; } } + + /** + * The JTable text component (used in editing) always has the table + * as its parent. The scrollRectToVisible must be adjusted taking the + * relative component position. + * + * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) + */ + private class TableTextField extends JTextField + { + /** + * Create the text field without the border. + */ + TableTextField() + { + setBorder(null); + } + + /** + * Scroll the table, making the given rectangle of this component + * visible. Mind the component position with relate to the table. + * With not this method overridden, the scroll pane scrolls to the + * top left cornec (untranslated position of the caret) after the first + * keystroke. + */ + public void scrollRectToVisible(Rectangle r) + { + // In private class we known that the rectangle data will not be + // reused and we need not to clone it. + r.translate(getX(), getY()); + super.scrollRectToVisible(r); + } + } + private static final long serialVersionUID = 3876025080382781659L; + + /** + * This table, for referring identically name methods from inner classes. + */ + final JTable this_table = this; /** @@ -1343,7 +1416,7 @@ public class JTable protected boolean rowSelectionAllowed; /** - * @deprecated Use {@link #rowSelectionAllowed}, {@link + * Obsolete. Use {@link #rowSelectionAllowed}, {@link * #getColumnSelectionAllowed}, or the combined methods {@link * #getCellSelectionEnabled} and {@link #setCellSelectionEnabled(boolean)}. */ @@ -1477,27 +1550,6 @@ public class JTable protected JTableHeader tableHeader; /** - * The row of the cell being edited. - */ - int rowBeingEdited = -1; - - /** - * The column of the cell being edited. - */ - int columnBeingEdited = -1; - - /** - * The action listener for the editor's Timer. - */ - Timer editorTimer = new EditorUpdateTimer(); - - /** - * Stores the old value of a cell before it was edited, in case - * editing is cancelled - */ - Object oldCellValue; - - /** * The property handler for this table's columns. */ TableColumnPropertyChangeHandler tableColumnPropertyChangeHandler = @@ -1510,6 +1562,11 @@ public class JTable private boolean surrendersFocusOnKeystroke = false; /** + * A Rectangle object to be reused in {@link #getCellRect}. + */ + private Rectangle rectCache = new Rectangle(); + + /** * Creates a new JTable instance. */ public JTable () @@ -1518,7 +1575,8 @@ public class JTable } /** - * Creates a new JTable instance. + * Creates a new JTable instance with the given number + * of rows and columns. * * @param numRows an int value * @param numColumns an int value @@ -1529,10 +1587,12 @@ public class JTable } /** - * Creates a new JTable instance. + * Creates a new JTable instance, storing the given data + * array and heaving the given column names. To see the column names, + * you must place the JTable into the {@link JScrollPane}. * - * @param data an Object[][] value - * @param columnNames an Object[] value + * @param data an Object[][] the table data + * @param columnNames an Object[] the column headers */ public JTable(Object[][] data, Object[] columnNames) { @@ -1540,20 +1600,31 @@ public class JTable } /** - * Creates a new JTable instance. - * - * @param dm a TableModel value + * Creates a new JTable instance, using the given data model + * object that provides information about the table content. The table model + * object is asked for the table size, other features and also receives + * notifications in the case when the table has been edited by the user. + * + * @param model + * the table model. */ - public JTable (TableModel dm) + public JTable (TableModel model) { - this(dm, null, null); + this(model, null, null); } /** - * Creates a new JTable instance. - * - * @param dm a TableModel value - * @param cm a TableColumnModel value + * Creates a new JTable instance, using the given model object + * that provides information about the table content. The table data model + * object is asked for the table size, other features and also receives + * notifications in the case when the table has been edited by the user. The + * table column model provides more detailed control on the table column + * related features. + * + * @param dm + * the table data mode + * @param cm + * the table column model */ public JTable (TableModel dm, TableColumnModel cm) { @@ -1561,11 +1632,13 @@ public class JTable } /** - * Creates a new JTable instance. + * Creates a new JTable instance, providing data model, + * column model and list selection model. The list selection model + * manages the selections. * - * @param dm a TableModel value - * @param cm a TableColumnModel value - * @param sm a ListSelectionModel value + * @param dm data model (manages table data) + * @param cm column model (manages table columns) + * @param sm list selection model (manages table selections) */ public JTable (TableModel dm, TableColumnModel cm, ListSelectionModel sm) { @@ -1593,8 +1666,23 @@ public class JTable columnModel.getSelectionModel().setAnchorSelectionIndex(0); columnModel.getSelectionModel().setLeadSelectionIndex(0); updateUI(); - } - + } + + /** + * Creates a new JTable instance that uses data and column + * names, stored in {@link Vector}s. + * + * @param data the table data + * @param columnNames the table column names. + */ + public JTable(Vector data, Vector columnNames) + { + this(new DefaultTableModel(data, columnNames)); + } + + /** + * Initialize local variables to default values. + */ protected void initializeLocalVars() { setTableHeader(createDefaultTableHeader()); @@ -1623,63 +1711,18 @@ public class JTable this.editingRow = -1; setIntercellSpacing(new Dimension(1,1)); } - - /** - * Creates a new JTable instance. - * - * @param data a Vector value - * @param columnNames a Vector value - */ - public JTable(Vector data, Vector columnNames) - { - this(new DefaultTableModel(data, columnNames)); - } - + /** - * The timer that updates the editor component. + * Add the new table column. The table column class allows to specify column + * features more precisely, setting the preferred width, column data type + * (column class) and table headers. + * + * There is no need the add columns to the table if the default column + * handling is sufficient. + * + * @param column + * the new column to add. */ - private class EditorUpdateTimer - extends Timer - implements ActionListener - { - /** - * Creates a new EditorUpdateTimer object with a default delay of 0.5 seconds. - */ - public EditorUpdateTimer() - { - super(500, null); - addActionListener(this); - } - - /** - * Lets the caret blink and repaints the table. - */ - public void actionPerformed(ActionEvent ev) - { - Caret c = ((JTextField)JTable.this.editorComp).getCaret(); - if (c != null) - c.setVisible(!c.isVisible()); - JTable.this.repaint(); - } - - /** - * Updates the blink delay according to the current caret. - */ - public void update() - { - stop(); - Caret c = ((JTextField)JTable.this.editorComp).getCaret(); - if (c != null) - { - setDelay(c.getBlinkRate()); - if (((JTextField)JTable.this.editorComp).isEditable()) - start(); - else - c.setVisible(false); - } - } - } - public void addColumn(TableColumn column) { if (column.getHeaderValue() == null) @@ -1691,12 +1734,24 @@ public class JTable columnModel.addColumn(column); column.addPropertyChangeListener(tableColumnPropertyChangeHandler); } - + + /** + * Create the default editors for this table. The default method creates + * the editor for Booleans. + * + * Other fields are edited as strings at the moment. + */ protected void createDefaultEditors() { - //FIXME: Create the editor object. + JCheckBox box = new BooleanCellRenderer().getCheckBox(); + setDefaultEditor(Boolean.class, new DefaultCellEditor(box)); } - + + /** + * Create the default renderers for this table. The default method creates + * renderers for Boolean, Number, Double, Date, Icon and ImageIcon. + * + */ protected void createDefaultRenderers() { setDefaultRenderer(Boolean.class, new BooleanCellRenderer()); @@ -1705,6 +1760,7 @@ public class JTable setDefaultRenderer(Double.class, new FloatCellRenderer()); setDefaultRenderer(Date.class, new DateCellRenderer()); setDefaultRenderer(Icon.class, new IconCellRenderer()); + setDefaultRenderer(ImageIcon.class, new IconCellRenderer()); } /** @@ -1714,112 +1770,148 @@ public class JTable { return new JScrollPane(table); } - + + /** + * Create the default table column model that is used if the user-defined + * column model is not provided. The default method creates + * {@link DefaultTableColumnModel}. + * + * @return the created table column model. + */ protected TableColumnModel createDefaultColumnModel() { return new DefaultTableColumnModel(); } + /** + * Create the default table data model that is used if the user-defined + * data model is not provided. The default method creates + * {@link DefaultTableModel}. + * + * @return the created table data model. + */ protected TableModel createDefaultDataModel() { return new DefaultTableModel(); } + /** + * Create the default table selection model that is used if the user-defined + * selection model is not provided. The default method creates + * {@link DefaultListSelectionModel}. + * + * @return the created table data model. + */ protected ListSelectionModel createDefaultSelectionModel() { return new DefaultListSelectionModel(); } - + + /** + * Create the default table header, if the user - defined table header is not + * provided. + * + * @return the default table header. + */ protected JTableHeader createDefaultTableHeader() { return new JTableHeader(columnModel); } - - // listener support - + + /** + * Invoked when the column is added. Revalidates and repains the table. + */ public void columnAdded (TableColumnModelEvent event) { revalidate(); repaint(); } + /** + * Invoked when the column margin is changed. + * Revalidates and repains the table. + */ public void columnMarginChanged (ChangeEvent event) { revalidate(); repaint(); } + /** + * Invoked when the column is moved. Revalidates and repains the table. + */ public void columnMoved (TableColumnModelEvent event) { revalidate(); repaint(); } + /** + * Invoked when the column is removed. Revalidates and repains the table. + */ public void columnRemoved (TableColumnModelEvent event) { revalidate(); repaint(); } + /** + * Invoked when the the column selection changes. + */ public void columnSelectionChanged (ListSelectionEvent event) { repaint(); } - + + /** + * Invoked when the editing is cancelled. + */ public void editingCanceled (ChangeEvent event) { - if (rowBeingEdited > -1 && columnBeingEdited > -1) + if (editorComp!=null) { - if (getValueAt(rowBeingEdited, columnBeingEdited) instanceof JTextField) - { - remove ((Component)getValueAt(rowBeingEdited, columnBeingEdited)); - setValueAt(oldCellValue, rowBeingEdited, columnBeingEdited); - } - rowBeingEdited = -1; - columnBeingEdited = -1; + remove(editorComp); + repaint(editorComp.getBounds()); + editorComp = null; } - editorTimer.stop(); - editorComp = null; - cellEditor = null; - requestFocusInWindow(false); - repaint(); } - + + /** + * Finish the current editing session and update the table with the + * new value by calling {@link #setValueAt}. + * + * @param event the change event + */ public void editingStopped (ChangeEvent event) { - if (rowBeingEdited > -1 && columnBeingEdited > -1) + if (editorComp!=null) { - if (getValueAt(rowBeingEdited, columnBeingEdited) instanceof JTextField) - { - remove((Component)getValueAt(rowBeingEdited, columnBeingEdited)); - setValueAt(((JTextField)editorComp).getText(), - rowBeingEdited, columnBeingEdited); - } - rowBeingEdited = -1; - columnBeingEdited = -1; + remove(editorComp); + setValueAt(cellEditor.getCellEditorValue(), editingRow, editingColumn); + repaint(editorComp.getBounds()); + editorComp = null; } - editorTimer.stop(); - editorComp = null; - cellEditor = null; - requestFocusInWindow(false); - repaint(); + requestFocusInWindow(); } + /** + * Invoked when the table changes. + * null means everything changed. + */ public void tableChanged (TableModelEvent event) { // update the column model from the table model if the structure has // changed and the flag autoCreateColumnsFromModel is set - if ((event.getFirstRow() ==TableModelEvent.HEADER_ROW) - && autoCreateColumnsFromModel) - + if ((event == null || (event.getFirstRow() == TableModelEvent.HEADER_ROW)) + && autoCreateColumnsFromModel) createDefaultColumnsFromModel(); // If the structure changes, we need to revalidate, since that might // affect the size parameters of the JTable. Otherwise we only need // to perform a repaint to update the view. - if (event.getType() == TableModelEvent.INSERT) + if (event == null || event.getType() == TableModelEvent.INSERT) revalidate(); - else if (event.getType() == TableModelEvent.DELETE) + if (event == null || event.getType() == TableModelEvent.DELETE) { if (dataModel.getRowCount() == 0) clearSelection(); @@ -1828,6 +1920,9 @@ public class JTable repaint(); } + /** + * Invoked when another table row is selected. + */ public void valueChanged (ListSelectionEvent event) { repaint(); @@ -1863,29 +1958,30 @@ public class JTable } /** - * Returns index of the row that contains specified point or - * -1 if this table doesn't contain this point. - * - * @param point point to identify the row - * @return index of the row that contains specified point or - * -1 if this table doesn't contain this point. + * Returns index of the row that contains specified point or -1 if this table + * doesn't contain this point. + * + * @param point + * point to identify the row + * @return index of the row that contains specified point or -1 if this table + * doesn't contain this point. */ public int rowAtPoint(Point point) { if (point != null) { int nrows = getRowCount(); - int height = getRowHeight(); + int height = getRowHeight() + getRowMargin(); int y = point.y; - for (int i = 0; i < nrows; ++i) - { - if (0 <= y && y < height) - return i; - y -= height; - } + int r = y / height; + if (r < 0 || r >= nrows) + return -1; + else + return r; } - return -1; + else + return -1; } /** @@ -1908,6 +2004,9 @@ public class JTable int column, boolean includeSpacing) { + // moveToCellBeingEdited expects the cached value and clones it. + // If the caching would be removed later, uplate moveToCellBeingEdited + // as well. int height = getRowHeight(row); int width = columnModel.getColumn(column).getWidth(); int x_gap = columnModel.getColumnMargin(); @@ -1923,9 +2022,10 @@ public class JTable x += columnModel.getColumn(i).getWidth(); if (includeSpacing) - return new Rectangle(x, y, width, height); + rectCache.setBounds(x, y, width, height +y_gap); else - return new Rectangle(x, y, width - x_gap, height - y_gap); + rectCache.setBounds(x, y, width - x_gap, height); + return rectCache; } public void clearSelection() @@ -2008,44 +2108,88 @@ public class JTable } + /** + * Get the cell editor, suitable for editing the given cell. The default + * method requests the editor from the column model. If the column model does + * not provide the editor, the call is forwarded to the + * {@link #getDefaultEditor(Class)} with the parameter, obtained from + * {@link TableModel#getColumnClass(int)}. + * + * @param row the cell row + * @param column the cell column + * @return the editor to edit that cell + */ public TableCellEditor getCellEditor(int row, int column) { TableCellEditor editor = columnModel.getColumn(column).getCellEditor(); if (editor == null) - editor = getDefaultEditor(dataModel.getColumnClass(column)); - + { + int mcolumn = convertColumnIndexToModel(column); + editor = getDefaultEditor(dataModel.getColumnClass(mcolumn)); + } + return editor; } - + + /** + * Get the default editor for editing values of the given type + * (String, Boolean and so on). + * + * @param columnClass the class of the value that will be edited. + * + * @return the editor, suitable for editing this data type + */ public TableCellEditor getDefaultEditor(Class columnClass) { if (defaultEditorsByColumnClass.containsKey(columnClass)) return (TableCellEditor) defaultEditorsByColumnClass.get(columnClass); else { - // FIXME: We have at least an editor for Object.class in our defaults. - TableCellEditor r = new DefaultCellEditor(new JTextField()); + JTextField t = new TableTextField(); + TableCellEditor r = new DefaultCellEditor(t); defaultEditorsByColumnClass.put(columnClass, r); return r; } } - + + /** + * Get the cell renderer for rendering the given cell. + * + * @param row the cell row + * @param column the cell column + * @return the cell renderer to render that cell. + */ public TableCellRenderer getCellRenderer(int row, int column) { - TableCellRenderer renderer = - columnModel.getColumn(column).getCellRenderer(); + TableCellRenderer renderer = columnModel.getColumn(column).getCellRenderer(); if (renderer == null) - renderer = getDefaultRenderer(getColumnClass(column)); - + { + int mcolumn = convertColumnIndexToModel(column); + renderer = getDefaultRenderer(dataModel.getColumnClass(mcolumn)); + } return renderer; } - + + /** + * Set default renderer for rendering the given data type. + * + * @param columnClass the data type (String, Boolean and so on) that must be + * rendered. + * @param rend the renderer that will rend this data type + */ public void setDefaultRenderer(Class columnClass, TableCellRenderer rend) { defaultRenderersByColumnClass.put(columnClass, rend); } - + + /** + * Get the default renderer for rendering the given data type. + * + * @param columnClass the data that must be rendered + * + * @return the appropriate defauld renderer for rendering that data type. + */ public TableCellRenderer getDefaultRenderer(Class columnClass) { if (defaultRenderersByColumnClass.containsKey(columnClass)) @@ -2057,7 +2201,19 @@ public class JTable return r; } } - + + /** + * Convert the table model index into the table column number. + * The model number need not match the real column position. The columns + * may be rearranged by the user with mouse at any time by dragging the + * column headers. + * + * @param vc the column number (0=first). + * + * @return the table column model index of this column. + * + * @see TableColumn#getModelIndex() + */ public int convertColumnIndexToModel(int vc) { if (vc < 0) @@ -2065,7 +2221,19 @@ public class JTable else return columnModel.getColumn(vc).getModelIndex(); } - + + /** + * Convert the table column number to the table column model index. + * The model number need not match the real column position. The columns + * may be rearranged by the user with mouse at any time by dragging the + * column headers. + * + * @param mc the table column index (0=first). + * + * @return the table column number in the model + * + * @see TableColumn#getModelIndex() + */ public int convertColumnIndexToView(int mc) { if (mc < 0) @@ -2078,7 +2246,16 @@ public class JTable } return -1; } - + + /** + * Prepare the renderer for rendering the given cell. + * + * @param renderer the renderer being prepared + * @param row the row of the cell being rendered + * @param column the column of the cell being rendered + * + * @return the component which .paint() method will paint the cell. + */ public Component prepareRenderer(TableCellRenderer renderer, int row, int column) @@ -2640,8 +2817,13 @@ public class JTable if (dataModel != null && columnModel != null) { int ncols = getColumnCount(); + TableColumn column; for (int i = 0; i < ncols; ++i) - columnModel.getColumn(i).setHeaderValue(dataModel.getColumnName(i)); + { + column = columnModel.getColumn(i); + if (column.getHeaderValue()==null) + column.setHeaderValue(dataModel.getColumnName(i)); + } } // according to Sun's spec we also have to set the tableHeader's @@ -2899,10 +3081,36 @@ public class JTable for (int i = 0; i < cols.length; i++) { if (cols[i] != null) - cols[i].setWidth(cols[i].getWidth() + average); + cols[i].setWidth(cols[i].getPreferredWidth() + average); } } - + + /** + * This distributes the superfluous width in a table, setting the width of the + * column being resized strictly to its preferred width. + */ + private void distributeSpillResizing(TableColumn[] cols, int spill, + TableColumn resizeIt) + { + int average = 0; + if (cols.length != 1) + average = spill / (cols.length-1); + for (int i = 0; i < cols.length; i++) + { + if (cols[i] != null && !cols[i].equals(resizeIt)) + cols[i].setWidth(cols[i].getPreferredWidth() + average); + } + resizeIt.setWidth(resizeIt.getPreferredWidth()); + } + + /** + * Set the widths of all columns, taking they preferred widths into + * consideration. The excess space, if any, will be distrubuted between + * all columns. This method also handles special cases when one of the + * collumns is currently being resized. + * + * @see TableColumn#setPreferredWidth(int) + */ public void doLayout() { TableColumn resizingColumn = null; @@ -2911,7 +3119,6 @@ public class JTable if (ncols < 1) return; - int[] pref = new int[ncols]; int prefSum = 0; int rCol = -1; @@ -2921,8 +3128,7 @@ public class JTable for (int i = 0; i < ncols; ++i) { TableColumn col = columnModel.getColumn(i); - int p = col.getWidth(); - pref[i] = p; + int p = col.getPreferredWidth(); prefSum += p; if (resizingColumn == col) rCol = i; @@ -2951,14 +3157,38 @@ public class JTable cols = new TableColumn[ncols]; for (int i = 0; i < ncols; ++i) cols[i] = columnModel.getColumn(i); - distributeSpill(cols, spill); + distributeSpillResizing(cols, spill, resizingColumn); break; case AUTO_RESIZE_SUBSEQUENT_COLUMNS: - cols = new TableColumn[ncols]; - for (int i = rCol; i < ncols; ++i) - cols[i] = columnModel.getColumn(i); - distributeSpill(cols, spill); + + // Subtract the width of the non-resized columns from the spill. + int w = 0; + int wp = 0; + TableColumn column; + for (int i = 0; i < rCol; i++) + { + column = columnModel.getColumn(i); + w += column.getWidth(); + wp+= column.getPreferredWidth(); + } + + // The number of columns right from the column being resized. + int n = ncols-rCol-1; + if (n>0) + { + // If there are any columns on the right sied to resize. + spill = (getWidth()-w) - (prefSum-wp); + int average = spill / n; + + // For all columns right from the column being resized: + for (int i = rCol+1; i < ncols; i++) + { + column = columnModel.getColumn(i); + column.setWidth(column.getPreferredWidth() + average); + } + } + resizingColumn.setWidth(resizingColumn.getPreferredWidth()); break; case AUTO_RESIZE_OFF: @@ -2974,6 +3204,16 @@ public class JTable cols[i] = columnModel.getColumn(i); distributeSpill(cols, spill); } + + if (editorComp!=null) + moveToCellBeingEdited(editorComp); + + // Repaint fixes the invalid view after the first keystroke if the cell + // editing is started immediately after the program start or cell + // resizing. + repaint(); + if (tableHeader!=null) + tableHeader.repaint(); } /** @@ -2983,7 +3223,7 @@ public class JTable { doLayout(); } - + /** * Obsolete since JDK 1.4. Please use doLayout(). */ @@ -3023,48 +3263,109 @@ public class JTable revalidate(); repaint(); } - + + /** + * Get the class (datatype) of the column. The cells are rendered and edited + * differently, depending from they data type. + * + * @param column the column (not the model index). + * + * @return the class, defining data type of that column (String.class for + * String, Boolean.class for boolean and so on). + */ public Class getColumnClass(int column) { - return getModel().getColumnClass(column); + return getModel().getColumnClass(convertColumnIndexToModel(column)); } + /** + * Get the name of the column. If the column has the column identifier set, + * the return value is the result of the .toString() method call on that + * identifier. If the identifier is not explicitly set, the returned value + * is calculated by + * {@link javax.swing.table.AbstractTableModel#getColumnName(int)}. + * + * @param column the column + * + * @return the name of that column. + */ public String getColumnName(int column) { int modelColumn = columnModel.getColumn(column).getModelIndex(); return dataModel.getColumnName(modelColumn); } - + + /** + * Get the column, currently being edited + * + * @return the column, currently being edited. + */ public int getEditingColumn() { return editingColumn; } - + + /** + * Set the column, currently being edited + * + * @param column the column, currently being edited. + */ public void setEditingColumn(int column) { editingColumn = column; } + /** + * Get the row currently being edited. + * + * @return the row, currently being edited. + */ public int getEditingRow() { return editingRow; } - - public void setEditingRow(int column) + + /** + * Set the row currently being edited. + * + * @param row the row, that will be edited + */ + public void setEditingRow(int row) { - editingRow = column; + editingRow = row; } + /** + * Get the editor component that is currently editing one of the cells + * + * @return the editor component or null, if none of the cells is being + * edited. + */ public Component getEditorComponent() { return editorComp; } + /** + * Check if one of the table cells is currently being edited. + * + * @return true if there is a cell being edited. + */ public boolean isEditing() { return editorComp != null; } - + + /** + * Set the default editor for the given column class (column data type). + * By default, String is handled by text field and Boolean is handled by + * the check box. + * + * @param columnClass the column data type + * @param editor the editor that will edit this data type + * + * @see TableModel#getColumnClass(int) + */ public void setDefaultEditor(Class columnClass, TableCellEditor editor) { if (editor != null) @@ -3072,7 +3373,7 @@ public class JTable else defaultEditorsByColumnClass.remove(columnClass); } - + public void addColumnSelectionInterval(int index0, int index1) { if ((index0 < 0 || index0 > (getColumnCount()-1) @@ -3127,21 +3428,49 @@ public class JTable getSelectionModel().removeSelectionInterval(index0, index1); } + /** + * Checks if the given column is selected. + * + * @param column the column + * + * @return true if the column is selected (as reported by the selection + * model, associated with the column model), false otherwise. + */ public boolean isColumnSelected(int column) { return getColumnModel().getSelectionModel().isSelectedIndex(column); } - + + /** + * Checks if the given row is selected. + * + * @param row the row + * + * @return true if the row is selected (as reported by the selection model), + * false otherwise. + */ public boolean isRowSelected(int row) { return getSelectionModel().isSelectedIndex(row); } - + + /** + * Checks if the given cell is selected. The cell is selected if both + * the cell row and the cell column are selected. + * + * @param row the cell row + * @param column the cell column + * + * @return true if the cell is selected, false otherwise + */ public boolean isCellSelected(int row, int column) { return isRowSelected(row) && isColumnSelected(column); } + /** + * Select all table. + */ public void selectAll() { // rowLead and colLead store the current lead selection indices @@ -3156,22 +3485,51 @@ public class JTable addColumnSelectionInterval(colLead,colLead); addRowSelectionInterval(rowLead, rowLead); } - + + /** + * Get the cell value at the given position. + * + * @param row the row to get the value + * @param column the actual column number (not the model index) + * to get the value. + * + * @return the cell value, as returned by model. + */ public Object getValueAt(int row, int column) { return dataModel.getValueAt(row, convertColumnIndexToModel(column)); } - + + /** + * Set value for the cell at the given position. If the cell is not + * editable, this method returns without action. The modified cell is + * repainted. + * + * @param value the value to set + * @param row the row of the cell being modified + * @param column the column of the cell being modified + */ public void setValueAt(Object value, int row, int column) { if (!isCellEditable(row, column)) return; - - if (value instanceof Component) - add((Component)value); dataModel.setValueAt(value, row, convertColumnIndexToModel(column)); + + repaint(getCellRect(row, column, true)); } - + + /** + * Get table column with the given identified. + * + * @param identifier the column identifier + * + * @return the table column with this identifier + * + * @throws IllegalArgumentException if identifier is + * null or there is no column with that identifier. + * + * @see TableColumn#setIdentifier(Object) + */ public TableColumn getColumn(Object identifier) { return columnModel.getColumn(columnModel.getColumnIndex(identifier)); @@ -3184,7 +3542,7 @@ public class JTable * @param row the row index. * @param column the column index. * - * @return A boolean. + * @return true if the cell is editable, false otherwise. */ public boolean isCellEditable(int row, int column) { @@ -3273,19 +3631,50 @@ public class JTable */ public boolean editCellAt (int row, int column) { - oldCellValue = getValueAt(row, column); + // Complete the previous editing session, if still active. + if (isEditing()) + editingStopped(new ChangeEvent("editingStopped")); + + editingRow = row; + editingColumn = column; + setCellEditor(getCellEditor(row, column)); editorComp = prepareEditor(cellEditor, row, column); - cellEditor.addCellEditorListener(this); - rowBeingEdited = row; - columnBeingEdited = column; - setValueAt(editorComp, row, column); - ((JTextField)editorComp).requestFocusInWindow(false); - editorTimer.start(); + + // Remove the previous editor components, if present. Only one + // editor component at time is allowed in the table. + removeAll(); + add(editorComp); + moveToCellBeingEdited(editorComp); + scrollRectToVisible(editorComp.getBounds()); + editorComp.requestFocusInWindow(); return true; } /** + * Move the given component under the cell being edited. + * The table must be in the editing mode. + * + * @param component the component to move. + */ + private void moveToCellBeingEdited(Component component) + { + Rectangle r = getCellRect(editingRow, editingColumn, true); + // Place the text field so that it would not touch the table + // border. + + // TODO Figure out while 5 and which constant should here be. + int xOffset = 5; + r.x+=xOffset; + r.y++; + r.width -=xOffset; + r.height --; + + // Clone rectangle as getCellRect returns the cached value. + component.setBounds(new Rectangle(r)); + } + + /** * Programmatically starts editing the specified cell. * * @param row the row of the cell to edit. @@ -3343,7 +3732,7 @@ public class JTable // TODO: Implement functionality of this property (in UI impl). surrendersFocusOnKeystroke = value; } - + /** * Returns whether cell editors of this table should receive keyboard focus * when the editor is activated by a keystroke. The default setting is diff --git a/libjava/classpath/javax/swing/JTextField.java b/libjava/classpath/javax/swing/JTextField.java index c490310..01c5c06 100644 --- a/libjava/classpath/javax/swing/JTextField.java +++ b/libjava/classpath/javax/swing/JTextField.java @@ -41,6 +41,7 @@ package javax.swing; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; +import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; @@ -352,7 +353,10 @@ public class JTextField extends JTextComponent Dimension size = super.getPreferredSize(); if (columns != 0) - size.width = columns * getColumnWidth(); + { + Insets i = getInsets(); + size.width = columns * getColumnWidth() + i.left + i.right; + } return size; } @@ -526,4 +530,18 @@ public class JTextField extends JTextComponent // javax.swing.text.FieldView. return horizontalVisibility; } + + /** + * Returns true, unless this is embedded in a + * JViewport in which case the viewport takes responsibility of + * validating. + * + * @return true, unless this is embedded in a + * JViewport in which case the viewport takes + * responsibility of validating + */ + public boolean isValidateRoot() + { + return ! (getParent() instanceof JViewport); + } } diff --git a/libjava/classpath/javax/swing/JTextPane.java b/libjava/classpath/javax/swing/JTextPane.java index 7c95d76..c0a5f80 100644 --- a/libjava/classpath/javax/swing/JTextPane.java +++ b/libjava/classpath/javax/swing/JTextPane.java @@ -327,9 +327,11 @@ public class JTextPane if (start == dot && end == dot) // There is no selection, update insertAttributes instead { - MutableAttributeSet inputAttributes = - getStyledEditorKit().getInputAttributes(); - inputAttributes.addAttributes(attribute); + MutableAttributeSet inputAttributes = + getStyledEditorKit().getInputAttributes(); + if (replace) + inputAttributes.removeAttributes(inputAttributes); + inputAttributes.addAttributes(attribute); } else getStyledDocument().setCharacterAttributes(start, end - start, attribute, diff --git a/libjava/classpath/javax/swing/JTree.java b/libjava/classpath/javax/swing/JTree.java index cfcb229..7876eeb 100644 --- a/libjava/classpath/javax/swing/JTree.java +++ b/libjava/classpath/javax/swing/JTree.java @@ -1482,6 +1482,9 @@ public class JTree extends JComponent implements Scrollable, Accessible setModel(model); setSelectionModel(new EmptySelectionModel()); selectionModel.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); + + // The root node appears expanded by default. + nodeStates.put(new TreePath(model.getRoot()), EXPANDED); } /** @@ -2497,8 +2500,9 @@ public class JTree extends JComponent implements Scrollable, Accessible { TreeUI ui = getUI(); - if (ui != null) - return ui.stopEditing(this); + if (isEditing()) + if (ui != null) + return ui.stopEditing(this); return false; } @@ -2506,9 +2510,10 @@ public class JTree extends JComponent implements Scrollable, Accessible public void cancelEditing() { TreeUI ui = getUI(); - - if (ui != null) - ui.cancelEditing(this); + + if (isEditing()) + if (ui != null) + ui.cancelEditing(this); } public void startEditingAtPath(TreePath path) @@ -2738,7 +2743,7 @@ public class JTree extends JComponent implements Scrollable, Accessible * * @return a String representation of this JTree */ - public String paramString() + protected String paramString() { // TODO: this is completely legal, but it would possibly be nice // to return some more content, like the tree structure, some properties diff --git a/libjava/classpath/javax/swing/JViewport.java b/libjava/classpath/javax/swing/JViewport.java index debb574..2b5d1cd 100644 --- a/libjava/classpath/javax/swing/JViewport.java +++ b/libjava/classpath/javax/swing/JViewport.java @@ -48,6 +48,7 @@ import java.awt.Insets; import java.awt.LayoutManager; import java.awt.Point; import java.awt.Rectangle; +import java.awt.Shape; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.io.Serializable; @@ -113,7 +114,7 @@ public class JViewport extends JComponent implements Accessible /** * Creates a new instance of AccessibleJViewport. */ - public AccessibleJViewport() + protected AccessibleJViewport() { // Nothing to do here. } @@ -252,6 +253,13 @@ public class JViewport extends JComponent implements Accessible boolean sizeChanged = true; /** + * Indicates if this JViewport is the paint root or not. If it is not, then + * we may not assume that the offscreen buffer still has the right content + * because parent components may have cleared the background already. + */ + private boolean isPaintRoot = false; + + /** * Initializes the default setting for the scrollMode property. */ static @@ -635,11 +643,19 @@ public class JViewport extends JComponent implements Accessible */ public void repaint(long tm, int x, int y, int w, int h) { - Component parent = getParent(); - if (parent != null) - { - parent.repaint(tm, x + getX(), y + getY(), w, h); - } +// Component parent = getParent(); +// if (parent != null) +// parent.repaint(tm, x + getX(), y + getY(), w, h); +// else +// super.repaint(tm, x, y, w, h); + + // The specs suggest to implement something like the above. This however + // breaks blit painting, because the parent (most likely a JScrollPane) + // clears the background of the offscreen area of the JViewport, thus + // destroying the pieces that we want to clip. So we simply call super here + // instead. + super.repaint(tm, x, y, w, h); + } protected void addImpl(Component comp, Object constraints, int index) @@ -710,9 +726,11 @@ public class JViewport extends JComponent implements Accessible protected boolean computeBlit(int dx, int dy, Point blitFrom, Point blitTo, Dimension blitSize, Rectangle blitPaint) { - if ((dx != 0 && dy != 0) || damaged) + if ((dx != 0 && dy != 0) || (dy == 0 && dy == 0) || damaged) // We cannot blit if the viewport is scrolled in both directions at - // once. + // once. Also, we do not want to blit if the viewport is not scrolled at + // all, because that probably means the view component repaints itself + // and the buffer needs updating. return false; Rectangle portBounds = SwingUtilities.calculateInnerArea(this, getBounds()); @@ -791,6 +809,8 @@ public class JViewport extends JComponent implements Accessible Point pos = getViewPosition(); Component view = getView(); + Shape oldClip = g.getClip(); + g.clipRect(0, 0, getWidth(), getHeight()); boolean translated = false; try { @@ -802,6 +822,7 @@ public class JViewport extends JComponent implements Accessible { if (translated) g.translate (pos.x, pos.y); + g.setClip(oldClip); } } @@ -854,6 +875,11 @@ public class JViewport extends JComponent implements Accessible // everything. else { + // If the image has not been scrolled at all, only the changed + // clip must be updated in the buffer. + if (dx==0 && dy==0) + g2.setClip(g.getClip()); + paintSimple(g2); } g2.dispose(); @@ -877,23 +903,49 @@ public class JViewport extends JComponent implements Accessible */ void paintBlit(Graphics g) { - // We cannot perform blitted painting as it is described in Sun's API docs. - // There it is suggested that this painting method should blit directly - // on the parent window's surface. This is not possible because when using - // Swing's double buffering (at least our implementation), it would - // immediatly be painted when the buffer is painted on the screen. For this - // to work we would need a kind of hole in the buffer image. And honestly - // I find this method not very elegant. - // The alternative, blitting directly on the buffer image, is also not - // possible because the buffer image gets cleared everytime when an opaque - // parent component is drawn on it. - - // What we do instead is falling back to the backing store approach which - // is in fact a mixed blitting/backing store approach where the blitting - // is performed on the backing store image and this is then drawn to the - // graphics context. This is very robust and works independent of the - // painting mechanism that is used by Swing. And it should have comparable - // performance characteristics as the blitting method. - paintBackingStore(g); + // First we move the part that remains visible after scrolling, then + // we only need to paint the bit that becomes newly visible. + Point viewPosition = getViewPosition(); + int dx = viewPosition.x - lastPaintPosition.x; + int dy = viewPosition.y - lastPaintPosition.y; + boolean canBlit = computeBlit(dx, dy, cachedBlitFrom, cachedBlitTo, + cachedBlitSize, cachedBlitPaint); + if (canBlit && isPaintRoot) + { + // Copy the part that remains visible during scrolling. + g.copyArea(cachedBlitFrom.x, cachedBlitFrom.y, + cachedBlitSize.width, cachedBlitSize.height, + cachedBlitTo.x - cachedBlitFrom.x, + cachedBlitTo.y - cachedBlitFrom.y); + // Now paint the part that becomes newly visible. + Shape oldClip = g.getClip(); + g.clipRect(cachedBlitPaint.x, cachedBlitPaint.y, + cachedBlitPaint.width, cachedBlitPaint.height); + try + { + paintSimple(g); + } + finally + { + g.setClip(oldClip); + } + } + // If blitting is not possible for some reason, fall back to repainting + // everything. + else + paintSimple(g); + lastPaintPosition.setLocation(getViewPosition()); + } + + /** + * Overridden from JComponent to set the {@link #isPaintRoot} flag. + * + * @param r the rectangle to paint + */ + void paintImmediately2(Rectangle r) + { + isPaintRoot = true; + super.paintImmediately2(r); + isPaintRoot = false; } } diff --git a/libjava/classpath/javax/swing/JWindow.java b/libjava/classpath/javax/swing/JWindow.java index cc0ac7f..19d830e 100644 --- a/libjava/classpath/javax/swing/JWindow.java +++ b/libjava/classpath/javax/swing/JWindow.java @@ -68,7 +68,7 @@ public class JWindow extends Window implements Accessible, RootPaneContainer /** * Creates a new instance of AccessibleJWindow. */ - public AccessibleJWindow() + protected AccessibleJWindow() { super(); // Nothing to do here. @@ -86,33 +86,73 @@ public class JWindow extends Window implements Accessible, RootPaneContainer protected AccessibleContext accessibleContext; + /** + * Creates a new JWindow that has a shared invisible owner frame + * as its parent. + */ public JWindow() { - super(SwingUtilities.getOwnerFrame()); + super(SwingUtilities.getOwnerFrame(null)); windowInit(); } + /** + * Creates a new JWindow that uses the specified graphics + * environment. This can be used to open a window on a different screen for + * example. + * + * @param gc the graphics environment to use + */ public JWindow(GraphicsConfiguration gc) { - super(SwingUtilities.getOwnerFrame(), gc); + super(SwingUtilities.getOwnerFrame(null), gc); windowInit(); } - + + /** + * Creates a new JWindow that has the specified + * owner frame. If owner is null, then + * an invisible shared owner frame is installed as owner frame. + * + * @param owner the owner frame of this window; if null a shared + * invisible owner frame is used + */ public JWindow(Frame owner) { - super(owner); + super(SwingUtilities.getOwnerFrame(owner)); windowInit(); } + /** + * Creates a new JWindow that has the specified + * owner window. If owner is null, + * then an invisible shared owner frame is installed as owner frame. + * + * @param owner the owner window of this window; if null a + * shared invisible owner frame is used + */ public JWindow(Window owner) { - super(owner); + super(SwingUtilities.getOwnerFrame(owner)); windowInit(); } + /** + * Creates a new JWindow for the given graphics configuration + * and that has the specified owner window. If + * owner is null, then an invisible shared owner + * frame is installed as owner frame. + * + * The gc parameter can be used to open the window on a + * different screen for example. + * + * @param owner the owner window of this window; if null a + * shared invisible owner frame is used + * @param gc the graphics configuration to use + */ public JWindow(Window owner, GraphicsConfiguration gc) { - super(owner, gc); + super(SwingUtilities.getOwnerFrame(owner), gc); windowInit(); } diff --git a/libjava/classpath/javax/swing/Popup.java b/libjava/classpath/javax/swing/Popup.java index 203ee3c..c3de69e 100644 --- a/libjava/classpath/javax/swing/Popup.java +++ b/libjava/classpath/javax/swing/Popup.java @@ -161,7 +161,7 @@ public class Popup super(owner, contents, x, y); this.contents = contents; - window = new JWindow(); + window = new JWindow(SwingUtilities.getWindowAncestor(owner)); window.getContentPane().add(contents); window.setLocation(x, y); window.setFocusableWindowState(false); diff --git a/libjava/classpath/javax/swing/PopupFactory.java b/libjava/classpath/javax/swing/PopupFactory.java index 7bb2529..b326205 100644 --- a/libjava/classpath/javax/swing/PopupFactory.java +++ b/libjava/classpath/javax/swing/PopupFactory.java @@ -152,13 +152,18 @@ public class PopupFactory // If we have a root pane and the contents fits within the root pane and // lightweight popups are enabled, than we can use a lightweight popup. JRootPane root = SwingUtilities.getRootPane(owner); - Point rootLoc = root.getLocationOnScreen(); - Dimension contentsSize = contents.getSize(); - Dimension rootSize = root.getSize(); - if (x >= rootLoc.x && y > rootLoc.y - && (x - rootLoc.x) + contentsSize.width < rootSize.width - && (y - rootLoc.y) + contentsSize.height < rootSize.height) - popup = new Popup.LightweightPopup(owner, contents, x, y); + if (root != null) + { + Point rootLoc = root.getLocationOnScreen(); + Dimension contentsSize = contents.getSize(); + Dimension rootSize = root.getSize(); + if (x >= rootLoc.x && y > rootLoc.y + && (x - rootLoc.x) + contentsSize.width < rootSize.width + && (y - rootLoc.y) + contentsSize.height < rootSize.height) + popup = new Popup.LightweightPopup(owner, contents, x, y); + else + popup = new Popup.JWindowPopup(owner, contents, x, y); + } else popup = new Popup.JWindowPopup(owner, contents, x, y); return popup; diff --git a/libjava/classpath/javax/swing/RepaintManager.java b/libjava/classpath/javax/swing/RepaintManager.java index 0be8105..ed05009 100644 --- a/libjava/classpath/javax/swing/RepaintManager.java +++ b/libjava/classpath/javax/swing/RepaintManager.java @@ -40,14 +40,18 @@ package javax.swing; import java.awt.Component; import java.awt.Dimension; +import java.awt.Graphics; import java.awt.Image; import java.awt.Rectangle; +import java.awt.Window; import java.awt.image.VolatileImage; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; +import java.util.Map; +import java.util.Set; import java.util.WeakHashMap; /** @@ -62,6 +66,7 @@ import java.util.WeakHashMap; * href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">this * document for more details.

* + * @author Roman Kennke (kennke@aicas.com) * @author Graydon Hoare (graydon@redhat.com) */ public class RepaintManager @@ -69,8 +74,13 @@ public class RepaintManager /** * The current repaint managers, indexed by their ThreadGroups. */ - static WeakHashMap currentRepaintManagers; - + private static WeakHashMap currentRepaintManagers; + + /** + * A rectangle object to be reused in damaged regions calculation. + */ + private static Rectangle rectCache = new Rectangle(); + /** *

A helper class which is placed into the system event queue at * various times in order to facilitate repainting and layout. There is @@ -84,7 +94,7 @@ public class RepaintManager * swing paint thread, which revalidates all invalid components and * repaints any damage in the swing scene.

*/ - protected class RepaintWorker + private class RepaintWorker implements Runnable { @@ -107,12 +117,18 @@ public class RepaintManager public void run() { - ThreadGroup threadGroup = Thread.currentThread().getThreadGroup(); - RepaintManager rm = - (RepaintManager) currentRepaintManagers.get(threadGroup); - setLive(false); - rm.validateInvalidComponents(); - rm.paintDirtyRegions(); + try + { + ThreadGroup threadGroup = Thread.currentThread().getThreadGroup(); + RepaintManager rm = + (RepaintManager) currentRepaintManagers.get(threadGroup); + rm.validateInvalidComponents(); + rm.paintDirtyRegions(); + } + finally + { + setLive(false); + } } } @@ -135,41 +151,23 @@ public class RepaintManager * @param o1 the first component * @param o2 the second component * - * @return a negative integer, if o1 is higher in the - * hierarchy than o2, zero, if both are at the same - * level and a positive integer, if o1 is deeper in - * the hierarchy than o2 + * @return a negative integer, if o1 is bigger in than + * o2, zero, if both are at the same size and a + * positive integer, if o1 is smaller than + * o2 */ public int compare(Object o1, Object o2) { if (o1 instanceof JComponent && o2 instanceof JComponent) { JComponent c1 = (JComponent) o1; + Rectangle d1 = (Rectangle) dirtyComponents.get(c1); JComponent c2 = (JComponent) o2; - return getDepth(c1) - getDepth(c2); - } - else - throw new ClassCastException("This comparator can only be used with " - + "JComponents"); - } - - /** - * Computes the depth for a given JComponent. - * - * @param c the component to compute the depth for - * - * @return the depth of the component - */ - private int getDepth(JComponent c) - { - Component comp = c; - int depth = 0; - while (comp != null) - { - comp = comp.getParent(); - depth++; + Rectangle d2 = (Rectangle) dirtyComponents.get(c2); + return d2.width * d2.height - d1.width * d1.height; } - return depth; + throw new ClassCastException("This comparator can only be used with " + + "JComponents"); } } @@ -179,6 +177,9 @@ public class RepaintManager * to exactly one rectangle. When more regions are marked as dirty on a * component, they are union'ed with the existing rectangle. * + * This is package private to avoid a synthetic accessor method in inner + * class. + * * @see #addDirtyRegion * @see #getDirtyRegion * @see #isCompletelyDirty @@ -187,18 +188,10 @@ public class RepaintManager */ HashMap dirtyComponents; - HashMap workDirtyComponents; - - /** - * Stores the order in which the components get repainted. - */ - ArrayList repaintOrder; - ArrayList workRepaintOrder; - /** * The comparator used for ordered inserting into the repaintOrder list. */ - Comparator comparator; + private transient Comparator comparator; /** * A single, shared instance of the helper class. Any methods which mark @@ -209,7 +202,7 @@ public class RepaintManager * @see #addDirtyRegion * @see #addInvalidComponent */ - RepaintWorker repaintWorker; + private RepaintWorker repaintWorker; /** * The set of components which need revalidation, in the "layout" sense. @@ -221,8 +214,7 @@ public class RepaintManager * @see #removeInvalidComponent * @see #validateInvalidComponents */ - ArrayList invalidComponents; - ArrayList workInvalidComponents; + private ArrayList invalidComponents; /** * Whether or not double buffering is enabled on this repaint @@ -232,17 +224,27 @@ public class RepaintManager * @see #isDoubleBufferingEnabled * @see #setDoubleBufferingEnabled */ - boolean doubleBufferingEnabled; + private boolean doubleBufferingEnabled; - /** - * The current offscreen buffer. This is reused for all requests for - * offscreen drawing buffers. It grows as necessary, up to {@link - * #doubleBufferMaximumSize}, but there is only one shared instance. - * - * @see #getOffscreenBuffer - * @see #doubleBufferMaximumSize + /** + * The offscreen buffers. This map holds one offscreen buffer per + * Window/Applet and releases them as soon as the Window/Applet gets garbage + * collected. */ - Image doubleBuffer; + private WeakHashMap offscreenBuffers; + + /** + * Indicates if the RepaintManager is currently repainting an area. + */ + private boolean repaintUnderway; + + /** + * This holds buffer commit requests when the RepaintManager is working. + * This maps Component objects (the top level components) to Rectangle + * objects (the area of the corresponding buffer that must be blitted on + * the component). + */ + private HashMap commitRequests; /** * The maximum width and height to allocate as a double buffer. Requests @@ -252,7 +254,7 @@ public class RepaintManager * @see #getDoubleBufferMaximumSize * @see #setDoubleBufferMaximumSize */ - Dimension doubleBufferMaximumSize; + private Dimension doubleBufferMaximumSize; /** @@ -261,14 +263,13 @@ public class RepaintManager public RepaintManager() { dirtyComponents = new HashMap(); - workDirtyComponents = new HashMap(); - repaintOrder = new ArrayList(); - workRepaintOrder = new ArrayList(); invalidComponents = new ArrayList(); - workInvalidComponents = new ArrayList(); repaintWorker = new RepaintWorker(); doubleBufferMaximumSize = new Dimension(2000,2000); doubleBufferingEnabled = true; + offscreenBuffers = new WeakHashMap(); + repaintUnderway = false; + commitRequests = new HashMap(); } /** @@ -346,9 +347,9 @@ public class RepaintManager * * @see #removeInvalidComponent */ - public synchronized void addInvalidComponent(JComponent component) + public void addInvalidComponent(JComponent component) { - Component ancestor = component.getParent(); + Component ancestor = component; while (ancestor != null && (! (ancestor instanceof JComponent) @@ -363,8 +364,11 @@ public class RepaintManager if (invalidComponents.contains(component)) return; - invalidComponents.add(component); - + synchronized (invalidComponents) + { + invalidComponents.add(component); + } + if (! repaintWorker.isLive()) { repaintWorker.setLive(true); @@ -379,9 +383,12 @@ public class RepaintManager * * @see #addInvalidComponent */ - public synchronized void removeInvalidComponent(JComponent component) + public void removeInvalidComponent(JComponent component) { - invalidComponents.remove(component); + synchronized (invalidComponents) + { + invalidComponents.remove(component); + } } /** @@ -402,41 +409,40 @@ public class RepaintManager * @see #markCompletelyClean * @see #markCompletelyDirty */ - public synchronized void addDirtyRegion(JComponent component, int x, int y, - int w, int h) + public void addDirtyRegion(JComponent component, int x, int y, + int w, int h) { - if (w == 0 || h == 0 || !component.isShowing()) + if (w <= 0 || h <= 0 || !component.isShowing()) return; - Rectangle r = new Rectangle(x, y, w, h); - if (dirtyComponents.containsKey(component)) - r = r.union((Rectangle)dirtyComponents.get(component)); - else - insertInRepaintOrder(component); - dirtyComponents.put(component, r); - if (! repaintWorker.isLive()) + + component.computeVisibleRect(rectCache); + SwingUtilities.computeIntersection(x, y, w, h, rectCache); + + if (! rectCache.isEmpty()) { - repaintWorker.setLive(true); - SwingUtilities.invokeLater(repaintWorker); + if (dirtyComponents.containsKey(component)) + { + SwingUtilities.computeUnion(rectCache.x, rectCache.y, + rectCache.width, rectCache.height, + (Rectangle) dirtyComponents.get(component)); + } + else + { + synchronized (dirtyComponents) + { + dirtyComponents.put(component, rectCache.getBounds()); + } + } + + if (! repaintWorker.isLive()) + { + repaintWorker.setLive(true); + SwingUtilities.invokeLater(repaintWorker); + } } } /** - * Inserts a component into the repaintOrder list in an ordered fashion, - * using a binary search. - * - * @param c the component to be inserted - */ - private void insertInRepaintOrder(JComponent c) - { - if (comparator == null) - comparator = new ComponentComparator(); - int insertIndex = Collections.binarySearch(repaintOrder, c, comparator); - if (insertIndex < 0) - insertIndex = -(insertIndex + 1); - repaintOrder.add(insertIndex, c); - } - - /** * Get the dirty region associated with a component, or null * if the component has no dirty region. * @@ -489,7 +495,7 @@ public class RepaintManager */ public void markCompletelyClean(JComponent component) { - synchronized (this) + synchronized (dirtyComponents) { dirtyComponents.remove(component); } @@ -523,63 +529,58 @@ public class RepaintManager */ public void validateInvalidComponents() { - // In order to keep the blocking of application threads minimal, we switch - // the invalidComponents field with the workInvalidComponents field and - // work with the workInvalidComponents field. - synchronized(this) - { - ArrayList swap = invalidComponents; - invalidComponents = workInvalidComponents; - workInvalidComponents = swap; - } - for (Iterator i = workInvalidComponents.iterator(); i.hasNext(); ) + // We don't use an iterator here because that would fail when there are + // components invalidated during the validation of others, which happens + // quite frequently. Instead we synchronize the access a little more. + while (invalidComponents.size() > 0) { - Component comp = (Component) i.next(); - // Find validate root. - while ((!(comp instanceof JComponent) - || !((JComponent) comp).isValidateRoot()) - && comp.getParent() != null) - comp = comp.getParent(); - - // Validate the validate root. + Component comp; + synchronized (invalidComponents) + { + comp = (Component) invalidComponents.remove(0); + } + // Validate the validate component. if (! (comp.isVisible() && comp.isShowing())) continue; comp.validate(); } - workInvalidComponents.clear(); } /** * Repaint all regions of all components which have been marked dirty in * the {@link #dirtyComponents} table. */ - public synchronized void paintDirtyRegions() + public void paintDirtyRegions() { - // In order to keep the blocking of application threads minimal, we switch - // the dirtyComponents field with the workdirtyComponents field and the - // repaintOrder field with the workRepaintOrder field and work with the - // work* fields. - synchronized(this) - { - ArrayList swap = workRepaintOrder; - workRepaintOrder = repaintOrder; - repaintOrder = swap; - HashMap swap2 = workDirtyComponents; - workDirtyComponents = dirtyComponents; - dirtyComponents = swap2; - } - for (Iterator i = workRepaintOrder.iterator(); i.hasNext();) + // Short cicuit if there is nothing to paint. + if (dirtyComponents.size() == 0) + return; + + synchronized (dirtyComponents) { - JComponent comp = (JComponent) i.next(); - // If a component is marked completely clean in the meantime, then skip - // it. - Rectangle damaged = (Rectangle) workDirtyComponents.get(comp); - if (damaged == null || damaged.isEmpty()) - continue; - comp.paintImmediately(damaged); + // We sort the components by their size here. This way we have a good + // chance that painting the bigger components also paints the smaller + // components and we don't need to paint them twice. + ArrayList repaintOrder = new ArrayList(dirtyComponents.size()); + repaintOrder.addAll(dirtyComponents.keySet()); + if (comparator == null) + comparator = new ComponentComparator(); + Collections.sort(repaintOrder, comparator); + repaintUnderway = true; + for (Iterator i = repaintOrder.iterator(); i.hasNext();) + { + JComponent comp = (JComponent) i.next(); + // If a component is marked completely clean in the meantime, then skip + // it. + Rectangle damaged = (Rectangle) dirtyComponents.get(comp); + if (damaged == null || damaged.isEmpty()) + continue; + comp.paintImmediately(damaged); + dirtyComponents.remove(comp); + } + repaintUnderway = false; + commitRemainingBuffers(); } - workRepaintOrder.clear(); - workDirtyComponents.clear(); } /** @@ -592,21 +593,114 @@ public class RepaintManager * @param proposedHeight The proposed height of the offscreen buffer * * @return A shared offscreen buffer for painting - * - * @see #doubleBuffer */ public Image getOffscreenBuffer(Component component, int proposedWidth, int proposedHeight) { - if (doubleBuffer == null - || (((doubleBuffer.getWidth(null) < proposedWidth) - || (doubleBuffer.getHeight(null) < proposedHeight)) - && (proposedWidth < doubleBufferMaximumSize.width) - && (proposedHeight < doubleBufferMaximumSize.height))) + Component root = SwingUtilities.getRoot(component); + Image buffer = (Image) offscreenBuffers.get(root); + if (buffer == null + || buffer.getWidth(null) < proposedWidth + || buffer.getHeight(null) < proposedHeight) + { + int width = Math.max(proposedWidth, root.getWidth()); + width = Math.min(doubleBufferMaximumSize.width, width); + int height = Math.max(proposedHeight, root.getHeight()); + height = Math.min(doubleBufferMaximumSize.height, height); + buffer = component.createImage(width, height); + offscreenBuffers.put(root, buffer); + } + return buffer; + } + + /** + * Blits the back buffer of the specified root component to the screen. If + * the RepaintManager is currently working on a paint request, the commit + * requests are queued up and committed at once when the paint request is + * done (by {@link #commitRemainingBuffers}). This is package private because + * it must get called by JComponent. + * + * @param root the component, either a Window or an Applet instance + * @param area the area to paint on screen + */ + void commitBuffer(Component root, Rectangle area) + { + // We synchronize on dirtyComponents here because that is what + // paintDirtyRegions also synchronizes on while painting. + synchronized (dirtyComponents) + { + // If the RepaintManager is not currently painting, then directly + // blit the requested buffer on the screen. + if (! repaintUnderway) + { + Graphics g = root.getGraphics(); + Image buffer = (Image) offscreenBuffers.get(root); + Rectangle clip = g.getClipBounds(); + if (clip != null) + area = SwingUtilities.computeIntersection(clip.x, clip.y, + clip.width, clip.height, + area); + int dx1 = area.x; + int dy1 = area.y; + int dx2 = area.x + area.width; + int dy2 = area.y + area.height; + // Make sure we have a sane clip at this point. + g.clipRect(area.x, area.y, area.width, area.height); + + // Make sure the coordinates are inside the buffer, everything else + // might lead to problems. + // TODO: This code should not really be necessary, however, in fact + // we have two issues here: + // 1. We shouldn't get repaint requests in areas outside the buffer + // region in the first place. This still happens for example + // when a component is inside a JViewport, and the component has + // a size that would reach beyond the window size. + // 2. Graphics.drawImage() should not behave strange when trying + // to draw regions outside the image. + int bufferWidth = buffer.getWidth(root); + int bufferHeight = buffer.getHeight(root); + dx1 = Math.min(bufferWidth, dx1); + dy1 = Math.min(bufferHeight, dy1); + dx2 = Math.min(bufferWidth, dx2); + dy2 = Math.min(bufferHeight, dy2); + g.drawImage(buffer, dx1, dy1, dx2, dy2, + dx1, dy1, dx2, dy2, root); + g.dispose(); + } + // Otherwise queue this request up, until all the RepaintManager work + // is done. + else + { + if (commitRequests.containsKey(root)) + SwingUtilities.computeUnion(area.x, area.y, area.width, + area.height, + (Rectangle) commitRequests.get(root)); + else + commitRequests.put(root, area); + } + } + } + + /** + * Commits the queued up back buffers to screen all at once. + */ + private void commitRemainingBuffers() + { + // We synchronize on dirtyComponents here because that is what + // paintDirtyRegions also synchronizes on while painting. + synchronized (dirtyComponents) { - doubleBuffer = component.createImage(proposedWidth, proposedHeight); + Set entrySet = commitRequests.entrySet(); + Iterator i = entrySet.iterator(); + while (i.hasNext()) + { + Map.Entry entry = (Map.Entry) i.next(); + Component root = (Component) entry.getKey(); + Rectangle area = (Rectangle) entry.getValue(); + commitBuffer(root, area); + i.remove(); + } } - return doubleBuffer; } /** diff --git a/libjava/classpath/javax/swing/ScrollPaneLayout.java b/libjava/classpath/javax/swing/ScrollPaneLayout.java index edf1f1f..b00b5c4 100644 --- a/libjava/classpath/javax/swing/ScrollPaneLayout.java +++ b/libjava/classpath/javax/swing/ScrollPaneLayout.java @@ -285,20 +285,20 @@ public class ScrollPaneLayout // Sun's implementation simply throws a ClassCastException if // parent is no JScrollPane, so do we. JScrollPane sc = (JScrollPane) parent; - Dimension viewportSize = viewport.getMinimumSize(); - int width = viewportSize.width; - int height = viewportSize.height; - if (hsb != null && hsb.isVisible()) - height += hsb.getMinimumSize().height; - if (vsb != null && vsb.isVisible()) - width += vsb.getMinimumSize().width; - if (rowHead != null && rowHead.isVisible()) - width += rowHead.getMinimumSize().width; - if (colHead != null && colHead.isVisible()) - height += colHead.getMinimumSize().height; Insets i = sc.getInsets(); - return new Dimension(width + i.left + i.right, - height + i.top + i.bottom); + Dimension viewportMinSize = sc.getViewport().getMinimumSize(); + + int width = i.left + i.right + viewportMinSize.width; + if (sc.getVerticalScrollBarPolicy() + != JScrollPane.VERTICAL_SCROLLBAR_NEVER) + width += sc.getVerticalScrollBar().getMinimumSize().width; + + int height = i.top + i.bottom + viewportMinSize.height; + if (sc.getHorizontalScrollBarPolicy() + != JScrollPane.HORIZONTAL_SCROLLBAR_NEVER) + height += sc.getHorizontalScrollBar().getMinimumSize().height; + + return new Dimension(width, height); } /** diff --git a/libjava/classpath/javax/swing/SpinnerDateModel.java b/libjava/classpath/javax/swing/SpinnerDateModel.java index c0de7d5..e0ccab7 100644 --- a/libjava/classpath/javax/swing/SpinnerDateModel.java +++ b/libjava/classpath/javax/swing/SpinnerDateModel.java @@ -1,5 +1,5 @@ /* SpinnerDateModel.java -- - Copyright (C) 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -42,21 +42,37 @@ import java.io.Serializable; import java.util.Calendar; import java.util.Date; +import javax.swing.event.ChangeEvent; + /** - * SpinnerDateModel - * - * Implements a SpinnerModel for dates, rotating a calendar field such as - * month, year, day, week, hour, minute. + * A date model used by the {@link JSpinner} component. This implements a + * spinner model for dates, rotating a calendar field such as month, year, + * day, week, hour, minute. * * @author Sven de Marothy - * @version 0.1 (first implementation) + * @since 1.4 */ public class SpinnerDateModel extends AbstractSpinnerModel implements Serializable { + /** The current date. */ private Calendar date; + + /** + * The start or earliest permitted date (null for no + * minimum). + */ private Comparable start; + + /** + * The end or latest permitted date (null for no + * maximum). + */ private Comparable end; + + /** + * The calendar field used to calculate the previous or next date. + */ private int calendarField; /** @@ -66,8 +82,9 @@ public class SpinnerDateModel extends AbstractSpinnerModel private static final long serialVersionUID = -4802518107105940612L; /** - * Constructs a SpinnerDateModel using the current date, - * no start or end limit, and Calendar.DAY_OF_MONTH as the calendar field. + * Constructs a SpinnerDateModel using the current date, + * no start or end limit, and {@link Calendar#DAY_OF_MONTH} as the calendar + * field. */ public SpinnerDateModel() { @@ -87,6 +104,12 @@ public class SpinnerDateModel extends AbstractSpinnerModel public SpinnerDateModel(Date value, Comparable start, Comparable end, int calendarField) { + if (value == null) + throw new IllegalArgumentException("Null 'value' argument."); + if (start != null && value.compareTo(start) < 0) + throw new IllegalArgumentException("Require value on or after start."); + if (end != null && value.compareTo(end) > 0) + throw new IllegalArgumentException("Require value on or before end."); date = Calendar.getInstance(); date.setTime(value); this.start = start; @@ -95,7 +118,10 @@ public class SpinnerDateModel extends AbstractSpinnerModel } /** - * Returns the value of the Calendar field to spin. + * Returns the {@link Calendar} field used to calculate the previous and + * next dates in the sequence. + * + * @return The date field code. */ public int getCalendarField() { @@ -103,8 +129,9 @@ public class SpinnerDateModel extends AbstractSpinnerModel } /** - * Returns the current date in the sequence. - * @return a Date object. + * Returns the current date. + * + * @return The current date. */ public Date getDate() { @@ -112,8 +139,9 @@ public class SpinnerDateModel extends AbstractSpinnerModel } /** - * Returns the starting limit of the SpinnerModel. - * @return a Date object, or null if there is no limit. + * Returns the start date, or null if there is no minimum date. + * + * @return The start date. */ public Comparable getStart() { @@ -121,8 +149,9 @@ public class SpinnerDateModel extends AbstractSpinnerModel } /** - * Returns the end limit of the SpinnerModel. - * @return a Date object, or null if there is no limit. + * Returns the end date, or null if there is no maximum date. + * + * @return The end date. */ public Comparable getEnd() { @@ -130,9 +159,10 @@ public class SpinnerDateModel extends AbstractSpinnerModel } /** - * Returns the current date in the sequence, - * this method returns the same as getDate(). - * @return a Date object. + * Returns the current date in the sequence (this method returns the same as + * {@link #getDate()}. + * + * @return The current date. */ public Object getValue() { @@ -141,8 +171,10 @@ public class SpinnerDateModel extends AbstractSpinnerModel /** * Returns the next date in the sequence, or null if the - * next date is equal to or past the end limit. - * @return a Date object, or null. + * next date is after the end date. The current date is not changed. + * + * @return The next date, or null if the current value is + * the latest date represented by the model. */ public Object getNextValue() { @@ -152,14 +184,17 @@ public class SpinnerDateModel extends AbstractSpinnerModel Date nextDate = nextCal.getTime(); if (end != null) if (end.compareTo(nextDate) < 0) - return null; + return null; return nextDate; } /** * Returns the previous date in the sequence, or null if the - * next date is equal to or past the end limit. - * @return a Date object, or null. + * previous date is prior to the start date. The current date is not + * changed. + * + * @return The previous date, or null if the current value is + * the earliest date represented by the model. */ public Object getPreviousValue() { @@ -167,16 +202,21 @@ public class SpinnerDateModel extends AbstractSpinnerModel prevCal.setTime(date.getTime()); prevCal.roll(calendarField, false); Date prevDate = prevCal.getTime(); - if (end != null) - if (end.compareTo(prevDate) > 0) - return null; + if (start != null) + if (start.compareTo(prevDate) > 0) + return null; return prevDate; } /** - * Sets the date field to change. It must be a valid Calendar field, - * excluding Calendar.ZONE_OFFSET and Calendar.DST_OFFSET. - * @param calendarField - the calendar field to set. + * Sets the date field to change when calculating the next and previous + * values. It must be a valid {@link Calendar} field, excluding + * {@link Calendar#ZONE_OFFSET} and {@link Calendar#DST_OFFSET}. + * + * @param calendarField the calendar field to set. + * + * @throws IllegalArgumentException if calendarField is not + * a valid code. */ public void setCalendarField(int calendarField) { @@ -187,51 +227,67 @@ public class SpinnerDateModel extends AbstractSpinnerModel if (this.calendarField != calendarField) { - this.calendarField = calendarField; - fireStateChanged(); + this.calendarField = calendarField; + fireStateChanged(); } } /** - * Sets the starting date limit for the sequence. - * - * @param start - a Date object of the limit date, - * or null for no limit. + * Sets the start date and, if the new date is different to the old date, + * sends a {@link ChangeEvent} to all registered listeners. A + * null date is interpreted as "no start date". No check + * is made to ensure that the new start date is on or before the current + * date - the caller is responsible for ensuring that this relationship + * holds. + * + * @param start the new start date (null permitted). */ public void setStart(Comparable start) { if (this.start != start) { - this.start = start; - fireStateChanged(); + this.start = start; + fireStateChanged(); } } /** - * Sets the end date limit for the sequence. - * - * @param end - a Date object of the limit date, - * or null for no limit. + * Sets the end date and, if the new date is different to the old date, + * sends a {@link ChangeEvent} to all registered listeners. A + * null date is interpreted as "no end date". No check + * is made to ensure that the new end date is on or after the current date - + * the caller is responsible for ensuring that this relationship holds. + * + * @param end the new end date (null permitted). */ public void setEnd(Comparable end) { if (this.end != end) { - this.end = end; - fireStateChanged(); + this.end = end; + fireStateChanged(); } } /** - * Sets the current date in the sequence. + * Sets the current date and, if the new value is different to the old + * value, sends a {@link ChangeEvent} to all registered listeners. * - * @param value - a Date object. + * @param value the new date (null not permitted, must be an + * instance of Date). + * + * @throws IllegalArgumentException if value is not an instance + * of Date. */ public void setValue(Object value) { if (! (value instanceof Date) || value == null) throw new IllegalArgumentException("Value not a date."); - date.setTime((Date) value); - fireStateChanged(); + + if (!date.getTime().equals(value)) + { + date.setTime((Date) value); + fireStateChanged(); + } } } diff --git a/libjava/classpath/javax/swing/SpinnerNumberModel.java b/libjava/classpath/javax/swing/SpinnerNumberModel.java index 2274c9e..389c536 100644 --- a/libjava/classpath/javax/swing/SpinnerNumberModel.java +++ b/libjava/classpath/javax/swing/SpinnerNumberModel.java @@ -1,5 +1,5 @@ /* SpinnerNumberModel.java -- - Copyright (C) 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -39,11 +39,13 @@ package javax.swing; import java.io.Serializable; +import javax.swing.event.ChangeEvent; + /** - * SpinnerNumberModel + * A model used by the {@link JSpinner} component. * * @author Ka-Hing Cheung - * @version 1.0 + * @since 1.4 */ public class SpinnerNumberModel extends AbstractSpinnerModel implements Serializable @@ -53,16 +55,16 @@ public class SpinnerNumberModel extends AbstractSpinnerModel */ private static final long serialVersionUID = 7279176385485777821L; - /** DOCUMENT ME! */ + /** The current value. */ private Number value; - /** DOCUMENT ME! */ + /** The minimum value (or null). */ private Comparable minimum; - /** DOCUMENT ME! */ + /** The maximum value (or null). */ private Comparable maximum; - /** DOCUMENT ME! */ + /** The step size. */ private Number stepSize; /** @@ -75,14 +77,14 @@ public class SpinnerNumberModel extends AbstractSpinnerModel } /** - * Creates a SpinnerNumberModel with double precision + * Creates a SpinnerNumberModel with double precision. * * @param value the initial value * @param minimum the minimum value * @param maximum the maximum value * @param stepSize the step size - * @throws IllegalArgumentException if minimum <= value <= maximum does not - * hold + * @throws IllegalArgumentException if minimum <= value <= maximum does + * not hold. */ public SpinnerNumberModel(double value, double minimum, double maximum, double stepSize) @@ -92,14 +94,14 @@ public class SpinnerNumberModel extends AbstractSpinnerModel } /** - * Creates a SpinnerNumberModel with integer precision + * Creates a SpinnerNumberModel with integer precision. * * @param value the initial value * @param minimum the minimum value * @param maximum the maximum value * @param stepSize the step size - * @throws IllegalArgumentException if minimum <= value <= maximum does not - * hold + * @throws IllegalArgumentException if minimum <= value <= maximum does + * not hold. */ public SpinnerNumberModel(int value, int minimum, int maximum, int stepSize) { @@ -108,16 +110,19 @@ public class SpinnerNumberModel extends AbstractSpinnerModel } /** - * Creates a SpinnerNumberModel with Numbers and - * Comparables. + * Creates a SpinnerNumberModel with the given attributes. * - * @param value the initial value - * @param minimum the minimum value, if null there's no minimum - * @param maximum the maximum value, if null there's no maximum - * @param stepSize the step size + * @param value the initial value. + * @param minimum the minimum value (null permitted). + * @param maximum the maximum value (null permitted). + * @param stepSize the step size. * * @throws IllegalArgumentException if minimum <= value <= maximum * does not hold + * @throws IllegalArgumentException if value is + * null. + * @throws IllegalArgumentException if stepSize is + * null. */ public SpinnerNumberModel(Number value, Comparable minimum, Comparable maximum, Number stepSize) @@ -128,33 +133,14 @@ public class SpinnerNumberModel extends AbstractSpinnerModel throw new IllegalArgumentException("value may not be null"); if (minimum != null) { - if (minimum.compareTo(value) > 0) - throw new IllegalArgumentException("minimum is not <= value"); + if (minimum.compareTo(value) > 0) + throw new IllegalArgumentException("minimum is not <= value"); } - else - minimum = new Comparable() - { - public int compareTo(Object obj) - { - return -1; - } - }; - - if (maximum != null) { - if (maximum.compareTo(value) < 0) - throw new IllegalArgumentException("maximum is not >= value"); + if (maximum.compareTo(value) < 0) + throw new IllegalArgumentException("maximum is not >= value"); } - else - maximum = new Comparable() - { - public int compareTo(Object obj) - { - return 1; - } - }; - this.value = value; this.stepSize = stepSize; @@ -163,26 +149,31 @@ public class SpinnerNumberModel extends AbstractSpinnerModel } /** - * Sets the new value and fire a change event + * Sets the current value and, if the new value is different to the old + * value, sends a {@link ChangeEvent} to all registered listeners. * - * @param value the new value + * @param value the new value (null not permitted, must be an + * instance of Number). * - * @throws IllegalArgumentException if minimum <= value <= maximum - * does not hold + * @throws IllegalArgumentException if value is not an instance + * of Number. */ public void setValue(Object value) { if (! (value instanceof Number)) throw new IllegalArgumentException("value must be a Number"); - this.value = (Number) value; - fireStateChanged(); + if (!this.value.equals(value)) + { + this.value = (Number) value; + fireStateChanged(); + } } /** - * Gets the current value + * Returns the current value. * - * @return the current value + * @return The current value. */ public Object getValue() { @@ -190,10 +181,12 @@ public class SpinnerNumberModel extends AbstractSpinnerModel } /** - * Gets the next value without changing the current value, or null if the - * current value is maximum. + * Returns the next value, or null if adding the step size to + * the current value results in a value greater than the maximum value. + * The current value is not changed. * - * @return the next value + * @return The next value, or null if the current value is the + * maximum value represented by this model. */ public Object getNextValue() { @@ -211,15 +204,21 @@ public class SpinnerNumberModel extends AbstractSpinnerModel num = new Short((short) (value.shortValue() + stepSize.shortValue())); else num = new Byte((byte) (value.byteValue() + stepSize.byteValue())); - - return maximum.compareTo(num) >= 0 ? num : null; + + // check upper bound if set + if ((maximum != null) && maximum.compareTo(num) < 0) + num = null; + + return num; } /** - * Gets the previous value without changing the current value, or null if - * the current value is minimum. + * Returns the previous value, or null if subtracting the + * step size from the current value results in a value less than the minimum + * value. The current value is not changed. * - * @return the previous value + * @return The previous value, or null if the current value + * is the minimum value represented by this model. */ public Object getPreviousValue() { @@ -237,62 +236,110 @@ public class SpinnerNumberModel extends AbstractSpinnerModel num = new Short((short) (value.shortValue() - stepSize.shortValue())); else num = new Byte((byte) (value.byteValue() - stepSize.byteValue())); + + // check lower bound if set + if ((minimum != null) && minimum.compareTo(num) > 0) + num = null; - return minimum.compareTo(num) <= 0 ? num : null; + return num; } /** - * DOCUMENT ME! + * Returns the current value. * - * @return DOCUMENT ME! + * @return The current value. */ public Number getNumber() { return value; } + /** + * Returns the minimum value, or null if there is no minimum. + * + * @return The minimum value. + */ public Comparable getMinimum() { return minimum; } + /** + * Sets the minimum value and, if the new value is different to the old + * value, sends a {@link ChangeEvent} to all registered listeners. A + * null value is interpreted as "no minimum value". No check + * is made to ensure that the new minimum is less than or equal to the + * current value, the caller is responsible for ensuring that this + * relationship holds. + * + * @param newMinimum the new minimum value (null permitted). + */ public void setMinimum(Comparable newMinimum) { - if (minimum != newMinimum) + if (minimum != null ? !minimum.equals(newMinimum) : newMinimum != null) { - minimum = newMinimum; - fireStateChanged(); + minimum = newMinimum; + fireStateChanged(); } } + /** + * Returns the maximum value, or null if there is no maximum. + * + * @return The maximum value. + */ public Comparable getMaximum() { return maximum; } + /** + * Sets the maximum value and, if the new value is different to the old + * value, sends a {@link ChangeEvent} to all registered listeners. A + * null value is interpreted as "no maximum value". No check + * is made to ensure that the new maximum is greater than or equal to the + * current value, the caller is responsible for ensuring that this + * relationship holds. + * + * @param newMaximum the new maximum (null permitted). + */ public void setMaximum(Comparable newMaximum) { - if (maximum != newMaximum) + if (maximum != null ? !maximum.equals(newMaximum) : newMaximum != null) { - maximum = newMaximum; - fireStateChanged(); + maximum = newMaximum; + fireStateChanged(); } } + /** + * Returns the step size. + * + * @return The step size. + */ public Number getStepSize() { return stepSize; } + /** + * Sets the step size and, if the new step size is different to the old + * step size, sends a {@link ChangeEvent} to all registered listeners. + * + * @param newStepSize the new step size (null not permitted). + * + * @throws IllegalArgumentException if newStepSize is + * null. + */ public void setStepSize(Number newStepSize) { if (newStepSize == null) throw new IllegalArgumentException(); - if (stepSize != newStepSize) + if (!stepSize.equals(newStepSize)) { - stepSize = newStepSize; - fireStateChanged(); + stepSize = newStepSize; + fireStateChanged(); } } } diff --git a/libjava/classpath/javax/swing/Spring.java b/libjava/classpath/javax/swing/Spring.java index 8f7105d..b9890c7 100644 --- a/libjava/classpath/javax/swing/Spring.java +++ b/libjava/classpath/javax/swing/Spring.java @@ -37,6 +37,9 @@ exception statement from your version. */ package javax.swing; +import java.awt.Component; +import java.awt.Dimension; + /** * Calculates the space between component edges, that are layed out by * {@link SpringLayout}. @@ -168,6 +171,139 @@ public abstract class Spring } /** + * Return a new Spring which computes its values by scaling + * the values of another spring by a constant factor. If the + * factor is negative, the minimum and maximum values of + * the argument spring will be interchanged. + * @param spring the spring to track + * @param factor the factor by which to scale + * @return a new multiplicative Spring + * @since 1.5 + */ + public static Spring scale(final Spring spring, final float factor) + { + if (spring == null) + throw new NullPointerException("spring argument is null"); + return new Spring() + { + public int getMaximumValue() + { + return (int) ((factor < 0 ? spring.getMinimumValue() + : spring.getMaximumValue()) + * factor); + } + + public int getMinimumValue() + { + return (int) ((factor < 0 ? spring.getMaximumValue() + : spring.getMinimumValue()) + * factor); + } + + public int getPreferredValue() + { + return (int) (spring.getPreferredValue() * factor); + } + + public int getValue() + { + return (int) (spring.getValue() * factor); + } + + public void setValue(int value) + { + spring.setValue((int) (value / factor)); + } + }; + } + + /** + * Return a new Spring which takes its values from the specified + * Component. In particular, the maximum value is taken from + * the maximumSize, the minimum value is taken from the minimumSize, + * the preferred value is taken from the preferredSize, and the + * value is taken from the component's current size. These values + * change as the component changes size. + * @param component the component + * @return a new Spring which tracks the component's width + * @since 1.5 + */ + public static Spring width(final Component component) + { + return new Spring() + { + public int getMaximumValue() + { + return component.getMaximumSize().width; + } + + public int getMinimumValue() + { + return component.getMinimumSize().width; + } + + public int getPreferredValue() + { + return component.getPreferredSize().width; + } + + public int getValue() + { + return component.getSize().width; + } + + public void setValue(int value) + { + Dimension d = component.getSize(); + component.setSize(value, d.height); + } + }; + } + + /** + * Return a new Spring which takes its values from the specified + * Component. In particular, the maximum value is taken from + * the maximumSize, the minimum value is taken from the minimumSize, + * the preferred value is taken from the preferredSize, and the + * value is taken from the component's current size. These values + * change as the component changes size. + * @param component the component + * @return a new Spring which tracks the component's height + * @since 1.5 + */ + public static Spring height(final Component component) + { + return new Spring() + { + public int getMaximumValue() + { + return component.getMaximumSize().height; + } + + public int getMinimumValue() + { + return component.getMinimumSize().height; + } + + public int getPreferredValue() + { + return component.getPreferredSize().height; + } + + public int getValue() + { + return component.getSize().height; + } + + public void setValue(int value) + { + Dimension d = component.getSize(); + component.setSize(d.width, value); + } + }; + } + + /** * A simple Spring, that holds constant values for min, pref and max. * * @author Roman Kennke (roman@ontographics.com) diff --git a/libjava/classpath/javax/swing/SpringLayout.java b/libjava/classpath/javax/swing/SpringLayout.java index 592cc0e..8d46a73 100644 --- a/libjava/classpath/javax/swing/SpringLayout.java +++ b/libjava/classpath/javax/swing/SpringLayout.java @@ -1,5 +1,5 @@ /* SpringLayout.java -- - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -150,6 +150,25 @@ public class SpringLayout implements LayoutManager2 } /** + * Create a new Constraints object which tracks the indicated + * component. The x and y positions for this Constraints object + * are constant Springs created with the component's location at + * the time this constructor is called. The width and height + * of this Constraints are Springs created using + * {@link Spring#width(Component)} and {@link Spring#height(Component)}, + * respectively. + * @param component the component to track + * @since 1.5 + */ + public Constraints(Component component) + { + this(Spring.constant(component.getX()), + Spring.constant(component.getY()), + Spring.width(component), + Spring.height(component)); + } + + /** * Returns the constraint for the edge with the edgeName. * This is expected to be one of * {@link #EAST}, {@link #WEST}, {@link #NORTH} or {@link #SOUTH}. @@ -343,8 +362,8 @@ public class SpringLayout implements LayoutManager2 /** * Adds a layout component and a constraint object to this layout. - * This method is usually only called by a {@java.awt.Container}s add - * Method. + * This method is usually only called by a {@link java.awt.Container}s add + * method. * * @param component the component to be added. * @param constraint the constraint to be set. @@ -357,8 +376,8 @@ public class SpringLayout implements LayoutManager2 /** * Adds a layout component and a constraint object to this layout. - * This method is usually only called by a {@java.awt.Container}s add - * Method. This method does nothing, since SpringLayout does not manage + * This method is usually only called by a {@link java.awt.Container}s add + * method. This method does nothing, since SpringLayout does not manage * String-indexed components. * * @param name the name. diff --git a/libjava/classpath/javax/swing/SwingUtilities.java b/libjava/classpath/javax/swing/SwingUtilities.java index 2d859b7..6762ccd 100644 --- a/libjava/classpath/javax/swing/SwingUtilities.java +++ b/libjava/classpath/javax/swing/SwingUtilities.java @@ -83,31 +83,6 @@ public class SwingUtilities { // Do nothing. } - - /** - * Calculates the portion of the base rectangle which is inside the - * insets. - * - * @param base The rectangle to apply the insets to - * @param insets The insets to apply to the base rectangle - * @param ret A rectangle to use for storing the return value, or - * null - * - * @return The calculated area inside the base rectangle and its insets, - * either stored in ret or a new Rectangle if ret is null - * - * @see #calculateInnerArea - */ - public static Rectangle calculateInsetArea(Rectangle base, Insets insets, - Rectangle ret) - { - if (ret == null) - ret = new Rectangle(); - ret.setBounds(base.x + insets.left, base.y + insets.top, - base.width - (insets.left + insets.right), - base.height - (insets.top + insets.bottom)); - return ret; - } /** * Calculates the portion of the component's bounds which is inside the @@ -122,13 +97,18 @@ public class SwingUtilities * * @return The calculated area inside the component and its border * insets - * - * @see #calculateInsetArea */ public static Rectangle calculateInnerArea(JComponent c, Rectangle r) { Rectangle b = getLocalBounds(c); - return calculateInsetArea(b, c.getInsets(), r); + if (r == null) + r = new Rectangle(); + Insets i = c.getInsets(); + r.x = b.x + i.left; + r.width = b.width - i.left - i.right; + r.y = b.y + i.top; + r.height = b.height - i.top - i.bottom; + return r; } /** @@ -1021,11 +1001,16 @@ public class SwingUtilities * * @return The common Frame */ - static Frame getOwnerFrame() + static Window getOwnerFrame(Window owner) { - if (ownerFrame == null) - ownerFrame = new OwnerFrame(); - return ownerFrame; + Window result = owner; + if (result == null) + { + if (ownerFrame == null) + ownerFrame = new OwnerFrame(); + result = ownerFrame; + } + return result; } /** @@ -1262,26 +1247,31 @@ public class SwingUtilities } /** - * Calculates the intersection of two rectangles. + * Calculates the intersection of two rectangles. The result is stored + * in rect. This is basically the same + * like {@link Rectangle#intersection(Rectangle)}, only that it does not + * create new Rectangle instances. The tradeoff is that you loose any data in + * rect. * * @param x upper-left x coodinate of first rectangle * @param y upper-left y coodinate of first rectangle * @param w width of first rectangle * @param h height of first rectangle * @param rect a Rectangle object of the second rectangle - * @throws NullPointerException if rect is null. + * + * @throws NullPointerException if rect is null * * @return a rectangle corresponding to the intersection of the - * two rectangles. A zero rectangle is returned if the rectangles - * do not overlap. + * two rectangles. An empty rectangle is returned if the rectangles + * do not overlap */ public static Rectangle computeIntersection(int x, int y, int w, int h, Rectangle rect) { - int x2 = (int) rect.getX(); - int y2 = (int) rect.getY(); - int w2 = (int) rect.getWidth(); - int h2 = (int) rect.getHeight(); + int x2 = (int) rect.x; + int y2 = (int) rect.y; + int w2 = (int) rect.width; + int h2 = (int) rect.height; int dx = (x > x2) ? x : x2; int dy = (y > y2) ? y : y2; @@ -1289,9 +1279,11 @@ public class SwingUtilities int dh = (y + h < y2 + h2) ? (y + h - dy) : (y2 + h2 - dy); if (dw >= 0 && dh >= 0) - return new Rectangle(dx, dy, dw, dh); + rect.setBounds(dx, dy, dw, dh); + else + rect.setBounds(0, 0, 0, 0); - return new Rectangle(0, 0, 0, 0); + return rect; } /** @@ -1308,26 +1300,31 @@ public class SwingUtilities } /** - * Calculates the union of two rectangles. + * Calculates the union of two rectangles. The result is stored in + * rect. This is basically the same as + * {@link Rectangle#union(Rectangle)} except that it avoids creation of new + * Rectangle objects. The tradeoff is that you loose any data in + * rect. * * @param x upper-left x coodinate of first rectangle * @param y upper-left y coodinate of first rectangle * @param w width of first rectangle * @param h height of first rectangle * @param rect a Rectangle object of the second rectangle - * @throws NullPointerException if rect is null. + * + * @throws NullPointerException if rect is null * * @return a rectangle corresponding to the union of the - * two rectangles. A rectangle encompassing both is returned if the - * rectangles do not overlap. + * two rectangles; a rectangle encompassing both is returned if the + * rectangles do not overlap */ public static Rectangle computeUnion(int x, int y, int w, int h, Rectangle rect) { - int x2 = (int) rect.getX(); - int y2 = (int) rect.getY(); - int w2 = (int) rect.getWidth(); - int h2 = (int) rect.getHeight(); + int x2 = (int) rect.x; + int y2 = (int) rect.y; + int w2 = (int) rect.width; + int h2 = (int) rect.height; int dx = (x < x2) ? x : x2; int dy = (y < y2) ? y : y2; @@ -1335,9 +1332,10 @@ public class SwingUtilities int dh = (y + h > y2 + h2) ? (y + h - dy) : (y2 + h2 - dy); if (dw >= 0 && dh >= 0) - return new Rectangle(dx, dy, dw, dh); - - return new Rectangle(0, 0, 0, 0); + rect.setBounds(dx, dy, dw, dh); + else + rect.setBounds(0, 0, 0, 0); + return rect; } /** diff --git a/libjava/classpath/javax/swing/Timer.java b/libjava/classpath/javax/swing/Timer.java index cf91c23..231b71d 100644 --- a/libjava/classpath/javax/swing/Timer.java +++ b/libjava/classpath/javax/swing/Timer.java @@ -68,11 +68,11 @@ public class Timer public void run() { if (logTimers) - System.out.println("javax.swing.Timer -> queueEvent()"); + System.out.println("javax.swing.Timer -> queueEvent()"); queueEvent(); if (!repeats) - task = null; + task = null; } } @@ -141,8 +141,9 @@ public class Timer /** * The task that calls queueEvent(). When null this Timer is stopped. + * This is package private to avoid synthetic accessor method. */ - private Task task; + Task task; /** * This object manages a "queue" of virtual actionEvents, maintained as a diff --git a/libjava/classpath/javax/swing/ToolTipManager.java b/libjava/classpath/javax/swing/ToolTipManager.java index 289149f..c7de4db 100644 --- a/libjava/classpath/javax/swing/ToolTipManager.java +++ b/libjava/classpath/javax/swing/ToolTipManager.java @@ -40,9 +40,6 @@ package javax.swing; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.LayoutManager; -import java.awt.Panel; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; diff --git a/libjava/classpath/javax/swing/UIManager.java b/libjava/classpath/javax/swing/UIManager.java index fbf1c7c..bf8739d 100644 --- a/libjava/classpath/javax/swing/UIManager.java +++ b/libjava/classpath/javax/swing/UIManager.java @@ -43,11 +43,11 @@ import java.awt.Dimension; import java.awt.Font; import java.awt.Insets; import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; import java.io.Serializable; import java.util.Locale; import javax.swing.border.Border; -import javax.swing.event.SwingPropertyChangeSupport; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.metal.MetalLookAndFeel; @@ -138,8 +138,8 @@ public class UIManager implements Serializable static UIDefaults userUIDefaults; /** Property change listener mechanism. */ - static SwingPropertyChangeSupport listeners - = new SwingPropertyChangeSupport(UIManager.class); + static PropertyChangeSupport listeners + = new PropertyChangeSupport(UIManager.class); static { diff --git a/libjava/classpath/javax/swing/UnsupportedLookAndFeelException.java b/libjava/classpath/javax/swing/UnsupportedLookAndFeelException.java index f99c0ac..b65119a 100644 --- a/libjava/classpath/javax/swing/UnsupportedLookAndFeelException.java +++ b/libjava/classpath/javax/swing/UnsupportedLookAndFeelException.java @@ -1,5 +1,5 @@ /* UnsupportedLookAndFeelException.java -- - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -37,11 +37,21 @@ exception statement from your version. */ package javax.swing; - +/** + * Thrown by the {@link UIManager#setLookAndFeel(LookAndFeel)} method when the + * specified look and feel is not supported on the current platform. + * + * @see LookAndFeel#isSupportedLookAndFeel() + */ public class UnsupportedLookAndFeelException extends Exception { - public UnsupportedLookAndFeelException(String a) + /** + * Creates a new exception instance with the specified message. + * + * @param s the exception message. + */ + public UnsupportedLookAndFeelException(String s) { - super(a); + super(s); } } diff --git a/libjava/classpath/javax/swing/ViewportLayout.java b/libjava/classpath/javax/swing/ViewportLayout.java index 79fd26c..674de95 100644 --- a/libjava/classpath/javax/swing/ViewportLayout.java +++ b/libjava/classpath/javax/swing/ViewportLayout.java @@ -1,5 +1,5 @@ /* ViewportLayout.java -- - Copyright (C) 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -46,9 +46,16 @@ import java.awt.Rectangle; import java.io.Serializable; /** - * ViewportLayout - * @author Andrew Selkirk - * @author Graydon Hoare + * The default layout for {@link JViewport}. The viewport makes its view the + * same size as itself, but not smaller than its minimum size. + * + * If the port extends extends into space past the edge of the view, + * this layout manager moves the port up or to the left, in view space, by the + * amount of empty space (keep the lower and right edges lined up). + * + * @author Andrew Selkirk + * @author Graydon Hoare + * @author Audrius Meskauskas (audriusa@Bioinformatics.org) */ public class ViewportLayout implements LayoutManager, Serializable { @@ -58,17 +65,31 @@ public class ViewportLayout implements LayoutManager, Serializable { // Nothing to do here. } - + + /** + * The method is not used with this manager. + */ public void addLayoutComponent(String name, Component c) { // Nothing to do here. } + /** + * The method is not used with this manager. + */ public void removeLayoutComponent(Component c) { // Nothing to do here. } - + + /** + * Get the preferred layout size. If the view implements + * {@link Scrollable}, this method returns + * {@link Scrollable#getPreferredScrollableViewportSize}. + * Otherwise, it returns {@link Component#getPreferredSize()}. + * + * @return the preferred layout size, as described about. + */ public Dimension preferredLayoutSize(Container parent) { JViewport vp = (JViewport)parent; @@ -83,14 +104,19 @@ public class ViewportLayout implements LayoutManager, Serializable return new Dimension(); } + /** + * Get the minimum layout size. Normally this method returns the value, + * returned by the view method {@link Component#getMinimumSize()}. + * + * If the view is not set, the zero size is returned. + * + * @param parent the viewport + * @return the minimum layout size. + */ public Dimension minimumLayoutSize(Container parent) { - JViewport vp = (JViewport)parent; - Component view = vp.getView(); - if (view != null) - return view.getMinimumSize(); - else - return new Dimension(); + // These values have been determined by the Mauve test for this method. + return new Dimension(4, 4); } /** @@ -101,15 +127,13 @@ public class ViewportLayout implements LayoutManager, Serializable * *
    * - *
  1. If the port is larger than the view's minimum size, put the port - * at view position (0,0) and make the view's size equal to - * the port's.
  2. - * *
  3. If the port is smaller than the view, leave the view at its - * minimum size. also, do not move the port, unless the port + * current size. Also, do not move the port, unless the port * extends into space past the edge of the view. If so, move the * port up or to the left, in view space, by the amount of empty space * (keep the lower and right edges lined up)
  4. + *
  5. In {@link JViewport#setViewSize(Dimension)}, the view size is never + * set smaller that its minimum size.
  6. * *
* @@ -118,7 +142,6 @@ public class ViewportLayout implements LayoutManager, Serializable * @see JViewport#getViewPosition * @see JViewport#setViewPosition */ - public void layoutContainer(Container parent) { // The way to interpret this function is basically to ignore the names @@ -141,23 +164,22 @@ public class ViewportLayout implements LayoutManager, Serializable Rectangle portBounds = port.getViewRect(); Dimension viewPref = view.getPreferredSize(); Dimension viewMinimum = view.getMinimumSize(); + Point portLowerRight = new Point(portBounds.x + portBounds.width, portBounds.y + portBounds.height); + int overextension; // vertical implementation of the above rules if ((! (view instanceof Scrollable) && viewPref.height < portBounds.height || (view instanceof Scrollable && ((Scrollable) view).getScrollableTracksViewportHeight()))) viewPref.height = portBounds.height; - - if (portBounds.height >= viewMinimum.height) - portBounds.y = 0; - else - { - int overextension = portLowerRight.y - viewPref.height; - if (overextension > 0) - portBounds.y -= overextension; - } + + // If the view is larger than the port, and port is partly outside + // the view, it is moved fully into the view area. + overextension = portLowerRight.y - viewPref.height; + if (overextension > 0) + portBounds.y -= overextension; // horizontal implementation of the above rules if ((! (view instanceof Scrollable) && viewPref.width < portBounds.width @@ -165,16 +187,13 @@ public class ViewportLayout implements LayoutManager, Serializable && ((Scrollable) view).getScrollableTracksViewportWidth()))) viewPref.width = portBounds.width; - if (portBounds.width >= viewMinimum.width) - portBounds.x = 0; - else - { - int overextension = portLowerRight.x - viewPref.width; - if (overextension > 0) - portBounds.x -= overextension; - } + // If the view is larger than the port, and port is partly outside + // the view, it is moved fully into the view area. + overextension = portLowerRight.x - viewPref.width; + if (overextension > 0) + portBounds.x -= overextension; - port.setViewPosition(portBounds.getLocation()); port.setViewSize(viewPref); + port.setViewPosition(portBounds.getLocation()); } } diff --git a/libjava/classpath/javax/swing/event/CaretEvent.java b/libjava/classpath/javax/swing/event/CaretEvent.java index c4870a8..7de05a8 100644 --- a/libjava/classpath/javax/swing/event/CaretEvent.java +++ b/libjava/classpath/javax/swing/event/CaretEvent.java @@ -1,5 +1,5 @@ /* CaretEvent.java -- - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -37,43 +37,34 @@ exception statement from your version. */ package javax.swing.event; -// Imports import java.util.EventObject; /** * CaretEvent * @author Andrew Selkirk */ -public abstract class CaretEvent extends EventObject { +public abstract class CaretEvent extends EventObject +{ - //------------------------------------------------------------- - // Initialization --------------------------------------------- - //------------------------------------------------------------- - - /** - * CaretEvent constructor - * @param source Source object - */ - public CaretEvent(Object source) { - super(source); - } // CaretEvent() + /** + * CaretEvent constructor + * @param source Source object + */ + public CaretEvent(Object source) + { + super(source); + } - - //------------------------------------------------------------- - // Methods ---------------------------------------------------- - //------------------------------------------------------------- - - /** - * Get caret location - * @returns the dot - */ - public abstract int getDot(); + /** + * Get caret location + * @return the dot + */ + public abstract int getDot(); - /** - * Get mark - * @returns the mark - */ - public abstract int getMark(); + /** + * Get mark + * @return the mark + */ + public abstract int getMark(); - -} // CaretEvent +} diff --git a/libjava/classpath/javax/swing/event/DocumentEvent.java b/libjava/classpath/javax/swing/event/DocumentEvent.java index 6cd8e61..8223049 100644 --- a/libjava/classpath/javax/swing/event/DocumentEvent.java +++ b/libjava/classpath/javax/swing/event/DocumentEvent.java @@ -1,5 +1,5 @@ /* DocumentEvent.java -- - Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -54,25 +54,25 @@ public interface DocumentEvent { /** * getIndex - * @returns int + * @return int */ int getIndex(); /** * getElement - * @returns Element + * @return Element */ Element getElement(); /** * getChildrenRemoved - * @returns Element[] + * @return Element[] */ Element[] getChildrenRemoved(); /** * getChildrenAdded - * @returns Element[] + * @return Element[] */ Element[] getChildrenAdded(); @@ -81,7 +81,7 @@ public interface DocumentEvent /** * EventType */ - class EventType + final class EventType { /** * INSERT @@ -114,7 +114,7 @@ public interface DocumentEvent /** * toString - * @returns String + * @return String */ public String toString() { @@ -124,32 +124,32 @@ public interface DocumentEvent /** * getType - * @returns EventType + * @return EventType */ EventType getType(); /** * getOffset - * @returns int + * @return int */ int getOffset(); /** * getLength - * @returns int + * @return int */ int getLength(); /** * getDocument - * @returns Document + * @return Document */ Document getDocument(); /** * getChange * @param element TODO - * @returns ElementChange + * @return ElementChange */ ElementChange getChange(Element element); diff --git a/libjava/classpath/javax/swing/event/EventListenerList.java b/libjava/classpath/javax/swing/event/EventListenerList.java index 147d68e..a7fbec4 100644 --- a/libjava/classpath/javax/swing/event/EventListenerList.java +++ b/libjava/classpath/javax/swing/event/EventListenerList.java @@ -188,7 +188,7 @@ public class EventListenerList /** * Get a list of listenerType/listener pairs - * @returns Listener list + * @return Listener list */ public Object[] getListenerList() { @@ -214,7 +214,7 @@ public class EventListenerList * @throws NullPointerException if c is * null. * - * @returns an array of c whose elements are the + * @return an array of c whose elements are the * currently subscribed listeners of the specified type. If there * are no such listeners, an empty array is returned. * diff --git a/libjava/classpath/javax/swing/event/ListSelectionEvent.java b/libjava/classpath/javax/swing/event/ListSelectionEvent.java index e5e4c33..d79cbfa 100644 --- a/libjava/classpath/javax/swing/event/ListSelectionEvent.java +++ b/libjava/classpath/javax/swing/event/ListSelectionEvent.java @@ -1,5 +1,5 @@ /* ListSelectionEvent.java -- - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -37,90 +37,99 @@ exception statement from your version. */ package javax.swing.event; -// Imports import java.util.EventObject; +import javax.swing.ListSelectionModel; + /** - * ListSelectionEvent + * An event that indicates a change to a list selection, including the source + * of the change (a {@link ListSelectionModel}) and the range of items in the + * list that have potentially changed their selection status. + * * @author Andrew Selkirk * @author Ronald Veldema */ -public class ListSelectionEvent extends EventObject { - - //------------------------------------------------------------- - // Variables -------------------------------------------------- - //------------------------------------------------------------- - - /** - * firstIndex - */ - private int firstIndex = 0; - - /** - * lastIndex - */ - private int lastIndex = 0; - - /** - * isAdjusting - */ - private boolean isAdjusting = false; - - //------------------------------------------------------------- - // Initialization --------------------------------------------- - //------------------------------------------------------------- - - /** - * Constructor ListSelectionEvent - * @param source Source - * @param firstIndex First index - * @param lastIndex Last index - * @param isAdjusting Is Adjusting? - */ - public ListSelectionEvent(Object source, int firstIndex, - int lastIndex, boolean isAdjusting) { - super(source); - this.firstIndex = firstIndex; - this.lastIndex = lastIndex; - this.isAdjusting = isAdjusting; - } // ListSelectionEvent() - - - //------------------------------------------------------------- - // Methods ---------------------------------------------------- - //------------------------------------------------------------- - - /** - * getFirstIndex - * @returns firstIndex - */ - public int getFirstIndex() { - return firstIndex; - } // getFirstIndex() - - /** - * getLastIndex - * @returns lastIndex - */ - public int getLastIndex() { - return lastIndex; - } // getLastIndex() - - /** - * getValueIsAdjusting - * @returns isAdjusting - */ - public boolean getValueIsAdjusting() { - return isAdjusting; - } // getValueIsAdjusting() - - /** - * String representation - * @returns String representation - */ - public String toString() { - return null; // TODO - } // toString() - - -} // ListSelectionEvent +public class ListSelectionEvent extends EventObject +{ + + /** + * The index of the first list item in the range of items that has + * potentially had its selection status modified. + */ + private int firstIndex = 0; + + /** + * The index of the last list item in the range of items that has + * potentially had its selection status modified. + */ + private int lastIndex = 0; + + /** A flag that indicates that this event is one in a series of events. */ + private boolean isAdjusting = false; + + /** + * Creates a new ListSelectionEvent. + * + * @param source the event source (null not permitted). + * @param firstIndex the first index. + * @param lastIndex the last index. + * @param isAdjusting a flag indicating that this event is one in a series + * of events updating a selection. + * + * @throws IllegalArgumentException if source is + * null. + */ + public ListSelectionEvent(Object source, int firstIndex, + int lastIndex, boolean isAdjusting) + { + super(source); + this.firstIndex = firstIndex; + this.lastIndex = lastIndex; + this.isAdjusting = isAdjusting; + } + + /** + * Returns the first index. + * + * @return The first index. + */ + public int getFirstIndex() + { + return firstIndex; + } + + /** + * Returns the last index. + * + * @return The last index. + */ + public int getLastIndex() + { + return lastIndex; + } + + /** + * Returns the flag that indicates that this event is one in a series of + * events updating a selection. + * + * @return A boolean. + */ + public boolean getValueIsAdjusting() + { + return isAdjusting; + } + + /** + * Returns a string representation of the event, typically used for debugging + * purposes. + * + * @return A string representation of the event. + */ + public String toString() + { + return this.getClass().toString() + "[ source=" + source.toString() + + " firstIndex= " + firstIndex + " lastIndex= " + lastIndex + + " isAdjusting= " + isAdjusting + " ]"; + } + +} diff --git a/libjava/classpath/javax/swing/event/ListSelectionListener.java b/libjava/classpath/javax/swing/event/ListSelectionListener.java index 4ebf583..a21dc73 100644 --- a/libjava/classpath/javax/swing/event/ListSelectionListener.java +++ b/libjava/classpath/javax/swing/event/ListSelectionListener.java @@ -1,5 +1,5 @@ /* ListSelectionListener.java -- - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -37,21 +37,25 @@ exception statement from your version. */ package javax.swing.event; -// Imports import java.util.EventListener; +import javax.swing.ListSelectionModel; + /** - * ListSelectionListener public interface + * A listener that receives {@link ListSelectionEvent} notifications, + * typically from a {@link ListSelectionModel} when it is modified. + * * @author Andrew Selkirk * @author Ronald Veldema */ -public interface ListSelectionListener extends EventListener { - - /** - * Value changed - * @param event List Selection Event - */ - void valueChanged(ListSelectionEvent event); +public interface ListSelectionListener extends EventListener +{ + /** + * Receives notification of a {@link ListSelectionEvent}. + * + * @param event the event. + */ + void valueChanged(ListSelectionEvent event); -} // ListSelectionListener +} \ No newline at end of file diff --git a/libjava/classpath/javax/swing/event/MenuDragMouseEvent.java b/libjava/classpath/javax/swing/event/MenuDragMouseEvent.java index 9976167..6be11bc 100644 --- a/libjava/classpath/javax/swing/event/MenuDragMouseEvent.java +++ b/libjava/classpath/javax/swing/event/MenuDragMouseEvent.java @@ -1,5 +1,5 @@ /* MenuDragMouseEvent.java -- - Copyright (C) 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -48,68 +48,57 @@ import javax.swing.MenuSelectionManager; * MenuDragMouseEvent * @author Andrew Selkirk */ -public class MenuDragMouseEvent extends MouseEvent { +public class MenuDragMouseEvent extends MouseEvent +{ - //------------------------------------------------------------- - // Variables -------------------------------------------------- - //------------------------------------------------------------- - - /** - * path - */ - private MenuElement[] path = null; + /** + * path + */ + private MenuElement[] path = null; - /** - * manager - */ - private MenuSelectionManager manager = null; - - - //------------------------------------------------------------- - // Initialization --------------------------------------------- - //------------------------------------------------------------- - - /** - * Constructor MenuDragMouseEvent - * @param source Source - * @param id MouseEvent type - * @param when Time - * @param modifiers Key modifiers - * @param x Horizontal position - * @param y Vertical position - * @param clickCount Click count - * @param popupTrigger Popup trigger? - * @param path Path - * @param manager MenuSelectionManager - */ - public MenuDragMouseEvent(Component source, int id, long when, int modifiers, - int x, int y, int clickCount, boolean popupTrigger, - MenuElement[] path, MenuSelectionManager manager) { - super(source, id, when, modifiers, x, y, clickCount, popupTrigger); - this.path = path; - this.manager = manager; - } // MenuDragMouseEvent() - - - //------------------------------------------------------------- - // Methods ---------------------------------------------------- - //------------------------------------------------------------- - - /** - * Get path - * @returns path - */ - public MenuElement[] getPath() { - return path; - } // getPath() - - /** - * Get menu selection manager - * @returns manager - */ - public MenuSelectionManager getMenuSelectionManager() { - return manager; - } // getMenuSelectionManager() - - -} // MenuDragMouseEvent + /** + * manager + */ + private MenuSelectionManager manager = null; + + /** + * Constructor MenuDragMouseEvent + * @param source Source + * @param id MouseEvent type + * @param when Time + * @param modifiers Key modifiers + * @param x Horizontal position + * @param y Vertical position + * @param clickCount Click count + * @param popupTrigger Popup trigger? + * @param path Path + * @param manager MenuSelectionManager + */ + public MenuDragMouseEvent(Component source, int id, long when, int modifiers, + int x, int y, int clickCount, boolean popupTrigger, + MenuElement[] path, MenuSelectionManager manager) + { + super(source, id, when, modifiers, x, y, clickCount, popupTrigger); + this.path = path; + this.manager = manager; + } + + /** + * Get path + * @return path + */ + public MenuElement[] getPath() + { + return path; + } + + /** + * Get menu selection manager + * @return manager + */ + public MenuSelectionManager getMenuSelectionManager() + { + return manager; + } + +} diff --git a/libjava/classpath/javax/swing/event/MenuKeyEvent.java b/libjava/classpath/javax/swing/event/MenuKeyEvent.java index 511cb22..3335850 100644 --- a/libjava/classpath/javax/swing/event/MenuKeyEvent.java +++ b/libjava/classpath/javax/swing/event/MenuKeyEvent.java @@ -1,5 +1,5 @@ /* MenuKeyEvent.java -- - Copyright (C) 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -48,66 +48,55 @@ import javax.swing.MenuSelectionManager; * MenuKeyEvent * @author Andrew Selkirk */ -public class MenuKeyEvent extends KeyEvent { +public class MenuKeyEvent extends KeyEvent +{ - //------------------------------------------------------------- - // Variables -------------------------------------------------- - //------------------------------------------------------------- - - /** - * path - */ - private MenuElement[] path = null; + /** + * path + */ + private MenuElement[] path = null; - /** - * manager - */ - private MenuSelectionManager manager = null; - - - //------------------------------------------------------------- - // Initialization --------------------------------------------- - //------------------------------------------------------------- - - /** - * Constructor MenuKeyEvent - * @param source Source - * @param id KeyEvent ID - * @param when Time - * @param modifiers Modifier keys - * @param keyCode Key code - * @param keyChar Key char - * @param path Path - * @param manager MenuSelectionManager - */ - public MenuKeyEvent(Component source, int id, long when, int modifiers, - int keyCode, char keyChar, MenuElement[] path, - MenuSelectionManager manager) { - super(source, id, when, modifiers, keyCode, keyChar); - this.path = path; - this.manager = manager; - } // MenuKeyEvent() - - - //------------------------------------------------------------- - // Methods ---------------------------------------------------- - //------------------------------------------------------------- - - /** - * getPath - * @returns path - */ - public MenuElement[] getPath() { - return path; - } // getPath() - - /** - * getMenuSelectionManager - * @returns MenuSelectionManager - */ - public MenuSelectionManager getMenuSelectionManager() { - return manager; - } // getMenuSelectionManager() - - -} // MenuKeyEvent + /** + * manager + */ + private MenuSelectionManager manager = null; + + /** + * Constructor MenuKeyEvent + * @param source Source + * @param id KeyEvent ID + * @param when Time + * @param modifiers Modifier keys + * @param keyCode Key code + * @param keyChar Key char + * @param path Path + * @param manager MenuSelectionManager + */ + public MenuKeyEvent(Component source, int id, long when, int modifiers, + int keyCode, char keyChar, MenuElement[] path, + MenuSelectionManager manager) + { + super(source, id, when, modifiers, keyCode, keyChar); + this.path = path; + this.manager = manager; + } + + /** + * getPath + * @return path + */ + public MenuElement[] getPath() + { + return path; + } + + /** + * getMenuSelectionManager + * @return MenuSelectionManager + */ + public MenuSelectionManager getMenuSelectionManager() + { + return manager; + } + +} diff --git a/libjava/classpath/javax/swing/event/SwingPropertyChangeSupport.java b/libjava/classpath/javax/swing/event/SwingPropertyChangeSupport.java index 7e8ff0d..7fb8aa6 100644 --- a/libjava/classpath/javax/swing/event/SwingPropertyChangeSupport.java +++ b/libjava/classpath/javax/swing/event/SwingPropertyChangeSupport.java @@ -1,5 +1,5 @@ /* SwingPropertyChangeSupport.java -- - Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -39,48 +39,24 @@ package javax.swing.event; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeListenerProxy; import java.beans.PropertyChangeSupport; -import java.util.ArrayList; -import java.util.EventListener; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; /** * Provides a mechanism for registering {@link PropertyChangeListener}s and * forwarding {@link PropertyChangeEvent}s to those listeners. - * + * + * As of JDK1.5 this class is no longer in use. Use + * {@link PropertyChangeSupport} instead. + * * @author Andrew Selkirk */ public final class SwingPropertyChangeSupport - extends PropertyChangeSupport + extends PropertyChangeSupport { private static final long serialVersionUID = 7162625831330845068L; /** - * Storage for the listeners that are not linked to a specific property. - */ - private transient EventListenerList listeners; - - /** - * Storage for the listeners that are linked (by name) to a specific property. - * The hash table maps String objects (the property names) to - * {@link EventListenerList} instances (which record the listener(s) for the - * given property). - */ - private Hashtable propertyListeners; - - /** - * The object that is used as the default source for the - * {@link PropertyChangeEvent}s generated by this class. - */ - private Object source; - - /** * Creates a new instance. * * @param source the source (null not permitted). @@ -90,247 +66,5 @@ public final class SwingPropertyChangeSupport public SwingPropertyChangeSupport(Object source) { super(source); - this.source = source; - this.listeners = new EventListenerList(); - this.propertyListeners = new Hashtable(); } - - /** - * Registers listener to receive notification of any future - * {@link PropertyChangeEvent}s generated by this instance. - * - * @param listener the listener (null is ignored). - * - * @see #removePropertyChangeListener(PropertyChangeListener) - */ - public synchronized void addPropertyChangeListener(PropertyChangeListener - listener) - { - listeners.add(PropertyChangeListener.class, listener); - } - - /** - * Registers listener to receive notification of any future - * {@link PropertyChangeEvent}s generated by this instance for the named - * property. - * - * @param propertyName the property name. - * @param listener the listener. - * - * @see #removePropertyChangeListener(String, PropertyChangeListener) - */ - public synchronized void addPropertyChangeListener(String propertyName, - PropertyChangeListener listener) - { - EventListenerList list; - list = (EventListenerList) propertyListeners.get(propertyName); - if (list == null) - { - list = new EventListenerList(); - propertyListeners.put(propertyName, list); - } - list.add(PropertyChangeListener.class, listener); - } - - /** - * Removes listener from the list of registered listeners, so - * that it will no longer receive notification of property change events. - * - * @param listener the listener to remove. - */ - public synchronized void removePropertyChangeListener(PropertyChangeListener - listener) - { - listeners.remove(PropertyChangeListener.class, listener); - } - - /** - * Removes listener from the list of registered listeners for - * the named property, so that it will no longer receive notification of - * property change events. - * - * @param propertyName the property name. - * @param listener the listener to remove. - */ - public synchronized void removePropertyChangeListener(String propertyName, - PropertyChangeListener listener) - { - EventListenerList list; - list = (EventListenerList) propertyListeners.get(propertyName); - if (list == null) - return; - list.remove(PropertyChangeListener.class, listener); - if (list.getListenerCount() == 0) - { - propertyListeners.remove(propertyName); - } - } - - /** - * Returns an array of the {@link PropertyChangeListener}s registered with - * this SwingPropertyChangeSupport instance. - * - * @return The array of listeners. - * - * @since 1.4 - */ - public synchronized PropertyChangeListener[] getPropertyChangeListeners() - { - // fetch the named listeners first so we know how many there are - List namedListeners = new ArrayList(); - Set namedListenerEntries = propertyListeners.entrySet(); - Iterator iterator = namedListenerEntries.iterator(); - while (iterator.hasNext()) - { - Map.Entry e = (Map.Entry) iterator.next(); - String propertyName = (String) e.getKey(); - EventListenerList ell = (EventListenerList) e.getValue(); - if (ell != null) - { - Object[] list = ell.getListenerList(); - for (int i = 0; i < list.length; i += 2) - { - namedListeners.add(new PropertyChangeListenerProxy(propertyName, - (PropertyChangeListener) list[i + 1])); - } - } - } - - // create an array that can hold everything - int size = listeners.getListenerCount() + namedListeners.size(); - PropertyChangeListener[] result = new PropertyChangeListener[size]; - - // copy in the general listeners - Object[] list = listeners.getListenerList(); - int index = 0; - for (int i = 0; i < list.length; i += 2) - result[index++] = (PropertyChangeListener) list[i + 1]; - - // ...and the named listeners - Iterator iterator2 = namedListeners.iterator(); - while (iterator2.hasNext()) - result[index++] = (PropertyChangeListenerProxy) iterator2.next(); - - return result; - } - - /** - * Returns an array of all listeners that are registered to receive - * notification of changes to the named property. This includes the general - * listeners as well as those registered specifically for the named - * property. - * - * @param propertyName the property name. - * - * @return An array of all listeners for the named property. - */ - public synchronized PropertyChangeListener[] getPropertyChangeListeners( - String propertyName) - { - EventListenerList list - = (EventListenerList) propertyListeners.get(propertyName); - if (list == null) - return getPropertyChangeListeners(); - int size = listeners.getListenerCount() + list.getListenerCount(); - PropertyChangeListener[] result = new PropertyChangeListener[size]; - - // copy in the general listeners - int index = 0; - for (int i = 0; i < listeners.listenerList.length; i += 2) - { - result[index++] - = (PropertyChangeListener) listeners.listenerList[i + 1]; - } - - // copy in the specific listeners - Object[] specificListeners = list.getListenerList(); - for (int i = 0; i < specificListeners.length; i += 2) - { - result[index++] = (PropertyChangeListener) specificListeners[i + 1]; - } - return result; - } - - /** - * Creates a new {@link PropertyChangeEvent} using the given arguments (and - * the default source for this - * SwingPropertyChangeSupport instance) and forwards it to all - * registered listeners via the - * {@link PropertyChangeListener#propertyChange(PropertyChangeEvent)} method. - *

- * Note that if oldValue and newValue are non-null - * and equal, no listeners will be notified. - * - * @param propertyName the property name. - * @param oldValue the old value - * @param newValue the new value. - */ - public void firePropertyChange(String propertyName, Object oldValue, - Object newValue) - { - PropertyChangeEvent event; - event = new PropertyChangeEvent(source, propertyName, oldValue, newValue); - firePropertyChange(event); - } - - /** - * Forwards event to registered listeners. - *

- * Note that if the event's getOldValue() and - * getNewValue() methods return non-null and equal values, no - * listeners will be notified. - * - * @param event the event. - */ - public void firePropertyChange(PropertyChangeEvent event) - { - EventListenerList list; - EventListener[] listenerList; - int index; - PropertyChangeListener listener; - - // if the old and new values are non-null and equal, don't notify listeners - if (event.getOldValue() != null && event.getNewValue() != null && - event.getOldValue().equals(event.getNewValue())) - return; - - // Process Main Listener List - listenerList = listeners.getListeners(PropertyChangeListener.class); - for (index = 0; index < listenerList.length; index++) - { - listener = (PropertyChangeListener) listenerList[index]; - listener.propertyChange(event); - } - - // Process Property Listener List - list = (EventListenerList) propertyListeners.get(event.getPropertyName()); - if (list != null) - { - listenerList = list.getListeners(PropertyChangeListener.class); - for (index = 0; index < listenerList.length; index++) - { - listener = (PropertyChangeListener) listenerList[index]; - listener.propertyChange(event); - } - } - - } - - /** - * Tell whether the specified property is being listened on or not. This - * will only return true if there are listeners on all - * properties or if there is a listener specifically on this property. - * - * @param propertyName the property that may be listened on - * @return whether the property is being listened on - * @throws NullPointerException if propertyName is null - */ - public synchronized boolean hasListeners(String propertyName) - { - if (listeners.getListenerCount() > 0) - return true; - else - return (propertyListeners.get(propertyName) != null); - } - } diff --git a/libjava/classpath/javax/swing/event/TableColumnModelEvent.java b/libjava/classpath/javax/swing/event/TableColumnModelEvent.java index 2ca4148..cff4913 100644 --- a/libjava/classpath/javax/swing/event/TableColumnModelEvent.java +++ b/libjava/classpath/javax/swing/event/TableColumnModelEvent.java @@ -1,5 +1,5 @@ /* TableColumnModelEvent.java -- - Copyright (C) 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -46,60 +46,48 @@ import javax.swing.table.TableColumnModel; * TableColumnModelEvent * @author Andrew Selkirk */ -public class TableColumnModelEvent extends EventObject { - - //------------------------------------------------------------- - // Variables -------------------------------------------------- - //------------------------------------------------------------- - - /** - * fromIndex - */ - protected int fromIndex = 0; - - /** - * toIndex - */ - protected int toIndex = 0; - - - //------------------------------------------------------------- - // Initialization --------------------------------------------- - //------------------------------------------------------------- - - /** - * Constructor TableColumnModelEvent - * @param source Source TableColumnModel - * @param from From index - * @param to To index - */ - public TableColumnModelEvent(TableColumnModel source, - int from, int to) { - super(source); - fromIndex = from; - toIndex = to; - } // TableColumnModelEvent() - - - //------------------------------------------------------------- - // Methods ---------------------------------------------------- - //------------------------------------------------------------- - - /** - * getFromIndex. - * @returns From index - */ - public int getFromIndex() { - return fromIndex; - } // getFromIndex() - - /** - * getToIndex. - * @returns To index - */ - public int getToIndex() { - return toIndex; - } // getToIndex() - - -} // TableColumnModelEvent +public class TableColumnModelEvent extends EventObject +{ + + /** + * fromIndex + */ + protected int fromIndex = 0; + + /** + * toIndex + */ + protected int toIndex = 0; + + /** + * Constructor TableColumnModelEvent + * @param source Source TableColumnModel + * @param from From index + * @param to To index + */ + public TableColumnModelEvent(TableColumnModel source, int from, int to) + { + super(source); + fromIndex = from; + toIndex = to; + } + + /** + * getFromIndex. + * @return From index + */ + public int getFromIndex() + { + return fromIndex; + } + + /** + * getToIndex. + * @return To index + */ + public int getToIndex() + { + return toIndex; + } + +} \ No newline at end of file diff --git a/libjava/classpath/javax/swing/event/TableModelListener.java b/libjava/classpath/javax/swing/event/TableModelListener.java index c8d6e8f8..21e5ea0 100644 --- a/libjava/classpath/javax/swing/event/TableModelListener.java +++ b/libjava/classpath/javax/swing/event/TableModelListener.java @@ -1,5 +1,5 @@ /* TableModelListener.java -- - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -40,16 +40,21 @@ package javax.swing.event; import java.util.EventListener; /** - * TableModelListener public interface + * A TableModelListener can register with a + * {@link javax.swing.table.TableModel} and receive notification of updates to + * the model. + * * @author Andrew Selkirk */ -public interface TableModelListener extends EventListener { - - /** - * Table changed - * @param event Table Model Event - */ - void tableChanged(TableModelEvent event); - - -} // TableModelListener +public interface TableModelListener extends EventListener +{ + + /** + * Called to notify the listener that the + * {@link javax.swing.table.TableModel} has been updated. + * + * @param event contains details of the update. + */ + void tableChanged(TableModelEvent event); + +} diff --git a/libjava/classpath/javax/swing/event/TreeExpansionEvent.java b/libjava/classpath/javax/swing/event/TreeExpansionEvent.java index c4b3313..5820b33 100644 --- a/libjava/classpath/javax/swing/event/TreeExpansionEvent.java +++ b/libjava/classpath/javax/swing/event/TreeExpansionEvent.java @@ -1,5 +1,5 @@ /* TreeExpansionEvent.java -- - Copyright (C) 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -46,44 +46,32 @@ import javax.swing.tree.TreePath; * TreeExpansionEvent * @author Andrew Selkirk */ -public class TreeExpansionEvent extends EventObject { - - //------------------------------------------------------------- - // Variables -------------------------------------------------- - //------------------------------------------------------------- - - /** - * path - */ - protected TreePath path = null; - - - //------------------------------------------------------------- - // Initialization --------------------------------------------- - //------------------------------------------------------------- - - /** - * Constructor TreeExpansionEvent - * @param source Source object - * @param path Path - */ - public TreeExpansionEvent(Object source, TreePath path) { - super(source); - this.path = path; - } // TreeExpansionEvent() - - - //------------------------------------------------------------- - // Methods ---------------------------------------------------- - //------------------------------------------------------------- - - /** - * getPath - * @returns Tree path - */ - public TreePath getPath() { - return path; - } // getPath() - - -} // TreeExpansionEvent +public class TreeExpansionEvent extends EventObject +{ + + /** + * path + */ + protected TreePath path = null; + + /** + * Constructor TreeExpansionEvent + * @param source Source object + * @param path Path + */ + public TreeExpansionEvent(Object source, TreePath path) + { + super(source); + this.path = path; + } + + /** + * getPath + * @return Tree path + */ + public TreePath getPath() + { + return path; + } + +} diff --git a/libjava/classpath/javax/swing/event/TreeModelEvent.java b/libjava/classpath/javax/swing/event/TreeModelEvent.java index 8fa28a7..2d562a5 100644 --- a/libjava/classpath/javax/swing/event/TreeModelEvent.java +++ b/libjava/classpath/javax/swing/event/TreeModelEvent.java @@ -1,5 +1,5 @@ /* TreeModelEvent.java -- - Copyright (C) 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -46,128 +46,123 @@ import javax.swing.tree.TreePath; * TreeModelEvent * @author Andrew Selkirk */ -public class TreeModelEvent extends EventObject { - - //------------------------------------------------------------- - // Variables -------------------------------------------------- - //------------------------------------------------------------- - - /** - * childIndices - */ - protected int[] childIndices = null; - - /** - * children - */ - protected Object[] children = null; - - /** - * path - */ - protected TreePath path = null; - - - //------------------------------------------------------------- - // Initialization --------------------------------------------- - //------------------------------------------------------------- +public class TreeModelEvent extends EventObject +{ + + /** + * childIndices + */ + protected int[] childIndices = null; + + /** + * children + */ + protected Object[] children = null; + + /** + * path + */ + protected TreePath path = null; - /** - * Constructor TreeModelEvent - * @param source Source object - * @param path - */ - public TreeModelEvent(Object source, Object[] path) { - super(source); - this.path = new TreePath(path); - } // TreeModelEvent() - - /** - * Constructor TreeModelEvent - * @param source Source object - * @param path path - * @param childIndices Child indices - * @param children Children - */ - public TreeModelEvent(Object source, Object[] path, - int[] childIndices, Object[] children) { - super(source); - this.path = new TreePath(path); - this.childIndices = childIndices; - this.children = children; - } // TreeModelEvent() - - /** - * Constructor TreeModelEvent - * @param source Source object - * @param path Path - */ - public TreeModelEvent(Object source, TreePath path) { - super(source); - this.path = path; - } // TreeModelEvent() - - /** - * Constructor TreeModelEvent - * @param source Source object - * @param path Path - * @param childIndices Child indices - * @param children Children - */ - public TreeModelEvent(Object source, TreePath path, - int[] childIndices, Object[] children) { - super(source); - this.path = path; - this.childIndices = childIndices; - this.children = children; - } // TreeModelEvent() - - - //------------------------------------------------------------- - // Methods ---------------------------------------------------- - //------------------------------------------------------------- - - /** - * getChildIndices - * @returns child indices - */ - public int[] getChildIndices() { - return childIndices; - } // getChildIndices() - - /** - * getChildren - * @returns children - */ - public Object[] getChildren() { - return children; - } // getChildren() - - /** - * getPath - * @returns path - */ - public Object[] getPath() { - return path.getPath(); - } // getPath() - - /** - * getTreePath - * @returns TreePath - */ - public TreePath getTreePath() { - return path; - } // getTreePath() - - /** - * String representation - * @returns String representation - */ - public String toString() { - return getClass() + " [Source: " + getSource() + ", TreePath: " + getTreePath() + - ", Child Indicies: " + getChildIndices() + ", Children: " + getChildren() + - ", Path: " + getPath() +"]"; - } // toString() - - -} // TreeModelEvent + /** + * Constructor TreeModelEvent + * @param source Source object + * @param path + */ + public TreeModelEvent(Object source, Object[] path) + { + super(source); + this.path = new TreePath(path); + } + + /** + * Constructor TreeModelEvent + * @param source Source object + * @param path path + * @param childIndices Child indices + * @param children Children + */ + public TreeModelEvent(Object source, Object[] path, + int[] childIndices, Object[] children) + { + super(source); + this.path = new TreePath(path); + this.childIndices = childIndices; + this.children = children; + } + + /** + * Constructor TreeModelEvent + * @param source Source object + * @param path Path + */ + public TreeModelEvent(Object source, TreePath path) + { + super(source); + this.path = path; + } + + /** + * Constructor TreeModelEvent + * @param source Source object + * @param path Path + * @param childIndices Child indices + * @param children Children + */ + public TreeModelEvent(Object source, TreePath path, + int[] childIndices, Object[] children) + { + super(source); + this.path = path; + this.childIndices = childIndices; + this.children = children; + } + + /** + * getChildIndices + * @return child indices + */ + public int[] getChildIndices() + { + return childIndices; + } + + /** + * getChildren + * @return children + */ + public Object[] getChildren() + { + return children; + } + + /** + * getPath + * @return path + */ + public Object[] getPath() + { + return path.getPath(); + } + + /** + * getTreePath + * @return TreePath + */ + public TreePath getTreePath() + { + return path; + } + + /** + * String representation + * @return String representation + */ + public String toString() + { + return getClass() + " [Source: " + getSource() + ", TreePath: " + + getTreePath() + ", Child Indicies: " + getChildIndices() + + ", Children: " + getChildren() + ", Path: " + getPath() +"]"; + } + +} diff --git a/libjava/classpath/javax/swing/event/TreeSelectionEvent.java b/libjava/classpath/javax/swing/event/TreeSelectionEvent.java index 9b87667..1930677 100644 --- a/libjava/classpath/javax/swing/event/TreeSelectionEvent.java +++ b/libjava/classpath/javax/swing/event/TreeSelectionEvent.java @@ -1,5 +1,5 @@ /* TreeSelectionEvent.java -- - Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -49,10 +49,6 @@ import javax.swing.tree.TreePath; */ public class TreeSelectionEvent extends EventObject { - //------------------------------------------------------------- - // Variables -------------------------------------------------- - //------------------------------------------------------------- - /** * paths */ @@ -73,11 +69,6 @@ public class TreeSelectionEvent extends EventObject { */ protected TreePath newLeadSelectionPath; - - //------------------------------------------------------------- - // Initialization --------------------------------------------- - //------------------------------------------------------------- - /** * Constructor TreeSelectionEvent * @param source TODO @@ -95,7 +86,7 @@ public class TreeSelectionEvent extends EventObject { this.areNew = areNew; this.oldLeadSelectionPath = oldLeadSelectionPath; this.newLeadSelectionPath = newLeadSelectionPath; - } // TreeSelectionEvent() + } /** * Constructor TreeSelectionEvent @@ -114,29 +105,24 @@ public class TreeSelectionEvent extends EventObject { this.areNew = new boolean[]{isNew}; this.oldLeadSelectionPath = oldLeadSelectionPath; this.newLeadSelectionPath = newLeadSelectionPath; - } // TreeSelectionEvent() - - - //------------------------------------------------------------- - // Methods ---------------------------------------------------- - //------------------------------------------------------------- + } /** - * @returns the first path element + * @return the first path element */ public TreePath getPath() { return paths[0]; - } // getPath() + } /** * - * @returns the paths with selection changed + * @return the paths with selection changed */ public TreePath[] getPaths() { return (TreePath[]) paths.clone(); - } // getPaths() + } /** * @return true if the first path is added to the selection, false otherwise @@ -144,7 +130,7 @@ public class TreeSelectionEvent extends EventObject { public boolean isAddedPath() { return areNew[0]; - } // isAddedPath() + } /** * @param path the path to check @@ -157,7 +143,7 @@ public class TreeSelectionEvent extends EventObject { return areNew[i]; return false; - } // isAddedPath() + } /** * @param index the index'th path @@ -166,7 +152,7 @@ public class TreeSelectionEvent extends EventObject { public boolean isAddedPath(int index) { return areNew[index]; - } // isAddedPath() + } /** * @return the previous lead selection path @@ -174,15 +160,15 @@ public class TreeSelectionEvent extends EventObject { public TreePath getOldLeadSelectionPath() { return oldLeadSelectionPath; - } // getOldLeadSelectionPath() + } /** - * @returns the current lead selection path + * @return the current lead selection path */ public TreePath getNewLeadSelectionPath() { return newLeadSelectionPath; - } // getNewLeadSelectionPath() + } /** * @param source the new event source @@ -193,7 +179,6 @@ public class TreeSelectionEvent extends EventObject { return new TreeSelectionEvent (source, paths, areNew, oldLeadSelectionPath, newLeadSelectionPath); - } // cloneWithSource() - + } -} // TreeSelectionEvent +} diff --git a/libjava/classpath/javax/swing/event/UndoableEditEvent.java b/libjava/classpath/javax/swing/event/UndoableEditEvent.java index 147c2e5..b59cead 100644 --- a/libjava/classpath/javax/swing/event/UndoableEditEvent.java +++ b/libjava/classpath/javax/swing/event/UndoableEditEvent.java @@ -1,5 +1,5 @@ /* UndoableEditEvent.java -- - Copyright (C) 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -47,46 +47,34 @@ import javax.swing.undo.UndoableEdit; * @author Andrew Selkirk * @author Ronald Veldema */ -public class UndoableEditEvent extends EventObject { +public class UndoableEditEvent extends EventObject +{ private static final long serialVersionUID = 4418044561759134484L; - //------------------------------------------------------------- - // Variables -------------------------------------------------- - //------------------------------------------------------------- - - /** - * edit - */ - private UndoableEdit edit; - - - //------------------------------------------------------------- - // Initialization --------------------------------------------- - //------------------------------------------------------------- - - /** - * Constructor UndoableEditEvent - * @param source TODO - * @param edit TODO - */ - public UndoableEditEvent(Object source, UndoableEdit edit) { - super(source); - this.edit = edit; - } // UndoableEditEvent() - - - //------------------------------------------------------------- - // Methods ---------------------------------------------------- - //------------------------------------------------------------- - - /** - * getEdit - * @returns UndoableEdit - */ - public UndoableEdit getEdit() { - return edit; - } // getEdit() - - -} // UndoableEditEvent + /** + * edit + */ + private UndoableEdit edit; + + /** + * Constructor UndoableEditEvent + * @param source TODO + * @param edit TODO + */ + public UndoableEditEvent(Object source, UndoableEdit edit) + { + super(source); + this.edit = edit; + } + + /** + * getEdit + * @return UndoableEdit + */ + public UndoableEdit getEdit() + { + return edit; + } + +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicBorders.java b/libjava/classpath/javax/swing/plaf/basic/BasicBorders.java index 5d4ce18..5e2cf2e 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicBorders.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicBorders.java @@ -299,9 +299,7 @@ public class BasicBorders public static Border getSplitPaneDividerBorder() { /* See comment in methods above for why this border is not shared. */ - return new SplitPaneDividerBorder( - UIManager.getColor("SplitPane.highlight"), - UIManager.getColor("SplitPane.darkShadow")); + return new SplitPaneDividerBorder(); } @@ -1518,34 +1516,15 @@ public class BasicBorders implements Border, UIResource, Serializable { /** - * The highlight color, which is drawn on the left or top edge - * depending on the orientation of the JSplitPanel. - */ - protected Color highlight; - - - /** - * The highlight color, which is drawn on the right or bottom edge - * depending on the orientation of the JSplitPanel. - */ - protected Color shadow; - - - /** * Constructs a new border for drawing the divider of a JSplitPane * in the Basic look and feel. The outer parts of the JSplitPane have * their own border class, SplitPaneBorder. - * - * @param shadow the shadow color. - * @param highlight the highlight color. */ - public SplitPaneDividerBorder(Color highlight, Color shadow) + public SplitPaneDividerBorder() { - this.highlight = (highlight != null) ? highlight : Color.white; - this.shadow = (shadow != null) ? shadow : Color.black; + // Nothing to do here. } - /** * Paints the border around the divider of a JSplitPane. * @@ -1564,6 +1543,8 @@ public class BasicBorders public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + Color highlight = UIManager.getColor("SplitPane.highlight"); + Color shadow = UIManager.getColor("SplitPane.shadow"); Color oldColor, dcol; int x2, y2; JSplitPane sp; @@ -1624,17 +1605,15 @@ public class BasicBorders return new Insets(1, 1, 1, 1); } - /** * Determines whether this border fills every pixel in its area * when painting. * - * @return true if both highlight and shadow - * color are fully opaque. + * @return true */ public boolean isBorderOpaque() { - return (highlight.getAlpha() == 255) && (shadow.getAlpha() == 255); + return true; } @@ -1785,4 +1764,5 @@ public class BasicBorders return insets; } } + } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java index 95e0dc9..e45970e 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java @@ -45,7 +45,6 @@ import javax.swing.JMenuItem; import javax.swing.MenuElement; import javax.swing.MenuSelectionManager; import javax.swing.UIDefaults; -import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; /** diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicColorChooserUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicColorChooserUI.java index 5a872ae..f37cbd7 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicColorChooserUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicColorChooserUI.java @@ -141,10 +141,9 @@ public class BasicColorChooserUI extends ColorChooserUI protected PropertyChangeListener propertyChangeListener; /** - * The JColorChooser. - * This is package-private to avoid an accessor method. + * The JColorChooser this is installed on. */ - JColorChooser chooser; + protected JColorChooser chooser; /** The JTabbedPane that is used. */ JTabbedPane pane; diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicComboPopup.java b/libjava/classpath/javax/swing/plaf/basic/BasicComboPopup.java index 08dab7f..798101d 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicComboPopup.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicComboPopup.java @@ -69,6 +69,7 @@ import javax.swing.ListSelectionModel; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.Timer; +import javax.swing.UIManager; import javax.swing.event.ListDataEvent; import javax.swing.event.ListDataListener; import javax.swing.event.ListSelectionEvent; @@ -193,8 +194,23 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup if (selectedIndex > comboBox.getMaximumRowCount()) scrollbar.setValue(getPopupHeightForRowCount(selectedIndex)); + // We put the autoclose-registration inside an InvocationEvent, so that + // the same event that triggered this show() call won't hide the popup + // immediately. + SwingUtilities.invokeLater + (new Runnable() + { + public void run() + { + // Register this popup to be autoclosed when user clicks outside the + // popup. + BasicLookAndFeel laf = (BasicLookAndFeel) UIManager.getLookAndFeel(); + laf.registerForAutoClose(BasicComboPopup.this); + }}); + // location specified is relative to comboBox super.show(comboBox, 0, cbBounds.height); + } /** diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicHTML.java b/libjava/classpath/javax/swing/plaf/basic/BasicHTML.java index b9891e1..98c9cb2 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicHTML.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicHTML.java @@ -38,12 +38,21 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import java.awt.Container; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.awt.Shape; import java.io.IOException; import java.io.StringReader; import javax.swing.JComponent; +import javax.swing.SwingConstants; +import javax.swing.event.DocumentEvent; import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.EditorKit; import javax.swing.text.Element; +import javax.swing.text.Position; import javax.swing.text.View; import javax.swing.text.ViewFactory; import javax.swing.text.html.HTMLDocument; @@ -59,6 +68,287 @@ public class BasicHTML { /** + * This class serves as the root view for HTML rendering components. + * Its purpose and implementation is similar to the BasicTextUI.RootView + * class, only that is implements some stuff differently due to the nature + * of not beeing inside a JTextComponent. + * + * @author Roman Kennke (kennke@aicas.com) + */ + private static class HTMLRootView extends View + { + /** + * The real root view. + */ + private View view; + + /** + * The component on which to render the view. + */ + private JComponent component; + + /** + * The EditorKit. + */ + private EditorKit editorKit; + + /** + * The document to use. + */ + private Document document; + + /** + * Creates a new RootView. + */ + public HTMLRootView(JComponent c, View view, EditorKit kit, Document doc) + { + super(null); + component = c; + editorKit = kit; + document = doc; + setView(view); + } + + /** + * Returns the ViewFactory for this RootView. If the current EditorKit + * provides a ViewFactory, this is used. Otherwise the TextUI itself + * is returned as a ViewFactory. + * + * @return the ViewFactory for this RootView + */ + public ViewFactory getViewFactory() + { + return editorKit.getViewFactory(); + } + + /** + * Indicates that the preferences of one of the child view has changed. + * This calls revalidate on the text component. + * + * @param v the child view which's preference has changed + * @param width true if the width preference has changed + * @param height true if the height preference has changed + */ + public void preferenceChanged(View v, boolean width, boolean height) + { + component.revalidate(); + } + + /** + * Sets the real root view. + * + * @param v the root view to set + */ + public void setView(View v) + { + if (view != null) + view.setParent(null); + + if (v != null) + v.setParent(this); + + view = v; + } + + /** + * Returns the real root view, regardless of the index. + * + * @param index not used here + * + * @return the real root view, regardless of the index. + */ + public View getView(int index) + { + return view; + } + + /** + * Returns 1 since the RootView always contains one + * child, that is the real root of the View hierarchy. + * + * @return 1 since the RootView always contains one + * child, that is the real root of the View hierarchy + */ + public int getViewCount() + { + int count = 0; + if (view != null) + count = 1; + return count; + } + + /** + * Returns the Container that contains this view. This + * normally will be the text component that is managed by this TextUI. + * + * @return the Container that contains this view + */ + public Container getContainer() + { + return component; + } + + /** + * Returns the preferred span along the specified axis. + * This is delegated to the real root view. + * + * @param axis the axis for which the preferred span is queried + * + * @return the preferred span along the axis + */ + public float getPreferredSpan(int axis) + { + if (view != null) + return view.getPreferredSpan(axis); + + return Integer.MAX_VALUE; + } + + /** + * Paints the view. This is delegated to the real root view. + * + * @param g the Graphics context to paint to + * @param s the allocation for the View + */ + public void paint(Graphics g, Shape s) + { + if (view != null) + { + Rectangle b = s.getBounds(); + view.setSize(b.width, b.height); + view.paint(g, s); + } + } + + + /** + * Maps a position in the document into the coordinate space of the View. + * The output rectangle usually reflects the font height but has a width + * of zero. + * + * This is delegated to the real root view. + * + * @param position the position of the character in the model + * @param a the area that is occupied by the view + * @param bias either {@link Position.Bias#Forward} or + * {@link Position.Bias#Backward} depending on the preferred + * direction bias. If null this defaults to + * Position.Bias.Forward + * + * @return a rectangle that gives the location of the document position + * inside the view coordinate space + * + * @throws BadLocationException if pos is invalid + * @throws IllegalArgumentException if b is not one of the above listed + * valid values + */ + public Shape modelToView(int position, Shape a, Position.Bias bias) + throws BadLocationException + { + return view.modelToView(position, a, bias); + } + + /** + * Maps coordinates from the View's space into a position + * in the document model. + * + * @param x the x coordinate in the view space + * @param y the y coordinate in the view space + * @param a the allocation of this View + * @param b the bias to use + * + * @return the position in the document that corresponds to the screen + * coordinates x, y + */ + public int viewToModel(float x, float y, Shape a, Position.Bias[] b) + { + return view.viewToModel(x, y, a, b); + } + + /** + * Notification about text insertions. These are forwarded to the + * real root view. + * + * @param ev the DocumentEvent describing the change + * @param shape the current allocation of the view's display + * @param vf the ViewFactory to use for creating new Views + */ + public void insertUpdate(DocumentEvent ev, Shape shape, ViewFactory vf) + { + view.insertUpdate(ev, shape, vf); + } + + /** + * Notification about text removals. These are forwarded to the + * real root view. + * + * @param ev the DocumentEvent describing the change + * @param shape the current allocation of the view's display + * @param vf the ViewFactory to use for creating new Views + */ + public void removeUpdate(DocumentEvent ev, Shape shape, ViewFactory vf) + { + view.removeUpdate(ev, shape, vf); + } + + /** + * Notification about text changes. These are forwarded to the + * real root view. + * + * @param ev the DocumentEvent describing the change + * @param shape the current allocation of the view's display + * @param vf the ViewFactory to use for creating new Views + */ + public void changedUpdate(DocumentEvent ev, Shape shape, ViewFactory vf) + { + view.changedUpdate(ev, shape, vf); + } + + /** + * Returns the document position that is (visually) nearest to the given + * document position pos in the given direction d. + * + * @param pos the document position + * @param b the bias for pos + * @param a the allocation for the view + * @param d the direction, must be either {@link SwingConstants#NORTH}, + * {@link SwingConstants#SOUTH}, {@link SwingConstants#WEST} or + * {@link SwingConstants#EAST} + * @param biasRet an array of {@link Position.Bias} that can hold at least + * one element, which is filled with the bias of the return position + * on method exit + * + * @return the document position that is (visually) nearest to the given + * document position pos in the given direction + * d + * + * @throws BadLocationException if pos is not a valid offset in + * the document model + */ + public int getNextVisualPositionFrom(int pos, Position.Bias b, Shape a, + int d, Position.Bias[] biasRet) + throws BadLocationException + { + return view.getNextVisualPositionFrom(pos, b, a, d, biasRet); + } + + public int getStartOffset() + { + return 0; + } + + public int getEndOffset() + { + return getDocument().getLength(); + } + + public Document getDocument() + { + return document; + } + } + + /** * The key that is used to store a HTML view in a JComponent's client * properties. */ @@ -116,7 +406,8 @@ public class BasicHTML ViewFactory vf = kit.getViewFactory(); Element root = doc.getDefaultRootElement(); View view = vf.create(root); - return view; + HTMLRootView rootView = new HTMLRootView(c, view, kit, doc); + return rootView; } /** @@ -132,13 +423,13 @@ public class BasicHTML { // We consider a string to be HTML if it contains both the '<' and '>' // character at least once. - return s.contains("<") && s.contains(">"); + return (s != null) && s.contains("<") && s.contains(">"); } /** * Stores a HTML renderer in c's client property if * text is HTML, otherwise it clears the corresponding client - * property. This is useful for {@link java.swing.plaf.ComponentUI} + * property. This is useful for {@link javax.swing.plaf.ComponentUI} * implementations that are shared between it's components. * * @param c the component to update the renderer for diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java index f9653bd..f6cbeec 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java @@ -54,8 +54,6 @@ import java.awt.event.ComponentListener; import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -import java.beans.PropertyVetoException; -import java.beans.VetoableChangeListener; import javax.swing.DefaultDesktopManager; import javax.swing.DesktopManager; @@ -94,7 +92,7 @@ public class BasicInternalFrameUI extends InternalFrameUI */ public void internalFrameActivated(InternalFrameEvent e) { - // FIXME: Implement. + frame.getGlassPane().setVisible(false); } /** @@ -124,7 +122,7 @@ public class BasicInternalFrameUI extends InternalFrameUI */ public void internalFrameDeactivated(InternalFrameEvent e) { - // FIXME: Implement. + frame.getGlassPane().setVisible(true); } /** @@ -464,8 +462,6 @@ public class BasicInternalFrameUI extends InternalFrameUI dims.width -= insets.left + insets.right; dims.height -= insets.top + insets.bottom; - frame.getRootPane().getGlassPane().setBounds(0, 0, dims.width, - dims.height); int nh = 0; int sh = 0; int ew = 0; @@ -526,18 +522,6 @@ public class BasicInternalFrameUI extends InternalFrameUI } /** - * This method returns the maximum layout size. - * - * @param c - * The Container to find a maximum layout size for. - * @return The maximum dimensions for the JInternalFrame. - */ - public Dimension maximumLayoutSize(Container c) - { - return preferredLayoutSize(c); - } - - /** * Th8is method returns the preferred layout size. * * @param c @@ -891,40 +875,12 @@ public class BasicInternalFrameUI extends InternalFrameUI * This helper class listens for PropertyChangeEvents from the * JInternalFrame. */ - public class InternalFramePropertyChangeListener implements - PropertyChangeListener, VetoableChangeListener + public class InternalFramePropertyChangeListener + implements PropertyChangeListener { /** * This method is called when one of the JInternalFrame's properties change. - * This method is to allow JInternalFrame to veto an attempt to close the - * internal frame. This allows JInternalFrame to honour its - * defaultCloseOperation if that is DO_NOTHING_ON_CLOSE. - */ - public void vetoableChange(PropertyChangeEvent e) - throws PropertyVetoException - { - if (e.getPropertyName().equals(JInternalFrame.IS_CLOSED_PROPERTY)) - { - if (frame.getDefaultCloseOperation() == JInternalFrame.HIDE_ON_CLOSE) - { - frame.setVisible(false); - frame.getDesktopPane().repaint(); - throw new PropertyVetoException( - "close operation is HIDE_ON_CLOSE\n", - e); - } - else if (frame.getDefaultCloseOperation() == JInternalFrame.DISPOSE_ON_CLOSE) - closeFrame(frame); - else - throw new PropertyVetoException( - "close operation is DO_NOTHING_ON_CLOSE\n", - e); - } - } - - /** - * This method is called when one of the JInternalFrame's properties change. * * @param evt * The PropertyChangeEvent. @@ -1091,13 +1047,6 @@ public class BasicInternalFrameUI extends InternalFrameUI */ protected PropertyChangeListener propertyChangeListener; - /** - * The VetoableChangeListener. Listens to PropertyChangeEvents - * from the JInternalFrame and allows the JInternalFrame to - * veto attempts to close it. - */ - private VetoableChangeListener internalFrameVetoableChangeListener; - /** The InternalFrameListener that listens to the JInternalFrame. */ private transient BasicInternalFrameListener internalFrameListener; @@ -1165,14 +1114,15 @@ public class BasicInternalFrameUI extends InternalFrameUI { frame = (JInternalFrame) c; - ((JComponent) frame.getRootPane().getGlassPane()).setOpaque(false); - frame.getRootPane().getGlassPane().setVisible(true); - installDefaults(); installListeners(); installComponents(); installKeyboardActions(); + ((JComponent) frame.getRootPane().getGlassPane()).setOpaque(false); + if (! frame.isSelected()) + frame.getRootPane().getGlassPane().setVisible(true); + frame.setOpaque(true); frame.invalidate(); } @@ -1205,8 +1155,6 @@ public class BasicInternalFrameUI extends InternalFrameUI frame.setLayout(internalFrameLayout); LookAndFeel.installBorder(frame, "InternalFrame.border"); frame.setFrameIcon(UIManager.getIcon("InternalFrame.icon")); - // InternalFrames are invisible by default. - frame.setVisible(false); } /** @@ -1238,13 +1186,11 @@ public class BasicInternalFrameUI extends InternalFrameUI borderListener = createBorderListener(frame); componentListener = createComponentListener(); propertyChangeListener = createPropertyChangeListener(); - internalFrameVetoableChangeListener = new InternalFramePropertyChangeListener(); frame.addMouseListener(borderListener); frame.addMouseMotionListener(borderListener); frame.addInternalFrameListener(internalFrameListener); frame.addPropertyChangeListener(propertyChangeListener); - frame.addVetoableChangeListener(internalFrameVetoableChangeListener); frame.getRootPane().getGlassPane().addMouseListener(glassPaneDispatcher); frame.getRootPane().getGlassPane().addMouseMotionListener(glassPaneDispatcher); } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicLabelUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicLabelUI.java index fd4cff5..d0964f4 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicLabelUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicLabelUI.java @@ -53,6 +53,7 @@ import javax.swing.LookAndFeel; import javax.swing.SwingUtilities; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.LabelUI; +import javax.swing.text.View; /** * This is the Basic Look and Feel class for the JLabel. One BasicLabelUI @@ -64,11 +65,22 @@ public class BasicLabelUI extends LabelUI implements PropertyChangeListener protected static BasicLabelUI labelUI; /** + * These fields hold the rectangles for the whole label, + * the icon and the text. + */ + private Rectangle vr; + private Rectangle ir; + private Rectangle tr; + + /** * Creates a new BasicLabelUI object. */ public BasicLabelUI() { super(); + vr = new Rectangle(); + ir = new Rectangle(); + tr = new Rectangle(); } /** @@ -99,13 +111,11 @@ public class BasicLabelUI extends LabelUI implements PropertyChangeListener public Dimension getPreferredSize(JComponent c) { JLabel lab = (JLabel) c; - Rectangle vr = new Rectangle(); - Rectangle ir = new Rectangle(); - Rectangle tr = new Rectangle(); Insets insets = lab.getInsets(); FontMetrics fm = lab.getFontMetrics(lab.getFont()); layoutCL(lab, fm, lab.getText(), lab.getIcon(), vr, ir, tr); - Rectangle cr = tr.union(ir); + Rectangle cr = SwingUtilities.computeUnion(tr.x, tr.y, tr.width, tr.height, + ir); return new Dimension(insets.left + cr.width + insets.right, insets.top + cr.height + insets.bottom); @@ -148,11 +158,6 @@ public class BasicLabelUI extends LabelUI implements PropertyChangeListener public void paint(Graphics g, JComponent c) { JLabel b = (JLabel) c; - - Rectangle tr = new Rectangle(); - Rectangle ir = new Rectangle(); - Rectangle vr = new Rectangle(); - FontMetrics fm = g.getFontMetrics(); vr = SwingUtilities.calculateInnerArea(c, vr); @@ -168,13 +173,21 @@ public class BasicLabelUI extends LabelUI implements PropertyChangeListener if (icon != null) icon.paintIcon(b, g, ir.x, ir.y); - if (text != null && !text.equals("")) - { - if (b.isEnabled()) - paintEnabledText(b, g, text, tr.x, tr.y + fm.getAscent()); - else - paintDisabledText(b, g, text, tr.x, tr.y + fm.getAscent()); - } + Object htmlRenderer = b.getClientProperty(BasicHTML.propertyKey); + if (htmlRenderer == null) + { + if (text != null && !text.equals("")) + { + if (b.isEnabled()) + paintEnabledText(b, g, text, tr.x, tr.y + fm.getAscent()); + else + paintDisabledText(b, g, text, tr.x, tr.y + fm.getAscent()); + } + } + else + { + ((View) htmlRenderer).paint(g, tr); + } } /** @@ -312,7 +325,7 @@ public class BasicLabelUI extends LabelUI implements PropertyChangeListener */ protected void installComponents(JLabel c) { - //FIXME: fix javadoc + implement. + BasicHTML.updateRenderer(c, c.getText()); } /** @@ -322,7 +335,8 @@ public class BasicLabelUI extends LabelUI implements PropertyChangeListener */ protected void uninstallComponents(JLabel c) { - //FIXME: fix javadoc + implement. + c.putClientProperty(BasicHTML.propertyKey, null); + c.putClientProperty(BasicHTML.documentBaseKey, null); } /** @@ -402,6 +416,11 @@ public class BasicLabelUI extends LabelUI implements PropertyChangeListener */ public void propertyChange(PropertyChangeEvent e) { - // What to do here? + if (e.getPropertyName().equals("text")) + { + String text = (String) e.getNewValue(); + JLabel l = (JLabel) e.getSource(); + BasicHTML.updateRenderer(l, text); + } } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicListUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicListUI.java index 00d157a..19dfe21 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicListUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicListUI.java @@ -64,6 +64,7 @@ import javax.swing.ListCellRenderer; import javax.swing.ListModel; import javax.swing.ListSelectionModel; import javax.swing.LookAndFeel; +import javax.swing.SwingUtilities; import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.event.ListDataEvent; @@ -135,6 +136,7 @@ public class BasicListUI extends ListUI */ public void contentsChanged(ListDataEvent e) { + updateLayoutStateNeeded |= modelChanged; list.revalidate(); } @@ -145,6 +147,7 @@ public class BasicListUI extends ListUI */ public void intervalAdded(ListDataEvent e) { + updateLayoutStateNeeded |= modelChanged; list.revalidate(); } @@ -155,6 +158,7 @@ public class BasicListUI extends ListUI */ public void intervalRemoved(ListDataEvent e) { + updateLayoutStateNeeded |= modelChanged; list.revalidate(); } } @@ -541,17 +545,21 @@ public class BasicListUI extends ListUI */ public void propertyChange(PropertyChangeEvent e) { - if (e.getSource() == BasicListUI.this.list) + if (e.getPropertyName().equals("model")) { if (e.getOldValue() != null && e.getOldValue() instanceof ListModel) - ((ListModel) e.getOldValue()).removeListDataListener(BasicListUI.this.listDataListener); - + { + ListModel oldModel = (ListModel) e.getOldValue(); + oldModel.removeListDataListener(listDataListener); + } if (e.getNewValue() != null && e.getNewValue() instanceof ListModel) - ((ListModel) e.getNewValue()).addListDataListener(BasicListUI.this.listDataListener); + { + ListModel newModel = (ListModel) e.getNewValue(); + newModel.addListDataListener(BasicListUI.this.listDataListener); + } + + updateLayoutStateNeeded |= modelChanged; } - // Update the updateLayoutStateNeeded flag. - if (e.getPropertyName().equals("model")) - updateLayoutStateNeeded |= modelChanged; else if (e.getPropertyName().equals("selectionModel")) updateLayoutStateNeeded |= selectionModelChanged; else if (e.getPropertyName().equals("font")) @@ -720,14 +728,20 @@ public class BasicListUI extends ListUI int minIndex = Math.min(index1, index2); int maxIndex = Math.max(index1, index2); Point loc = indexToLocation(list, minIndex); - Rectangle bounds = new Rectangle(loc.x, loc.y, cellWidth, + + // When the layoutOrientation is VERTICAL, then the width == the list + // width. Otherwise the cellWidth field is used. + int width = cellWidth; + if (l.getLayoutOrientation() == JList.VERTICAL) + width = l.getWidth(); + + Rectangle bounds = new Rectangle(loc.x, loc.y, width, getCellHeight(minIndex)); for (int i = minIndex + 1; i <= maxIndex; i++) { Point hiLoc = indexToLocation(list, i); - Rectangle hibounds = new Rectangle(hiLoc.x, hiLoc.y, cellWidth, - getCellHeight(i)); - bounds = bounds.union(hibounds); + bounds = SwingUtilities.computeUnion(hiLoc.x, hiLoc.y, width, + getCellHeight(i), bounds); } return bounds; @@ -883,8 +897,6 @@ public class BasicListUI extends ListUI Dimension dim = flyweight.getPreferredSize(); cellWidth = Math.max(cellWidth, dim.width); } - if (list.getLayoutOrientation() == JList.VERTICAL) - cellWidth = Math.max(cellWidth, list.getSize().width); } } @@ -894,7 +906,7 @@ public class BasicListUI extends ListUI */ protected void maybeUpdateLayoutState() { - if (updateLayoutStateNeeded != 0 || !list.isValid()) + if (updateLayoutStateNeeded != 0) { updateLayoutState(); updateLayoutStateNeeded = 0; diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java b/libjava/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java index f5217be..3451224 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java @@ -38,15 +38,24 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import java.awt.AWTEvent; import java.awt.Color; +import java.awt.Component; +import java.awt.Container; import java.awt.Dimension; import java.awt.Font; +import java.awt.Toolkit; +import java.awt.event.AWTEventListener; import java.awt.event.ActionEvent; +import java.awt.event.MouseEvent; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.util.Enumeration; +import java.util.Iterator; import java.util.ResourceBundle; +import java.util.Set; +import java.util.WeakHashMap; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; @@ -57,8 +66,11 @@ import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.ActionMap; import javax.swing.BorderFactory; +import javax.swing.JPopupMenu; import javax.swing.KeyStroke; import javax.swing.LookAndFeel; +import javax.swing.MenuSelectionManager; +import javax.swing.SwingUtilities; import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.border.BevelBorder; @@ -77,6 +89,96 @@ import javax.swing.plaf.InsetsUIResource; public abstract class BasicLookAndFeel extends LookAndFeel implements Serializable { + + /** + * Helps closing menu popups when the user clicks outside of any menu area. + * This is implemented as an AWTEventListener that listens on the event + * queue directly, grabs all mouse events from there and finds out of they + * are targetted at a menu/submenu/menubar or not. If not, + * the MenuSelectionManager is messaged to close the currently opened menus, + * if any. + * + * @author Roman Kennke (kennke@aicas.com) + */ + private class PopupHelper implements AWTEventListener + { + + /** + * Registered popups for autoclose. + */ + private WeakHashMap autoClosePopups = new WeakHashMap(); + + /** + * Receives an event from the event queue. + * + * @param event + */ + public void eventDispatched(AWTEvent event) + { + if (event instanceof MouseEvent) + { + MouseEvent mouseEvent = (MouseEvent) event; + if (mouseEvent.getID() == MouseEvent.MOUSE_PRESSED) + mousePressed(mouseEvent); + } + } + + /** + * Handles mouse pressed events from the event queue. + * + * @param ev the mouse pressed event + */ + private void mousePressed(MouseEvent ev) + { + // Autoclose all menus managed by the MenuSelectionManager. + MenuSelectionManager m = MenuSelectionManager.defaultManager(); + Component target = ev.getComponent(); + if (target instanceof Container) + target = ((Container) target).findComponentAt(ev.getPoint()); + if (! m.isComponentPartOfCurrentMenu(target)) + m.clearSelectedPath(); + + // Handle other registered popup instances, like ComboBox popups. + autoClosePopups(ev, target); + } + + /** + * Registers Popup and its content to be autoclosed when a mouseclick + * occurs outside of the popup. + * + * @param popup the popup to be autoclosed when clicked outside + */ + void registerForAutoClose(JPopupMenu popup) + { + autoClosePopups.put(popup, null); + } + + /** + * Automatically closes all popups that are not 'hit' by the mouse event. + * + * @param ev the mouse event + * @param target the target of the mouse event + */ + private void autoClosePopups(MouseEvent ev, Component target) + { + if (autoClosePopups.size() != 0) + { + Set popups = autoClosePopups.keySet(); + Iterator i = popups.iterator(); + while (i.hasNext()) + { + JPopupMenu popup = (JPopupMenu) i.next(); + if (!(target == popup + || SwingUtilities.isDescendingFrom(target, popup))) + { + popup.setVisible(false); + i.remove(); + } + } + } + } + } + /** * An action that can play an audio file. * @@ -137,6 +239,11 @@ public abstract class BasicLookAndFeel extends LookAndFeel static final long serialVersionUID = -6096995660290287879L; + /** + * Helps closing menu popups when user clicks outside of the menu area. + */ + private transient PopupHelper popupHelper; + private ActionMap audioActionMap; /** @@ -1023,6 +1130,8 @@ public abstract class BasicLookAndFeel extends LookAndFeel "SplitPane.dividerSize", new Integer(7), "SplitPane.highlight", new ColorUIResource(highLight), "SplitPane.shadow", new ColorUIResource(shadow), + "SplitPaneDivider.border", BasicBorders.getSplitPaneDividerBorder(), + "SplitPaneDivider.draggingColor", new ColorUIResource(Color.DARK_GRAY), "TabbedPane.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { "ctrl PAGE_DOWN","navigatePageDown", "ctrl PAGE_UP", "navigatePageUp", @@ -1520,4 +1629,36 @@ public abstract class BasicLookAndFeel extends LookAndFeel } } + /** + * Initializes the Look and Feel. + */ + public void initialize() + { + Toolkit toolkit = Toolkit.getDefaultToolkit(); + popupHelper = new PopupHelper(); + toolkit.addAWTEventListener(popupHelper, AWTEvent.MOUSE_EVENT_MASK); + } + + /** + * Uninitializes the Look and Feel. + */ + public void uninitialize() + { + Toolkit toolkit = Toolkit.getDefaultToolkit(); + toolkit.removeAWTEventListener(popupHelper); + popupHelper = null; + } + + /** + * Registers a JPopupMenu for autoclosing when a mouseclick occurs outside + * of the JPopupMenu. This must be called when the popup gets opened. The + * popup is unregistered from autoclosing as soon as it either got closed + * by this helper, or when it has been garbage collected. + * + * @param popup the popup menu to autoclose + */ + void registerForAutoClose(JPopupMenu popup) + { + popupHelper.registerForAutoClose(popup); + } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicMenuItemUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicMenuItemUI.java index 63f0ce2..9166c49 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicMenuItemUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicMenuItemUI.java @@ -610,8 +610,7 @@ public class BasicMenuItemUI extends MenuItemUI Font f = m.getFont(); g.setFont(f); FontMetrics fm = g.getFontMetrics(f); - SwingUtilities.calculateInnerArea(m, br); - SwingUtilities.calculateInsetArea(br, m.getInsets(), vr); + SwingUtilities.calculateInnerArea(m, vr); paintBackground(g, m, background); /* diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuUI.java index e15a17b..6ecd06b 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuUI.java @@ -37,28 +37,20 @@ exception statement from your version. */ package javax.swing.plaf.basic; -import java.awt.AWTEvent; import java.awt.Component; -import java.awt.Container; -import java.awt.Cursor; import java.awt.Dimension; -import java.awt.Point; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.awt.event.MouseEvent; import javax.swing.BoxLayout; import javax.swing.JComponent; -import javax.swing.JLayeredPane; -import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.LookAndFeel; import javax.swing.MenuElement; import javax.swing.MenuSelectionManager; -import javax.swing.RootPaneContainer; import javax.swing.SwingUtilities; -import javax.swing.event.MouseInputListener; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; import javax.swing.plaf.ComponentUI; @@ -73,9 +65,6 @@ public class BasicPopupMenuUI extends PopupMenuUI /* popupMenu for which this UI delegate is for*/ protected JPopupMenu popupMenu; - /* MouseInputListener listens to mouse events. Package private for inner classes. */ - static transient MouseInputListener mouseInputListener; - /* PopupMenuListener listens to popup menu events fired by JPopupMenu*/ private transient PopupMenuListener popupMenuListener; @@ -270,30 +259,9 @@ public class BasicPopupMenuUI extends PopupMenuUI // remove listener that listens to component events fired // by the top - level window that this popup belongs to. Component invoker = popupMenu.getInvoker(); - - RootPaneContainer rootContainer = (RootPaneContainer) SwingUtilities - .getRoot(invoker); + Component rootContainer = SwingUtilities.getRoot(invoker); if (rootContainer != null) - { - ((Container) rootContainer).removeComponentListener(topWindowListener); - - // If this popup menu is the last popup menu visible on the screen, - // then - // stop interrupting mouse events in the glass pane before hiding this - // last popup menu. - boolean topLevelMenu = (popupMenu.getInvoker() instanceof JMenu) - && ((JMenu) popupMenu.getInvoker()).isTopLevelMenu(); - - if (topLevelMenu || !(popupMenu.getInvoker() instanceof MenuElement)) - { - // set glass pane not to interrupt mouse events and remove - // mouseInputListener - Container glassPane = (Container) rootContainer.getGlassPane(); - glassPane.setVisible(false); - glassPane.removeMouseListener(mouseInputListener); - mouseInputListener = null; - } - } + rootContainer.removeComponentListener(topWindowListener); } /** @@ -307,20 +275,8 @@ public class BasicPopupMenuUI extends PopupMenuUI // ComponentEvents fired by it. We need to cancel this popup menu // if topWindow to which this popup belongs was resized or moved. Component invoker = popupMenu.getInvoker(); - RootPaneContainer rootContainer = (RootPaneContainer) SwingUtilities - .getRoot(invoker); - ((Container) rootContainer).addComponentListener(topWindowListener); - - // Set the glass pane to interrupt all mouse events originating in root - // container - if (mouseInputListener == null) - { - Container glassPane = (Container) rootContainer.getGlassPane(); - glassPane.setVisible(true); - mouseInputListener = new MouseInputHandler(rootContainer); - glassPane.addMouseListener(mouseInputListener); - glassPane.addMouseMotionListener(mouseInputListener); - } + Component rootContainer = SwingUtilities.getRoot(invoker); + rootContainer.addComponentListener(topWindowListener); // if this popup menu is a free floating popup menu, // then by default its first element should be always selected when @@ -399,275 +355,4 @@ public class BasicPopupMenuUI extends PopupMenuUI } } - /** - * MouseInputHandler listens to all mouse events originated in the root - * container. This class is responsible for closing menu hierarchy when the - * user presses mouse over any component that do not belong to the current - * menu hierarchy. This is acomplished by interrupting all mouse event in - * the glass pane and checking if other component was pressed while menu - * was open, before redestributing events further to intended components - */ - private class MouseInputHandler implements MouseInputListener - { - private JLayeredPane layeredPane; - private Container glassPane; - private Cursor nativeCursor; - private transient Component mouseEventTarget; - private transient Component pressedComponent; - private transient Component lastComponentEntered; - private transient Component tempComponent; - private transient int pressCount; - - /** - * Creates a new MouseInputHandler object. - * - * @param c the top most root container - */ - public MouseInputHandler(RootPaneContainer c) - { - layeredPane = c.getLayeredPane(); - glassPane = (Container) c.getGlassPane(); - } - - /** - * Handles mouse clicked event - * - * @param e Mouse event - */ - public void mouseClicked(MouseEvent e) - { - handleEvent(e); - } - - /** - * Handles mouseDragged event - * - * @param e MouseEvent - */ - public void mouseDragged(MouseEvent e) - { - handleEvent(e); - } - - /** - * Handles mouseEntered event - * - * @param e MouseEvent - */ - public void mouseEntered(MouseEvent e) - { - handleEvent(e); - } - - /** - * Handles mouseExited event - * - * @param e MouseEvent - */ - public void mouseExited(MouseEvent e) - { - handleEvent(e); - } - - /** - * Handles mouse moved event - * - * @param e MouseEvent - */ - public void mouseMoved(MouseEvent e) - { - handleEvent(e); - } - - /** - * Handles mouse pressed event - * - * @param e MouseEvent - */ - public void mousePressed(MouseEvent e) - { - handleEvent(e); - } - - /** - * Handles mouse released event - * - * @param e MouseEvent - */ - public void mouseReleased(MouseEvent e) - { - handleEvent(e); - } - - /* - * This method determines component that was intended to received mouse - * event, before it was interrupted within the glass pane. This method - * also redispatches mouse entered and mouse exited events to the - * appropriate components. This code is slightly modified code from - * Container.LightweightDispatcher class, which is private inside - * Container class and cannot be used here. - */ - public void acquireComponentForMouseEvent(MouseEvent me) - { - int x = me.getX(); - int y = me.getY(); - - // Find the candidate which should receive this event. - Component parent = layeredPane; - Component candidate = null; - Point p = me.getPoint(); - while ((candidate == null) && (parent != null)) - { - p = SwingUtilities.convertPoint(glassPane, p.x, p.y, parent); - candidate = SwingUtilities.getDeepestComponentAt(parent, p.x, p.y); - - if (candidate == null) - { - p = SwingUtilities.convertPoint(parent, p.x, p.y, - parent.getParent()); - parent = parent.getParent(); - } - } - - // If the only candidate we found was the native container itself, - // don't dispatch any event at all. We only care about the lightweight - // children here. - if (candidate == layeredPane) - candidate = null; - - // If our candidate is new, inform the old target we're leaving. - if ((lastComponentEntered != null) && lastComponentEntered.isShowing() - && (lastComponentEntered != candidate)) - { - // Old candidate could have been removed from - // the layeredPane so we check first. - if (SwingUtilities.isDescendingFrom(lastComponentEntered, layeredPane)) - { - Point tp = SwingUtilities.convertPoint(layeredPane, x, y, - lastComponentEntered); - MouseEvent exited = new MouseEvent(lastComponentEntered, - MouseEvent.MOUSE_EXITED, - me.getWhen(), - me.getModifiersEx(), tp.x, - tp.y, me.getClickCount(), - me.isPopupTrigger(), - me.getButton()); - - tempComponent = lastComponentEntered; - lastComponentEntered = null; - tempComponent.dispatchEvent(exited); - } - - lastComponentEntered = null; - } - - // If we have a candidate, maybe enter it. - if (candidate != null) - { - mouseEventTarget = candidate; - - if (candidate.isLightweight() && candidate.isShowing() - && (candidate != layeredPane) - && (candidate != lastComponentEntered)) - { - lastComponentEntered = mouseEventTarget; - - Point cp = SwingUtilities.convertPoint(layeredPane, x, y, - lastComponentEntered); - MouseEvent entered = new MouseEvent(lastComponentEntered, - MouseEvent.MOUSE_ENTERED, - me.getWhen(), - me.getModifiersEx(), cp.x, - cp.y, me.getClickCount(), - me.isPopupTrigger(), - me.getButton()); - lastComponentEntered.dispatchEvent(entered); - } - } - - if ((me.getID() == MouseEvent.MOUSE_RELEASED) - || ((me.getID() == MouseEvent.MOUSE_PRESSED) && (pressCount > 0)) - || (me.getID() == MouseEvent.MOUSE_DRAGGED)) - { - // If any of the following events occur while a button is held down, - // they should be dispatched to the same component to which the - // original MOUSE_PRESSED event was dispatched: - // - MOUSE_RELEASED - // - MOUSE_PRESSED: another button pressed while the first is held down - // - MOUSE_DRAGGED - if (SwingUtilities.isDescendingFrom(pressedComponent, layeredPane)) - mouseEventTarget = pressedComponent; - else if (me.getID() == MouseEvent.MOUSE_CLICKED) - { - // Don't dispatch CLICKED events whose target is not the same as the - // target for the original PRESSED event. - if (candidate != pressedComponent) - mouseEventTarget = null; - else if (pressCount == 0) - pressedComponent = null; - } - } - } - - /* - * This method handles mouse events interrupted by glassPane. It - * redispatches the mouse events appropriately to the intended components. - * The code in this method is also taken from - * Container.LightweightDispatcher class. The code is slightly modified - * to handle the case when mouse is released over non-menu component. In - * this case this method closes current menu hierarchy before - * redispatching the event further. - */ - public void handleEvent(AWTEvent e) - { - if (e instanceof MouseEvent) - { - MouseEvent me = (MouseEvent) e; - - acquireComponentForMouseEvent(me); - - // Avoid dispatching ENTERED and EXITED events twice. - if (mouseEventTarget != null && mouseEventTarget.isShowing() - && (e.getID() != MouseEvent.MOUSE_ENTERED) - && (e.getID() != MouseEvent.MOUSE_EXITED)) - { - MouseEvent newEvt = SwingUtilities.convertMouseEvent(glassPane, - me, - mouseEventTarget); - - mouseEventTarget.dispatchEvent(newEvt); - - // If mouse was clicked over the component that is not part - // of menu hierarchy,then must close the menu hierarchy */ - if (e.getID() == MouseEvent.MOUSE_RELEASED) - { - boolean partOfMenuHierarchy = false; - MenuSelectionManager manager = MenuSelectionManager - .defaultManager(); - - partOfMenuHierarchy = manager.isComponentPartOfCurrentMenu(mouseEventTarget); - - if (! partOfMenuHierarchy) - manager.clearSelectedPath(); - } - - switch (e.getID()) - { - case MouseEvent.MOUSE_PRESSED: - if (pressCount++ == 0) - pressedComponent = mouseEventTarget; - break; - case MouseEvent.MOUSE_RELEASED: - // Clear our memory of the original PRESSED event, only if - // we're not expecting a CLICKED event after this. If - // there is a CLICKED event after this, it will do clean up. - if ((--pressCount == 0) - && (mouseEventTarget != pressedComponent)) - pressedComponent = null; - break; - } - } - } - } - } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java index 8af5ff7..f8f62e1 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java @@ -45,7 +45,6 @@ import javax.swing.JMenuItem; import javax.swing.MenuElement; import javax.swing.MenuSelectionManager; import javax.swing.UIDefaults; -import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; /** diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicRootPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicRootPaneUI.java index 2a698e8..28e3b67 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicRootPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicRootPaneUI.java @@ -1,4 +1,4 @@ -/* BasicPanelUI.java -- +/* BasicRootPaneUI.java -- Copyright (C) 2002, 2004 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -43,7 +43,6 @@ import java.beans.PropertyChangeListener; import javax.swing.JComponent; import javax.swing.JRootPane; -import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.RootPaneUI; @@ -75,8 +74,7 @@ public class BasicRootPaneUI extends RootPaneUI */ protected void installDefaults(JRootPane rp) { - // Is this ok? - rp.setBackground(UIManager.getColor("control")); + // TODO: What to do here, if anything? (might be a hook method) } /** diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java index a2f5b82..c8713c9 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java @@ -653,19 +653,17 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL) { - width += incrButton.getPreferredSize().getWidth(); - width += decrButton.getPreferredSize().getWidth(); - - width += (scrollbar.getMaximum() - scrollbar.getMinimum()); - height = UIManager.getInt("ScrollBar.width"); + width += incrButton.getPreferredSize().getWidth(); + width += decrButton.getPreferredSize().getWidth(); + width += 16; + height = UIManager.getInt("ScrollBar.width"); } else { - height += incrButton.getPreferredSize().getHeight(); - height += decrButton.getPreferredSize().getHeight(); - - height += (scrollbar.getMaximum() - scrollbar.getMinimum()); - width = UIManager.getInt("ScrollBar.width"); + height += incrButton.getPreferredSize().getHeight(); + height += decrButton.getPreferredSize().getHeight(); + height += 16; + width = UIManager.getInt("ScrollBar.width"); } Insets insets = scrollbar.getInsets(); @@ -721,18 +719,6 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ protected void installComponents() { - if (incrButton != null) - scrollbar.add(incrButton); - if (decrButton != null) - scrollbar.add(decrButton); - } - - /** - * This method installs the defaults for the scrollbar specified by the - * Basic Look and Feel. - */ - protected void installDefaults() - { int orientation = scrollbar.getOrientation(); switch (orientation) { @@ -746,6 +732,18 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, break; } + if (incrButton != null) + scrollbar.add(incrButton); + if (decrButton != null) + scrollbar.add(decrButton); + } + + /** + * This method installs the defaults for the scrollbar specified by the + * Basic Look and Feel. + */ + protected void installDefaults() + { LookAndFeel.installColors(scrollbar, "ScrollBar.background", "ScrollBar.foreground"); LookAndFeel.installBorder(scrollbar, "ScrollBar.border"); diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSpinnerUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicSpinnerUI.java index 3b7399e..6f7a41a 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicSpinnerUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicSpinnerUI.java @@ -1,5 +1,5 @@ -/* SpinnerUI.java -- - Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. +/* BasicSpinnerUI.java -- + Copyright (C) 2003, 2004, 2005, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,6 +41,7 @@ package javax.swing.plaf.basic; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; +import java.awt.Font; import java.awt.Insets; import java.awt.LayoutManager; import java.awt.event.ActionEvent; @@ -59,22 +60,21 @@ import javax.swing.plaf.ComponentUI; import javax.swing.plaf.SpinnerUI; /** - * DOCUMENT ME! + * A UI delegate for the {@link JSpinner} component. * * @author Ka-Hing Cheung * - * @see javax.swing.JSpinner * @since 1.4 */ public class BasicSpinnerUI extends SpinnerUI { /** - * Creates a new ComponentUI for the specified + * Creates a new BasicSpinnerUI for the specified * JComponent * - * @param c DOCUMENT ME! + * @param c the component (ignored). * - * @return a ComponentUI + * @return A new instance of {@link BasicSpinnerUI}. */ public static ComponentUI createUI(JComponent c) { @@ -144,14 +144,15 @@ public class BasicSpinnerUI extends SpinnerUI { return new PropertyChangeListener() { - public void propertyChange(PropertyChangeEvent evt) - { - // FIXME: Add check for enabled property change. Need to - // disable the buttons. - if ("editor".equals(evt.getPropertyName())) - BasicSpinnerUI.this.replaceEditor((JComponent) evt.getOldValue(), - (JComponent) evt.getNewValue()); - } + public void propertyChange(PropertyChangeEvent event) + { + // FIXME: Add check for enabled property change. Need to + // disable the buttons. + if ("editor".equals(event.getPropertyName())) + BasicSpinnerUI.this.replaceEditor((JComponent) event.getOldValue(), + (JComponent) event.getNewValue()); + // FIXME: Handle 'font' property change + } }; } @@ -169,6 +170,12 @@ public class BasicSpinnerUI extends SpinnerUI LookAndFeel.installColorsAndFont(spinner, "Spinner.background", "Spinner.foreground", "Spinner.font"); LookAndFeel.installBorder(spinner, "Spinner.border"); + JComponent e = spinner.getEditor(); + if (e instanceof JSpinner.DefaultEditor) + { + JSpinner.DefaultEditor de = (JSpinner.DefaultEditor) e; + de.getTextField().setBorder(null); + } spinner.setLayout(createLayout()); spinner.setOpaque(true); } @@ -352,7 +359,8 @@ public class BasicSpinnerUI extends SpinnerUI private PropertyChangeListener listener = createPropertyChangeListener(); /** - * DOCUMENT ME! + * A layout manager for the {@link JSpinner} component. The spinner has + * three subcomponents: an editor, a 'next' button and a 'previous' button. */ private class DefaultLayoutManager implements LayoutManager { @@ -365,58 +373,52 @@ public class BasicSpinnerUI extends SpinnerUI { synchronized (parent.getTreeLock()) { - Insets i = parent.getInsets(); - boolean l2r = parent.getComponentOrientation().isLeftToRight(); - /* - -------------- -------------- - | | n | | n | | - | e | - | or | - | e | - | | p | | p | | - -------------- -------------- - */ - Dimension e = minSize(editor); - Dimension n = minSize(next); - Dimension p = minSize(previous); - Dimension s = spinner.getPreferredSize(); - - int x = l2r ? i.left : i.right; - int y = i.top; - int w = Math.max(p.width, n.width); - int h = Math.max(p.height, n.height); - h = Math.max(h, e.height / 2); - int e_width = s.width - w; - - if (l2r) - { - setBounds(editor, x, y + (s.height - e.height) / 2, e_width, - e.height); - x += e_width; - - setBounds(next, x, y, w, h); - y += h; - - setBounds(previous, x, y, w, h); - } - else - { - setBounds(next, x, y + (s.height - e.height) / 2, w, h); - y += h; - - setBounds(previous, x, y, w, h); - x += w; - y -= h; - - setBounds(editor, x, y, e_width, e.height); - } + Insets i = parent.getInsets(); + boolean l2r = parent.getComponentOrientation().isLeftToRight(); + /* + -------------- -------------- + | | n | | n | | + | e | - | or | - | e | + | | p | | p | | + -------------- -------------- + */ + Dimension e = prefSize(editor); + Dimension n = prefSize(next); + Dimension p = prefSize(previous); + Dimension s = spinner.getPreferredSize(); + + int x = l2r ? i.left : i.right; + int y = i.top; + int w = Math.max(p.width, n.width); + int h = e.height / 2; + int e_width = s.width - w - i.left - i.right; + + if (l2r) + { + setBounds(editor, x, y, e_width, 2 * h); + x += e_width; + setBounds(next, x, y, w, h); + y += h; + setBounds(previous, x, y, w, h); + } + else + { + setBounds(next, x, y + (s.height - e.height) / 2, w, h); + y += h; + setBounds(previous, x, y + (s.height - e.height) / 2, w, h); + x += w; + y -= h; + setBounds(editor, x, y, e_width, e.height); + } } } /** - * DOCUMENT ME! + * Calculates the minimum layout size. * - * @param parent DOCUMENT ME! + * @param parent the parent. * - * @return DOCUMENT ME! + * @return The minimum layout size. */ public Dimension minimumLayoutSize(Container parent) { @@ -424,36 +426,32 @@ public class BasicSpinnerUI extends SpinnerUI if (editor != null) { - Dimension tmp = editor.getMinimumSize(); - d.width += tmp.width; - d.height = tmp.height; + Dimension tmp = editor.getMinimumSize(); + d.width += tmp.width; + d.height = tmp.height; } int nextWidth = 0; int previousWidth = 0; - int otherHeight = 0; if (next != null) { - Dimension tmp = next.getMinimumSize(); - nextWidth = tmp.width; - otherHeight += tmp.height; + Dimension tmp = next.getMinimumSize(); + nextWidth = tmp.width; } if (previous != null) { - Dimension tmp = previous.getMinimumSize(); - previousWidth = tmp.width; - otherHeight += tmp.height; + Dimension tmp = previous.getMinimumSize(); + previousWidth = tmp.width; } - d.height = Math.max(d.height, otherHeight); d.width += Math.max(nextWidth, previousWidth); return d; } /** - * DOCUMENT ME! + * Returns the preferred layout size of the container. * * @param parent DOCUMENT ME! * @@ -465,31 +463,29 @@ public class BasicSpinnerUI extends SpinnerUI if (editor != null) { - Dimension tmp = editor.getPreferredSize(); - d.width += Math.max(tmp.width, 40); - d.height = tmp.height; + Dimension tmp = editor.getPreferredSize(); + d.width += Math.max(tmp.width, 40); + d.height = tmp.height; } int nextWidth = 0; int previousWidth = 0; - int otherHeight = 0; if (next != null) { - Dimension tmp = next.getPreferredSize(); - nextWidth = tmp.width; - otherHeight += tmp.height; + Dimension tmp = next.getPreferredSize(); + nextWidth = tmp.width; } if (previous != null) { - Dimension tmp = previous.getPreferredSize(); - previousWidth = tmp.width; - otherHeight += tmp.height; + Dimension tmp = previous.getPreferredSize(); + previousWidth = tmp.width; } - d.height = Math.max(d.height, otherHeight); d.width += Math.max(nextWidth, previousWidth); - + Insets insets = parent.getInsets(); + d.width = d.width + insets.left + insets.right; + d.height = d.height + insets.top + insets.bottom; return d; } @@ -501,11 +497,11 @@ public class BasicSpinnerUI extends SpinnerUI public void removeLayoutComponent(Component child) { if (child == editor) - editor = null; + editor = null; else if (child == next) - next = null; + next = null; else if (previous == child) - previous = null; + previous = null; } /** @@ -517,11 +513,11 @@ public class BasicSpinnerUI extends SpinnerUI public void addLayoutComponent(String name, Component child) { if ("Editor".equals(name)) - editor = child; + editor = child; else if ("Next".equals(name)) - next = child; + next = child; else if ("Previous".equals(name)) - previous = child; + previous = child; } /** @@ -531,36 +527,36 @@ public class BasicSpinnerUI extends SpinnerUI * * @return DOCUMENT ME! */ - private Dimension minSize(Component c) + private Dimension prefSize(Component c) { if (c == null) - return new Dimension(); + return new Dimension(); else - return c.getMinimumSize(); + return c.getPreferredSize(); } /** - * DOCUMENT ME! + * Sets the bounds for the specified component. * - * @param c DOCUMENT ME! - * @param x DOCUMENT ME! - * @param y DOCUMENT ME! - * @param w DOCUMENT ME! - * @param h DOCUMENT ME! + * @param c the component. + * @param x the x-coordinate for the top-left of the component bounds. + * @param y the y-coordinate for the top-left of the component bounds. + * @param w the width of the bounds. + * @param h the height of the bounds. */ private void setBounds(Component c, int x, int y, int w, int h) { if (c != null) - c.setBounds(x, y, w, h); + c.setBounds(x, y, w, h); } - /** DOCUMENT ME! */ + /** The editor component. */ private Component editor; - /** DOCUMENT ME! */ + /** The next button. */ private Component next; - /** DOCUMENT ME! */ + /** The previous button. */ private Component previous; } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneDivider.java b/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneDivider.java index ff17ff0..06d3298 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneDivider.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneDivider.java @@ -38,7 +38,6 @@ exception statement from your version. */ package javax.swing.plaf.basic; -import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; @@ -161,31 +160,6 @@ public class BasicSplitPaneDivider extends Container */ transient int currentDividerLocation = 1; - /** DOCUMENT ME! */ - private transient Border tmpBorder = new Border() - { - public Insets getBorderInsets(Component c) - { - return new Insets(2, 2, 2, 2); - } - - public boolean isBorderOpaque() - { - return false; - } - - public void paintBorder(Component c, Graphics g, int x, int y, - int width, int height) - { - Color saved = g.getColor(); - g.setColor(Color.BLACK); - - g.drawRect(x + 2, y + 2, width - 4, height - 4); - - g.setColor(saved); - } - }; - /** * Constructs a new divider. * @@ -196,7 +170,6 @@ public class BasicSplitPaneDivider extends Container setLayout(new DividerLayout()); setBasicSplitPaneUI(ui); setDividerSize(splitPane.getDividerSize()); - setBorder(tmpBorder); } /** @@ -212,8 +185,6 @@ public class BasicSplitPaneDivider extends Container if (splitPane != null) { splitPane.removePropertyChangeListener(this); - splitPane.removeMouseListener(mouseHandler); - splitPane.removeMouseMotionListener(mouseHandler); removeMouseListener(mouseHandler); removeMouseMotionListener(mouseHandler); splitPane = null; @@ -227,8 +198,6 @@ public class BasicSplitPaneDivider extends Container if (splitPane != null) { splitPane.addPropertyChangeListener(this); - splitPane.addMouseListener(mouseHandler); - splitPane.addMouseMotionListener(mouseHandler); addMouseListener(mouseHandler); addMouseMotionListener(mouseHandler); hiddenDivider = splitPaneUI.getNonContinuousLayoutDivider(); diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneUI.java index cf31e8b..8a7c9d2 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneUI.java @@ -62,6 +62,7 @@ import javax.swing.LookAndFeel; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.SplitPaneUI; +import javax.swing.plaf.UIResource; /** * This is the Basic Look and Feel implementation of the SplitPaneUI class. @@ -253,20 +254,21 @@ public class BasicSplitPaneUI extends SplitPaneUI JSplitPane split = (JSplitPane) container; distributeExtraSpace(); Insets insets = split.getInsets(); - int width = getInitialLocation(insets); Dimension dims = split.getSize(); - for (int i = 0; i < components.length; i += 2) - { - if (components[i] == null) - continue; - setComponentToSize(components[i], sizes[i], width, insets, dims); - width += sizes[i]; - } - if (components[1] != null) - { - setComponentToSize(components[1], sizes[1], width, insets, dims); - width += sizes[1]; - } + int loc = getInitialLocation(insets); + int available = getAvailableSize(dims, insets); + sizes[0] = getDividerLocation(split) - loc; + sizes[1] = available - sizes[0] - sizes[2]; + // The size of the divider won't change. + + // Layout component#1. + setComponentToSize(components[0], sizes[0], loc, insets, dims); + // Layout divider. + loc += sizes[0]; + setComponentToSize(components[2], sizes[2], loc, insets, dims); + // Layout component#2. + loc += sizes[2]; + setComponentToSize(components[1], sizes[1], loc, insets, dims); } } @@ -388,6 +390,8 @@ public class BasicSplitPaneUI extends SplitPaneUI { for (int i = 0; i < components.length; i++) resetSizeAt(i); + setDividerLocation(splitPane, + getInitialLocation(splitPane.getInsets()) + sizes[0]); } /** @@ -451,21 +455,7 @@ public class BasicSplitPaneUI extends SplitPaneUI */ void distributeExtraSpace() { - int availSize = getAvailableSize(splitPane.getSize(), - splitPane.getInsets()); - int[] newSizes = new int[3]; - double weight = splitPane.getResizeWeight(); - - int oldLen = sizes[0] + sizes[1]; - - // dividers don't change size. - availSize -= sizes[2] + oldLen; - - int rightAlloc = (int) (availSize * (1 - weight)); - int leftAlloc = availSize - rightAlloc; - - sizes[0] += leftAlloc; - sizes[1] += rightAlloc; + // FIXME: This needs to be reimplemented correctly. } /** @@ -835,8 +825,6 @@ public class BasicSplitPaneUI extends SplitPaneUI if (prop <= 1 && prop >= 0) splitPane.setDividerLocation(prop); } - layoutManager.layoutContainer(splitPane); - splitPane.repaint(); // Don't have to deal with continuous_layout - only // necessary in dragging modes (and it's checked // every time you drag there) @@ -933,6 +921,8 @@ public class BasicSplitPaneUI extends SplitPaneUI /** The JSplitPane that this UI draws. */ protected JSplitPane splitPane; + private int dividerLocation; + /** * Creates a new BasicSplitPaneUI object. */ @@ -992,6 +982,7 @@ public class BasicSplitPaneUI extends SplitPaneUI "SplitPane.foreground"); LookAndFeel.installBorder(splitPane, "SplitPane.border"); divider = createDefaultDivider(); + divider.setBorder(UIManager.getBorder("SplitPaneDivider.border")); resetLayoutManager(); nonContinuousLayoutDivider = createDefaultNonContinuousLayoutDivider(); splitPane.add(divider, JSplitPane.DIVIDER); @@ -1012,8 +1003,10 @@ public class BasicSplitPaneUI extends SplitPaneUI divider = null; nonContinuousLayoutDivider = null; - splitPane.setBackground(null); - splitPane.setBorder(null); + if (splitPane.getBackground() instanceof UIResource) + splitPane.setBackground(null); + if (splitPane.getBorder() instanceof UIResource) + splitPane.setBorder(null); } /** @@ -1219,7 +1212,8 @@ public class BasicSplitPaneUI extends SplitPaneUI if (nonContinuousLayoutDivider == null) { nonContinuousLayoutDivider = new Canvas(); - nonContinuousLayoutDivider.setBackground(Color.DARK_GRAY); + Color c = UIManager.getColor("SplitPaneDivider.draggingColor"); + nonContinuousLayoutDivider.setBackground(c); } return nonContinuousLayoutDivider; } @@ -1298,44 +1292,7 @@ public class BasicSplitPaneUI extends SplitPaneUI */ public void setDividerLocation(JSplitPane jc, int location) { - location = validLocation(location); - Container p = jc.getParent(); - Component right = jc.getRightComponent(); - Dimension rightPrefSize = right == null ? new Dimension(0, 0) - : right.getPreferredSize(); - Dimension size = jc.getSize(); - // check if the size has been set for the splitpane - if (size.width == 0 && size.height == 0) - size = jc.getPreferredSize(); - - if (getOrientation() == 0 && location > size.height) - { - location = size.height; - while (p != null) - { - p.setSize(p.getWidth(), p.getHeight() + rightPrefSize.height); - p = p.getParent(); - } - } - else if (location > size.width) - { - location = size.width; - while (p != null) - { - p.setSize(p.getWidth() + rightPrefSize.width, p.getHeight()); - p = p.getParent(); - } - } - - setLastDragLocation(getDividerLocation(splitPane)); - splitPane.setLastDividerLocation(getDividerLocation(splitPane)); - int[] tmpSizes = layoutManager.getSizes(); - tmpSizes[0] = location - - layoutManager.getInitialLocation(splitPane.getInsets()); - tmpSizes[1] = layoutManager.getAvailableSize(splitPane.getSize(), - splitPane.getInsets()) - - tmpSizes[0]; - layoutManager.setSizes(tmpSizes); + dividerLocation = location; splitPane.revalidate(); splitPane.repaint(); } @@ -1349,8 +1306,7 @@ public class BasicSplitPaneUI extends SplitPaneUI */ public int getDividerLocation(JSplitPane jc) { - return layoutManager.sizes[0] - + layoutManager.getInitialLocation(splitPane.getInsets()); + return dividerLocation; } /** @@ -1365,7 +1321,7 @@ public class BasicSplitPaneUI extends SplitPaneUI { int value = layoutManager.getInitialLocation(jc.getInsets()); if (layoutManager.components[0] != null) - value -= layoutManager.minimumSizeOfComponent(0); + value += layoutManager.minimumSizeOfComponent(0); return value; } @@ -1501,8 +1457,6 @@ public class BasicSplitPaneUI extends SplitPaneUI nonContinuousLayoutDivider.setVisible(true); nonContinuousLayoutDivider.setBounds(divider.getBounds()); } - splitPane.revalidate(); - splitPane.repaint(); } /** @@ -1544,11 +1498,9 @@ public class BasicSplitPaneUI extends SplitPaneUI nonContinuousLayoutDivider.setVisible(false); draggingHW = false; location = validLocation(location); - dragDividerTo(location); splitPane.setDividerLocation(location); splitPane.setLastDividerLocation(beginDragDividerLocation); beginDragDividerLocation = -1; - splitPane.repaint(); } /** diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java index a8f52ce..5b1e1ff 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java @@ -451,6 +451,8 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants } } runCount = runs; + if (runCount > tabRuns.length) + expandTabRunsArray(); tabRuns[0] = 0; normalizeTabRuns(tabPlacement, tabCount, start, max); @@ -1025,6 +1027,8 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants } } runCount = runs; + if (runCount > tabRuns.length) + expandTabRunsArray(); padSelectedTab(tabPlacement, tabPane.getSelectedIndex()); } @@ -1733,9 +1737,6 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants int tabCount = tabPane.getTabCount(); int currRun = 1; - if (tabCount > runCount) - runCount = tabCount; - if (tabCount < 1) return; diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTableHeaderUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTableHeaderUI.java index 9c8a5ef..1e8e39f 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicTableHeaderUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTableHeaderUI.java @@ -39,14 +39,18 @@ exception statement from your version. */ package javax.swing.plaf.basic; import java.awt.Component; +import java.awt.Cursor; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import javax.swing.CellRendererPane; import javax.swing.JComponent; import javax.swing.LookAndFeel; +import javax.swing.Timer; import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.event.MouseInputListener; @@ -57,62 +61,346 @@ import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; +/** + * Basic pluggable look and feel interface for JTableHeader. + */ public class BasicTableHeaderUI extends TableHeaderUI { - + /** + * The width of the space (in both direction) around the column boundary, + * where mouse cursor changes shape into "resize" + */ + static int COLUMN_BOUNDARY_TOLERANCE = 3; + public static ComponentUI createUI(JComponent h) { return new BasicTableHeaderUI(); } - + + /** + * The table header that is using this interface. + */ protected JTableHeader header; + + /** + * The mouse input listener, responsible for mouse manipulations with + * the table header. + */ protected MouseInputListener mouseInputListener; + + /** + * Paint the header cell. + */ protected CellRendererPane rendererPane; + + /** + * The header cell border. + */ protected Border cellBorder; - - public class MouseInputHandler implements MouseInputListener + + /** + * If not null, one of the columns is currently being dragged. + */ + Rectangle draggingHeaderRect; + + /** + * Handles column movement and rearrangement by mouse. The same instance works + * both as mouse listener and the mouse motion listner. + */ + public class MouseInputHandler + implements MouseInputListener { + /** + * If true, the cursor is being already shown in the alternative "resize" + * shape. + */ + boolean showingResizeCursor; + + /** + * The position, from where the cursor is dragged during resizing. Double + * purpose field (absolute value during resizing and relative offset during + * column dragging). + */ + int draggingFrom = - 1; + + /** + * The number of the column being dragged. + */ + int draggingColumnNumber; + + /** + * The previous preferred width of the column. + */ + int prevPrefWidth = - 1; + + /** + * The timer to coalesce column resizing events. + */ + Timer timer; + + /** + * Returns without action, part of the MouseInputListener interface. + */ public void mouseClicked(MouseEvent e) { - // TODO: Implement this properly. + // Nothing to do. } + /** + * If being in the resizing mode, handle resizing. + */ public void mouseDragged(MouseEvent e) { - // TODO: Implement this properly. + TableColumn resizeIt = header.getResizingColumn(); + if (resizeIt != null && header.getResizingAllowed()) + { + // The timer is intialised on demand. + if (timer == null) + { + // The purpose of timer is to coalesce events. If the queue + // is free, the repaint event is fired immediately. + timer = new Timer(1, new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + header.getTable().doLayout(); + } + }); + timer.setRepeats(false); + timer.setCoalesce(true); + } + resizeIt.setPreferredWidth(prevPrefWidth + e.getX() - draggingFrom); + timer.restart(); + } + else if (draggingHeaderRect != null && header.getReorderingAllowed()) + { + draggingHeaderRect.x = e.getX() + draggingFrom; + header.repaint(); + } } + /** + * Returns without action, part of the MouseInputListener interface. + */ public void mouseEntered(MouseEvent e) { - // TODO: Implement this properly. + // Nothing to do. } + /** + * Reset drag information of the column resizing. + */ public void mouseExited(MouseEvent e) { - // TODO: Implement this properly. + if (header.getResizingColumn() != null && header.getResizingAllowed()) + endResizing(); + if (header.getDraggedColumn() != null && header.getReorderingAllowed()) + endDragging(null); } + /** + * Change the mouse cursor if the mouse if above the column boundary. + */ public void mouseMoved(MouseEvent e) { - // TODO: Implement this properly. + // When dragging, the functionality is handled by the mouseDragged. + if (e.getButton() == 0 && header.getResizingAllowed()) + { + TableColumnModel model = header.getColumnModel(); + int n = model.getColumnCount(); + if (n < 2) + // It must be at least two columns to have at least one boundary. + // Otherwise, nothing to do. + return; + + boolean onBoundary = false; + + int x = e.getX(); + int a = x - COLUMN_BOUNDARY_TOLERANCE; + int b = x + COLUMN_BOUNDARY_TOLERANCE; + + int p = 0; + + Scan: for (int i = 0; i < n - 1; i++) + { + p += model.getColumn(i).getWidth(); + + if (p >= a && p <= b) + { + TableColumn column = model.getColumn(i); + onBoundary = true; + + draggingFrom = x; + prevPrefWidth = column.getWidth(); + header.setResizingColumn(column); + break Scan; + } + } + + if (onBoundary != showingResizeCursor) + { + // Change the cursor shape, if needed. + if (onBoundary) + { + + if (p < x) + header.setCursor(Cursor.getPredefinedCursor + (Cursor.W_RESIZE_CURSOR)); + else + header.setCursor(Cursor.getPredefinedCursor + (Cursor.E_RESIZE_CURSOR)); + } + else + { + header.setCursor(Cursor.getDefaultCursor()); + header.setResizingColumn(null); + } + + showingResizeCursor = onBoundary; + } + } } + /** + * Starts the dragging/resizing procedure. + */ public void mousePressed(MouseEvent e) { - // TODO: Implement this properly. + if (header.getResizingAllowed()) + { + TableColumn resizingColumn = header.getResizingColumn(); + if (resizingColumn != null) + { + resizingColumn.setPreferredWidth(resizingColumn.getWidth()); + return; + } + } + + if (header.getReorderingAllowed()) + { + TableColumnModel model = header.getColumnModel(); + int n = model.getColumnCount(); + if (n < 2) + // It must be at least two columns to change the column location. + return; + + boolean onBoundary = false; + + int x = e.getX(); + int p = 0; + int col = - 1; + + Scan: for (int i = 0; i < n; i++) + { + p += model.getColumn(i).getWidth(); + if (p > x) + { + col = i; + break Scan; + } + } + if (col < 0) + return; + + TableColumn dragIt = model.getColumn(col); + header.setDraggedColumn(dragIt); + + draggingFrom = (p - dragIt.getWidth()) - x; + draggingHeaderRect = new Rectangle(header.getHeaderRect(col)); + draggingColumnNumber = col; + } } + /** + * Set all column preferred width to the current width to prevend abrupt + * width changes during the next resize. + */ public void mouseReleased(MouseEvent e) { - // TODO: Implement this properly. + if (header.getResizingColumn() != null && header.getResizingAllowed()) + endResizing(); + if (header.getDraggedColumn() != null && header.getReorderingAllowed()) + endDragging(e); + } + + /** + * Stop resizing session. + */ + void endResizing() + { + TableColumnModel model = header.getColumnModel(); + int n = model.getColumnCount(); + if (n > 2) + { + TableColumn c; + for (int i = 0; i < n; i++) + { + c = model.getColumn(i); + c.setPreferredWidth(c.getWidth()); + } + } + header.setResizingColumn(null); + showingResizeCursor = false; + if (timer != null) + timer.stop(); + header.setCursor(Cursor.getDefaultCursor()); } - } + /** + * Stop the dragging session. + * + * @param e the "mouse release" mouse event, needed to determing the final + * location for the dragged column. + */ + void endDragging(MouseEvent e) + { + header.setDraggedColumn(null); + + // Return if the mouse have left the header area while pressed. + if (e == null) + { + header.repaint(draggingHeaderRect); + draggingHeaderRect = null; + return; + } + else + draggingHeaderRect = null; + + TableColumnModel model = header.getColumnModel(); + + // Find where have we dragged the column. + int x = e.getX(); + int p = 0; + int col = - 1; + int n = model.getColumnCount(); + + Scan: for (int i = 0; i < n; i++) + { + p += model.getColumn(i).getWidth(); + if (p > x) + { + col = i; + break Scan; + } + } + if (col >= 0) + header.getTable().moveColumn(draggingColumnNumber, col); + } + } + + /** + * Create and return the mouse input listener. + * + * @return the mouse listener ({@link MouseInputHandler}, if not overridden. + */ protected MouseInputListener createMouseInputListener() { return new MouseInputHandler(); } - + + /** + * Construct a new BasicTableHeaderUI, create mouse listeners. + */ public BasicTableHeaderUI() { mouseInputListener = createMouseInputListener(); @@ -131,9 +419,15 @@ public class BasicTableHeaderUI extends TableHeaderUI // TODO: Implement this properly. } + /** + * Add the mouse listener and the mouse motion listener to the table + * header. The listeners support table column resizing and rearrangement + * by mouse. + */ protected void installListeners() { header.addMouseListener(mouseInputListener); + header.addMouseMotionListener(mouseInputListener); } public void installUI(JComponent c) @@ -156,10 +450,14 @@ public class BasicTableHeaderUI extends TableHeaderUI { // TODO: Implement this properly. } - + + /** + * Remove the previously installed listeners. + */ protected void uninstallListeners() { header.removeMouseListener(mouseInputListener); + header.removeMouseMotionListener(mouseInputListener); } public void uninstallUI(JComponent c) @@ -168,7 +466,10 @@ public class BasicTableHeaderUI extends TableHeaderUI uninstallKeyboardActions(); uninstallDefaults(); } - + + /** + * Repaint the table header. + */ public void paint(Graphics gfx, JComponent c) { TableColumnModel cmod = header.getColumnModel(); @@ -206,10 +507,26 @@ public class BasicTableHeaderUI extends TableHeaderUI bounds.width, bounds.height); } } - + + // This displays a running rectangle that is much simplier than the total + // animation, as it is seen in Sun's application. + // TODO animate the collumn dragging like in Sun's jre. + if (draggingHeaderRect!=null) + { + gfx.setColor(header.getForeground()); + gfx.drawRect(draggingHeaderRect.x, draggingHeaderRect.y+2, + draggingHeaderRect.width-1, draggingHeaderRect.height-6); + } } - public Dimension getPreferredSize(JComponent c) + /** + * Get the preferred header size. + * + * @param ignored unused + * + * @return the preferred size of the associated header. + */ + public Dimension getPreferredSize(JComponent ignored) { TableColumnModel cmod = header.getColumnModel(); TableCellRenderer defaultRend = header.getDefaultRenderer(); diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTableUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTableUI.java index 18b6912..8360a9e 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicTableUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTableUI.java @@ -58,11 +58,11 @@ import java.beans.PropertyChangeListener; import javax.swing.AbstractAction; import javax.swing.ActionMap; import javax.swing.CellRendererPane; +import javax.swing.DefaultCellEditor; import javax.swing.DefaultListSelectionModel; import javax.swing.InputMap; import javax.swing.JComponent; import javax.swing.JTable; -import javax.swing.JTextField; import javax.swing.KeyStroke; import javax.swing.ListSelectionModel; import javax.swing.LookAndFeel; @@ -74,8 +74,8 @@ import javax.swing.plaf.ActionMapUIResource; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.InputMapUIResource; import javax.swing.plaf.TableUI; +import javax.swing.table.TableCellEditor; import javax.swing.table.TableCellRenderer; -import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; import javax.swing.table.TableModel; @@ -193,10 +193,31 @@ public class BasicTableUI extends TableUI colModel.setSelectionInterval(lo_col, hi_col); } } - - public void mouseClicked(MouseEvent e) + + /** + * For the double click, start the cell editor. + */ + public void mouseClicked(MouseEvent e) { - // TODO: What should be done here, if anything? + Point p = e.getPoint(); + int row = table.rowAtPoint(p); + int col = table.columnAtPoint(p); + if (table.isCellEditable(row, col)) + { + // If the cell editor is the default editor, we request the + // number of the required clicks from it. Otherwise, + // require two clicks (double click). + TableCellEditor editor = table.getCellEditor(row, col); + if (editor instanceof DefaultCellEditor) + { + DefaultCellEditor ce = (DefaultCellEditor) editor; + if (e.getClickCount() < ce.getClickCountToStart()) + return; + } + else if (e.getClickCount() < 2) + return; + table.editCellAt(row, col); + } } public void mouseDragged(MouseEvent e) @@ -354,7 +375,8 @@ public class BasicTableUI extends TableUI maxTotalColumnWidth += table.getColumnModel().getColumn(i).getMaxWidth(); if (maxTotalColumnWidth == 0 || table.getRowCount() == 0) return null; - return new Dimension(maxTotalColumnWidth, table.getRowCount()*table.getRowHeight()); + return new Dimension(maxTotalColumnWidth, table.getRowCount()* + (table.getRowHeight()+table.getRowMargin())); } /** @@ -380,7 +402,7 @@ public class BasicTableUI extends TableUI public Dimension getPreferredSize(JComponent comp) { int width = table.getColumnModel().getTotalColumnWidth(); - int height = table.getRowCount() * table.getRowHeight(); + int height = table.getRowCount() * (table.getRowHeight()+table.getRowMargin()); return new Dimension(width, height); } @@ -854,6 +876,10 @@ public class BasicTableUI extends TableUI rowModel.setAnchorSelectionIndex(rowLead); colModel.setAnchorSelectionIndex(colLead); } + else if (command.equals("stopEditing")) + { + table.editingStopped(new ChangeEvent(command)); + } else { // If we're here that means we bound this TableAction class @@ -1185,30 +1211,17 @@ public class BasicTableUI extends TableUI * system beginning at (0,0) in the upper left corner of the * table * @param rend A cell renderer to paint with - * @param data The data to provide to the cell renderer - * @param rowLead The lead selection for the rows of the table. - * @param colLead The lead selection for the columns of the table. */ void paintCell(Graphics g, int row, int col, Rectangle bounds, - TableCellRenderer rend, TableModel data, - int rowLead, int colLead) + TableCellRenderer rend) { Component comp = table.prepareRenderer(rend, row, col); rendererPane.paintComponent(g, comp, table, bounds); - - // FIXME: this is manual painting of the Caret, why doesn't the - // JTextField take care of this itself? - if (comp instanceof JTextField) - { - Rectangle oldClip = g.getClipBounds(); - g.translate(bounds.x, bounds.y); - g.clipRect(0, 0, bounds.width, bounds.height); - ((JTextField)comp).getCaret().paint(g); - g.translate(-bounds.x, -bounds.y); - g.setClip(oldClip); - } } + /** + * Paint the associated table. + */ public void paint(Graphics gfx, JComponent ignored) { int ncols = table.getColumnCount(); @@ -1217,59 +1230,72 @@ public class BasicTableUI extends TableUI return; Rectangle clip = gfx.getClipBounds(); - TableColumnModel cols = table.getColumnModel(); - - int height = table.getRowHeight(); - int x0 = 0, y0 = 0; - int x = x0; - int y = y0; - - Dimension gap = table.getIntercellSpacing(); - int ymax = clip.y + clip.height; - int xmax = clip.x + clip.width; + // Determine the range of cells that are within the clip bounds. + Point p1 = new Point(clip.x, clip.y); + int c0 = table.columnAtPoint(p1); + if (c0 == -1) + c0 = 0; + int r0 = table.rowAtPoint(p1); + if (r0 == -1) + r0 = 0; + Point p2 = new Point(clip.x + clip.width, clip.y + clip.height); + int cn = table.columnAtPoint(p2); + if (cn == -1) + cn = table.getColumnCount() - 1; + int rn = table.rowAtPoint(p2); + if (rn == -1) + rn = table.getRowCount() - 1; + + TableColumnModel cmodel = table.getColumnModel(); + int [] widths = new int[cn+1]; + for (int i = c0; i <=cn ; i++) + { + widths[i] = cmodel.getColumn(i).getWidth(); + } + + Rectangle bounds = table.getCellRect(r0, c0, false); + bounds.height = table.getRowHeight()+table.getRowMargin(); + + // The left boundary of the area being repainted. + int left = bounds.x; + + // The top boundary of the area being repainted. + int top = bounds.y; + + // The bottom boundary of the area being repainted. + int bottom; + + // The cell height. + int height = bounds.height; + // paint the cell contents - for (int c = 0; c < ncols && x < xmax; ++c) + Color grid = table.getGridColor(); + for (int r = r0; r <= rn; ++r) { - y = y0; - TableColumn col = cols.getColumn(c); - int width = col.getWidth(); - int halfGapWidth = gap.width / 2; - int halfGapHeight = gap.height / 2; - for (int r = 0; r < nrows && y < ymax; ++r) + for (int c = c0; c <= cn; ++c) { - Rectangle bounds = new Rectangle(x + halfGapWidth, - y + halfGapHeight + 1, - width - gap.width + 1, - height - gap.height); - if (bounds.intersects(clip)) - { - paintCell(gfx, r, c, bounds, table.getCellRenderer(r, c), - table.getModel(), - table.getSelectionModel().getLeadSelectionIndex(), - table.getColumnModel().getSelectionModel().getLeadSelectionIndex()); - } - y += height; + bounds.width = widths[c]; + paintCell(gfx, r, c, bounds, table.getCellRenderer(r, c)); + bounds.x += widths[c]; } - x += width; + bounds.y += height; + bounds.x = left; } - - // tighten up the x and y max bounds - ymax = y; - xmax = x; - - Color grid = table.getGridColor(); + + bottom = bounds.y; // paint vertical grid lines if (grid != null && table.getShowVerticalLines()) { - x = x0; Color save = gfx.getColor(); gfx.setColor(grid); - for (int c = 0; c < ncols && x < xmax; ++c) + int x = left; + + for (int c = c0; c <= cn; ++c) { - x += cols.getColumn(c).getWidth(); - gfx.drawLine(x, y0, x, ymax); + gfx.drawLine(x, top, x, bottom); + x += widths[c]; } gfx.setColor(save); } @@ -1277,13 +1303,13 @@ public class BasicTableUI extends TableUI // paint horizontal grid lines if (grid != null && table.getShowHorizontalLines()) { - y = y0; Color save = gfx.getColor(); gfx.setColor(grid); - for (int r = 0; r < nrows && y < ymax; ++r) + int y = top; + for (int r = r0; r <= rn; ++r) { + gfx.drawLine(left, y, p2.x, y); y += height; - gfx.drawLine(x0, y, xmax, y); } gfx.setColor(save); } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTextUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTextUI.java index fc38894..beb1a6d 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicTextUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTextUI.java @@ -1,5 +1,5 @@ /* BasicTextUI.java -- - Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -46,15 +46,11 @@ import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; import java.awt.Shape; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; -import java.awt.event.KeyEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.ActionMap; import javax.swing.InputMap; @@ -70,6 +66,7 @@ import javax.swing.plaf.ActionMapUIResource; import javax.swing.plaf.InputMapUIResource; import javax.swing.plaf.TextUI; import javax.swing.plaf.UIResource; +import javax.swing.text.AbstractDocument; import javax.swing.text.BadLocationException; import javax.swing.text.Caret; import javax.swing.text.DefaultCaret; @@ -82,6 +79,7 @@ import javax.swing.text.Highlighter; import javax.swing.text.JTextComponent; import javax.swing.text.Keymap; import javax.swing.text.Position; +import javax.swing.text.Utilities; import javax.swing.text.View; import javax.swing.text.ViewFactory; @@ -161,11 +159,11 @@ public abstract class BasicTextUI extends TextUI * Indicates that the preferences of one of the child view has changed. * This calls revalidate on the text component. * - * @param view the child view which's preference has changed + * @param v the child view which's preference has changed * @param width true if the width preference has changed * @param height true if the height preference has changed */ - public void preferenceChanged(View view, boolean width, boolean height) + public void preferenceChanged(View v, boolean width, boolean height) { textComponent.revalidate(); } @@ -181,7 +179,7 @@ public abstract class BasicTextUI extends TextUI view.setParent(null); if (v != null) - v.setParent(null); + v.setParent(this); view = v; } @@ -207,10 +205,10 @@ public abstract class BasicTextUI extends TextUI */ public int getViewCount() { + int count = 0; if (view != null) - return 1; - else - return 0; + count = 1; + return count; } /** @@ -249,7 +247,11 @@ public abstract class BasicTextUI extends TextUI public void paint(Graphics g, Shape s) { if (view != null) - view.paint(g, s); + { + Rectangle b = s.getBounds(); + view.setSize(b.width, b.height); + view.paint(g, s); + } } @@ -277,7 +279,7 @@ public abstract class BasicTextUI extends TextUI public Shape modelToView(int position, Shape a, Position.Bias bias) throws BadLocationException { - return ((View) view).modelToView(position, a, bias); + return view.modelToView(position, a, bias); } /** @@ -363,12 +365,44 @@ public abstract class BasicTextUI extends TextUI { return view.getNextVisualPositionFrom(pos, b, a, d, biasRet); } + + /** + * Returns the startOffset of this view, which is always the beginning + * of the document. + * + * @return the startOffset of this view + */ + public int getStartOffset() + { + return 0; + } + + /** + * Returns the endOffset of this view, which is always the end + * of the document. + * + * @return the endOffset of this view + */ + public int getEndOffset() + { + return getDocument().getLength(); + } + + /** + * Returns the document associated with this view. + * + * @return the document associated with this view + */ + public Document getDocument() + { + return textComponent.getDocument(); + } } /** * Receives notifications when properties of the text component change. */ - class PropertyChangeHandler implements PropertyChangeListener + private class PropertyChangeHandler implements PropertyChangeListener { /** * Notifies when a property of the text component changes. @@ -448,7 +482,7 @@ public abstract class BasicTextUI extends TextUI /** * Receives notification when the model changes. */ - PropertyChangeHandler updateHandler = new PropertyChangeHandler(); + private PropertyChangeHandler updateHandler = new PropertyChangeHandler(); /** The DocumentEvent handler. */ DocumentHandler documentHandler = new DocumentHandler(); @@ -515,20 +549,19 @@ public abstract class BasicTextUI extends TextUI c.setOpaque(true); textComponent = (JTextComponent) c; - Document doc = textComponent.getDocument(); if (doc == null) { - doc = getEditorKit(textComponent).createDefaultDocument(); - textComponent.setDocument(doc); + doc = getEditorKit(textComponent).createDefaultDocument(); + textComponent.setDocument(doc); } - - textComponent.addPropertyChangeListener(updateHandler); - modelChanged(); - installDefaults(); installListeners(); installKeyboardActions(); + + // We need to trigger this so that the view hierarchy gets initialized. + modelChanged(); + } /** @@ -584,6 +617,7 @@ public abstract class BasicTextUI extends TextUI protected void installListeners() { textComponent.addFocusListener(focuslistener); + textComponent.addPropertyChangeListener(updateHandler); installDocumentListeners(); } @@ -621,6 +655,11 @@ public abstract class BasicTextUI extends TextUI */ protected Keymap createKeymap() { + // FIXME: It seems to me that this method implementation is wrong. It seems + // to fetch the focusInputMap and transform it to the KeyBinding/Keymap + // implemenation. I would think that it should be done the other way, + // fetching the keybindings (from prefix + ".bindings") and transform + // it to the newer InputMap/ActionMap implementation. JTextComponent.KeyBinding[] bindings = null; String prefix = getPropertyPrefix(); InputMapUIResource m = (InputMapUIResource) UIManager.get(prefix + ".focusInputMap"); @@ -637,10 +676,7 @@ public abstract class BasicTextUI extends TextUI } } if (bindings == null) - { - bindings = new JTextComponent.KeyBinding[0]; - UIManager.put(prefix + ".focusInputMap", bindings); - } + bindings = new JTextComponent.KeyBinding[0]; Keymap km = JTextComponent.addKeymap(getKeymapName(), JTextComponent.getKeymap(JTextComponent.DEFAULT_KEYMAP)); @@ -726,8 +762,6 @@ public abstract class BasicTextUI extends TextUI super.uninstallUI(component); rootView.setView(null); - textComponent.removePropertyChangeListener(updateHandler); - uninstallDefaults(); uninstallListeners(); uninstallKeyboardActions(); @@ -750,6 +784,7 @@ public abstract class BasicTextUI extends TextUI */ protected void uninstallListeners() { + textComponent.removePropertyChangeListener(updateHandler); textComponent.removeFocusListener(focuslistener); textComponent.getDocument().removeDocumentListener(documentHandler); } @@ -786,7 +821,9 @@ public abstract class BasicTextUI extends TextUI float w = v.getPreferredSpan(View.X_AXIS); float h = v.getPreferredSpan(View.Y_AXIS); - return new Dimension((int) w, (int) h); + Insets i = c.getInsets(); + return new Dimension((int) w + i.left + i.right, + (int) h + i.top + i.bottom); } /** @@ -817,18 +854,49 @@ public abstract class BasicTextUI extends TextUI } /** - * Paints the text component. + * Paints the text component. This acquires a read lock on the model and then + * calls {@link #paintSafely(Graphics)} in order to actually perform the + * painting. * * @param g the Graphics context to paint to * @param c not used here */ public final void paint(Graphics g, JComponent c) { - paintSafely(g); + try + { + Document doc = textComponent.getDocument(); + if (doc instanceof AbstractDocument) + { + AbstractDocument aDoc = (AbstractDocument) doc; + aDoc.readLock(); + } + + paintSafely(g); + } + finally + { + Document doc = textComponent.getDocument(); + if (doc instanceof AbstractDocument) + { + AbstractDocument aDoc = (AbstractDocument) doc; + aDoc.readUnlock(); + } + } } /** - * Actually performs the painting. + * This paints the text component while beeing sure that the model is not + * modified while painting. + * + * The following is performed in this order: + *

    + *
  1. If the text component is opaque, the background is painted by + * calling {@link #paintBackground(Graphics)}.
  2. + *
  3. If there is a highlighter, the highlighter is painted.
  4. + *
  5. The view hierarchy is painted.
  6. + *
  7. The Caret is painter.
  8. + *
* * @param g the Graphics context to paint to */ @@ -840,9 +908,19 @@ public abstract class BasicTextUI extends TextUI if (textComponent.isOpaque()) paintBackground(g); - if (highlighter != null - && textComponent.getSelectionStart() != textComponent.getSelectionEnd()) - highlighter.paint(g); + // Try painting with the highlighter without checking whether there + // is a selection because a highlighter can be used to do more than + // marking selected text. + if (highlighter != null) + { + // Handle restoring of the color here to prevent + // drawing problems when the Highlighter implementor + // forgets to restore it. + Color oldColor = g.getColor(); + highlighter.paint(g); + g.setColor(oldColor); + } + rootView.paint(g, getVisibleEditorRect()); @@ -857,10 +935,23 @@ public abstract class BasicTextUI extends TextUI */ protected void paintBackground(Graphics g) { - // This method does nothing. All the background filling is done by the - // ComponentUI update method. However, the method is called by paint - // to provide a way for subclasses to draw something different (e.g. - // background images etc) on the background. + Color old = g.getColor(); + g.setColor(textComponent.getBackground()); + g.fillRect(0, 0, textComponent.getWidth(), textComponent.getHeight()); + g.setColor(old); + } + + /** + * Overridden for better control over background painting. This now simply + * calls {@link #paint} and this delegates the background painting to + * {@link #paintBackground}. + * + * @param g the graphics to use + * @param c the component to be painted + */ + public void update(Graphics g, JComponent c) + { + paint(g, c); } /** @@ -895,7 +986,84 @@ public abstract class BasicTextUI extends TextUI public void damageRange(JTextComponent t, int p0, int p1, Position.Bias firstBias, Position.Bias secondBias) { - // TODO: Implement me. + try + { + // Limit p0 and p1 to sane values to prevent unfriendly + // BadLocationExceptions. This makes it possible for the highlighter + // to send us illegal values which can happen when a large number + // of selected characters are removed (eg. by pressing delete + // or backspace). + // The reference implementation does not throw an exception, too. + p0 = Math.min(p0, t.getDocument().getLength()); + p1 = Math.min(p1, t.getDocument().getLength()); + + Rectangle l1 = modelToView(t, p0, firstBias); + Rectangle l2 = modelToView(t, p1, secondBias); + if (l1.y == l2.y) + t.repaint(l1.union(l2)); + else + { + // The two rectangles lie on different lines and we need a + // different algorithm to calculate the damaged area: + // 1. The line of p0 is damaged from the position of p0 + // to the right border. + // 2. All lines between the ones where p0 and p1 lie on + // are completely damaged. Use the allocation area to find + // out the bounds. + // 3. The final line is damaged from the left bound to the + // position of p1. + Insets insets = t.getInsets(); + + // Damage first line until the end. + l1.width = insets.right + t.getWidth() - l1.x; + t.repaint(l1); + + // Note: Utilities.getPositionBelow() may return the offset + // that was put in. In that case there is no next line and + // we should stop searching for one. + + int posBelow = Utilities.getPositionBelow(t, p0, l1.x); + if (posBelow < p1 && posBelow != -1 && posBelow != p0) + { + // Take the rectangle of the offset we just found and grow it + // to the maximum width. Retain y because this is our start + // height. + Rectangle grow = modelToView(t, posBelow); + grow.x = insets.left; + grow.width = t.getWidth() + insets.right; + + // Find further lines which have to be damaged completely. + int nextPosBelow = posBelow; + while (nextPosBelow < p1 && nextPosBelow != -1 && posBelow != nextPosBelow) + { + posBelow = nextPosBelow; + nextPosBelow = Utilities.getPositionBelow(t, posBelow, l1.x); + } + // Now posBelow is an offset on the last line which has to be damaged + // completely. (newPosBelow is on the same line as p1) + + // Retrieve the rectangle of posBelow and use its y and height + // value to calculate the final height of the multiple line + // spanning rectangle. + Rectangle end = modelToView(t, posBelow); + grow.height = end.y + end.height - grow.y; + + // Mark that area as damage. + t.repaint(grow); + } + + // Damage last line from its beginning to the position of p1. + l2.width += l2.x; + l2.x = insets.left; + t.repaint(l2); + } + } + catch (BadLocationException ex) + { + AssertionError err = new AssertionError("Unexpected bad location"); + err.initCause(ex); + throw err; + } } /** @@ -1061,7 +1229,6 @@ public abstract class BasicTextUI extends TextUI */ protected Rectangle getVisibleEditorRect() { - JTextComponent textComponent = getComponent(); int width = textComponent.getWidth(); int height = textComponent.getHeight(); @@ -1082,7 +1249,6 @@ public abstract class BasicTextUI extends TextUI protected final void setView(View view) { rootView.setView(view); - view.setParent(rootView); textComponent.revalidate(); textComponent.repaint(); } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java index f2ebcfc..1c6e6c5 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java @@ -45,6 +45,7 @@ import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Insets; +import java.awt.Label; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.ActionEvent; @@ -114,9 +115,18 @@ import javax.swing.tree.TreeSelectionModel; * @see javax.swing.JTree * @author Lillian Angel (langel@redhat.com) * @author Sascha Brawer (brawer@dandelis.ch) + * @author Audrius Meskauskas (audriusa@bioinformatics.org) */ public class BasicTreeUI extends TreeUI { + /** + * The tree cell editing may be started by the single mouse click on the + * selected cell. To separate it from the double mouse click, the editing + * session starts after this time (in ms) after that single click, and only + * no other clicks were performed during that time. + */ + static int WAIT_TILL_EDITING = 900; + /** Collapse Icon for the tree. */ protected transient Icon collapsedIcon; @@ -225,12 +235,6 @@ public class BasicTreeUI extends TreeUI /** Set to true if the editor has a different size than the renderer. */ protected boolean editorHasDifferentSize; - /** The action listener for the editor's Timer. */ - Timer editorTimer = new EditorUpdateTimer(); - - /** The new value of the node after editing. */ - Object newVal; - /** The action bound to KeyStrokes. */ TreeAction action; @@ -266,6 +270,20 @@ public class BasicTreeUI extends TreeUI private TreeExpansionListener treeExpansionListener; private TreeModelListener treeModelListener; + + /** + * This timer fires the editing action after about 1200 ms if not reset during + * that time. It handles the editing start with the single mouse click + * (and not the double mouse click) on the selected tree node. + */ + Timer startEditTimer; + + /** + * The special value of the mouse event is sent indicating that this is not + * just the mouse click, but the mouse click on the selected node. Sending + * such event forces to start the cell editing session. + */ + static final MouseEvent EDIT = new MouseEvent(new Label(), 7,7,7,7,7,7, false); /** * Creates a new BasicTreeUI object. @@ -303,7 +321,7 @@ public class BasicTreeUI extends TreeUI { return new BasicTreeUI(); } - + /** * Returns the Hash color. * @@ -796,7 +814,10 @@ public class BasicTreeUI extends TreeUI public boolean stopEditing(JTree tree) { if (isEditing(tree)) - completeEditing(true, false, false); + { + completeEditing(false, false, true); + finish(); + } return !isEditing(tree); } @@ -807,9 +828,12 @@ public class BasicTreeUI extends TreeUI * is the tree to cancel the editing session on. */ public void cancelEditing(JTree tree) - { - if (isEditing(tree)) - completeEditing(false, true, false); + { + // There is no need to send the cancel message to the editor, + // as the cancellation event itself arrives from it. This would + // only be necessary when cancelling the editing programatically. + completeEditing(false, false, false); + finish(); } /** @@ -1213,6 +1237,7 @@ public class BasicTreeUI extends TreeUI protected void updateCachedPreferredSize() { int maxWidth = 0; + updateCurrentVisiblePath(); boolean isLeaf = false; if (currentVisiblePath != null) { @@ -1246,7 +1271,7 @@ public class BasicTreeUI extends TreeUI protected void pathWasExpanded(TreePath path) { validCachedPreferredSize = false; - tree.repaint(); + tree.repaint(); } /** @@ -1271,7 +1296,6 @@ public class BasicTreeUI extends TreeUI leftChildIndent = UIManager.getInt("Tree.leftChildIndent"); setRowHeight(UIManager.getInt("Tree.rowHeight")); tree.setRowHeight(getRowHeight()); - tree.requestFocusInWindow(false); tree.setScrollsOnExpand(UIManager.getBoolean("Tree.scrollsOnExpand")); setExpandedIcon(UIManager.getIcon("Tree.expandedIcon")); setCollapsedIcon(UIManager.getIcon("Tree.collapsedIcon")); @@ -1621,7 +1645,14 @@ public class BasicTreeUI extends TreeUI } if (messageTree) - treeModel.valueForPathChanged(tree.getLeadSelectionPath(), newVal); + { + TreeCellEditor editor = getCellEditor(); + if (editor != null) + { + Object value = editor.getCellEditorValue(); + treeModel.valueForPathChanged(tree.getLeadSelectionPath(), value); + } + } } /** @@ -1636,44 +1667,48 @@ public class BasicTreeUI extends TreeUI */ protected boolean startEditing(TreePath path, MouseEvent event) { - int x; - int y; - if (event == null) - { - Rectangle bounds = getPathBounds(tree, path); - x = bounds.x; - y = bounds.y; - } - else - { - x = event.getX(); - y = event.getY(); - } + // Force to recalculate the maximal row height. + maxHeight = 0; + + // Force to recalculate the cached preferred size. + validCachedPreferredSize = false; updateCellEditor(); TreeCellEditor ed = getCellEditor(); - if (ed != null && ed.shouldSelectCell(event) && ed.isCellEditable(event)) + + if (ed != null + && (event == EDIT || ed.shouldSelectCell(event)) + && ed.isCellEditable(event)) { + Rectangle bounds = getPathBounds(tree, path); + + // Extend the right boundary till the tree width. + bounds.width = tree.getWidth() - bounds.x; + editingPath = path; editingRow = tree.getRowForPath(editingPath); - Object val = editingPath.getLastPathComponent(); - cellEditor.addCellEditorListener(cellEditorListener); + Object value = editingPath.getLastPathComponent(); + stopEditingInCompleteEditing = false; boolean expanded = tree.isExpanded(editingPath); isEditing = true; - editingComponent = ed.getTreeCellEditorComponent(tree, val, true, + editingComponent = ed.getTreeCellEditorComponent(tree, value, true, expanded, isLeaf(editingRow), editingRow); - editingComponent.getParent().setVisible(true); - editingComponent.getParent().validate(); - tree.add(editingComponent.getParent()); - editingComponent.getParent().validate(); - validCachedPreferredSize = false; - - ((JTextField) editingComponent).requestFocusInWindow(false); - editorTimer.start(); + + // Remove all previous components (if still present). Only one + // container with the editing component inside is allowed in the tree. + tree.removeAll(); + + // The editing component must be added to its container. We add the + // container, not the editing component itself. + Component container = editingComponent.getParent(); + container.setBounds(bounds); + tree.add(container); + editingComponent.requestFocus(); + return true; } return false; @@ -1922,7 +1957,7 @@ public class BasicTreeUI extends TreeUI tree.clearSelection(); if (tree.isEditing() && !e.getActionCommand().equals("startEditing")) - tree.cancelEditing(); + tree.stopEditing(); tree.scrollPathToVisible(lead); } @@ -1957,51 +1992,7 @@ public class BasicTreeUI extends TreeUI } } - /** - * The timer that updates the editor component. - */ - private class EditorUpdateTimer extends Timer implements ActionListener - { - /** - * Creates a new EditorUpdateTimer object with a default delay of 0.3 - * seconds. - */ - public EditorUpdateTimer() - { - super(300, null); - addActionListener(this); - } - - /** - * Lets the caret blink and repaints the table. - */ - public void actionPerformed(ActionEvent ev) - { - Caret c = ((JTextField) editingComponent).getCaret(); - if (c != null) - c.setVisible(!c.isVisible()); - tree.repaint(); - } - - /** - * Updates the blink delay according to the current caret. - */ - public void update() - { - stop(); - Caret c = ((JTextField) editingComponent).getCaret(); - if (c != null) - { - setDelay(c.getBlinkRate()); - if (((JTextField) editingComponent).isEditable()) - start(); - else - c.setVisible(false); - } - } - } - - /** + /** * Updates the preferred size when scrolling, if necessary. */ public class ComponentHandler extends ComponentAdapter implements @@ -2089,29 +2080,7 @@ public class BasicTreeUI extends TreeUI */ public void editingStopped(ChangeEvent e) { - editingPath = null; - editingRow = -1; - stopEditingInCompleteEditing = false; - if (editingComponent != null) - { - tree.remove(editingComponent.getParent()); - editingComponent = null; - } - if (cellEditor != null) - { - newVal = ((JTextField) getCellEditor().getCellEditorValue()).getText(); - completeEditing(false, false, true); - if (cellEditor instanceof DefaultTreeCellEditor) - tree.removeTreeSelectionListener((DefaultTreeCellEditor) cellEditor); - cellEditor.removeCellEditorListener(cellEditorListener); - setCellEditor(null); - createdCellEditor = false; - } - isEditing = false; - tree.requestFocusInWindow(false); - editorTimer.stop(); - validCachedPreferredSize = false; - tree.repaint(); + stopEditing(tree); } /** @@ -2123,25 +2092,7 @@ public class BasicTreeUI extends TreeUI */ public void editingCanceled(ChangeEvent e) { - editingPath = null; - editingRow = -1; - stopEditingInCompleteEditing = false; - if (editingComponent != null) - tree.remove(editingComponent.getParent()); - editingComponent = null; - if (cellEditor != null) - { - if (cellEditor instanceof DefaultTreeCellEditor) - tree.removeTreeSelectionListener((DefaultTreeCellEditor) cellEditor); - cellEditor.removeCellEditorListener(cellEditorListener); - setCellEditor(null); - createdCellEditor = false; - } - tree.requestFocusInWindow(false); - editorTimer.stop(); - isEditing = false; - validCachedPreferredSize = false; - tree.repaint(); + cancelEditing(tree); } }// CellEditorHandler @@ -2261,7 +2212,15 @@ public class BasicTreeUI extends TreeUI * is the mouse event that occured */ public void mousePressed(MouseEvent e) - { + { + // Any mouse click cancels the previous waiting edit action, initiated + // by the single click on the selected node. + if (startEditTimer != null) + { + startEditTimer.stop(); + startEditTimer = null; + } + Point click = e.getPoint(); TreePath path = getClosestPathForLocation(tree, click.x, click.y); @@ -2298,9 +2257,37 @@ public class BasicTreeUI extends TreeUI { if (inBounds) { - selectPath(tree, path); - if (e.getClickCount() == 2 && !isLeaf(row)) - toggleExpandState(path); + TreePath currentLead = tree.getLeadSelectionPath(); + if ( + currentLead != null && + currentLead.equals(path) && + e.getClickCount() == 1 && + tree.isEditable() + ) + { + // Schedule the editing session. + final TreePath editPath = path; + + if (startEditTimer != null) + startEditTimer.stop(); + + startEditTimer = new Timer(WAIT_TILL_EDITING, + new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + startEditing(editPath, EDIT); + } + }); + startEditTimer.setRepeats(false); + startEditTimer.start(); + } + else + { + selectPath(tree, path); + if (e.getClickCount() == 2 && !isLeaf(row)) + toggleExpandState(path); + } } if (cntlClick) @@ -2686,7 +2673,7 @@ public class BasicTreeUI extends TreeUI public class TreeHomeAction extends AbstractAction { - /** direction is either home or end */ + /** The direction, either home or end */ protected int direction; /** @@ -2983,7 +2970,7 @@ public class BasicTreeUI extends TreeUI public void valueChanged(TreeSelectionEvent event) { if (tree.isEditing()) - tree.cancelEditing(); + tree.stopEditing(); } }// TreeSelectionHandler @@ -3650,25 +3637,14 @@ public class BasicTreeUI extends TreeUI if (row != 0) bounds.x += gap; bounds.width = preferredSize.width + bounds.x; - if (editingComponent != null && editingPath != null && isEditing(tree) - && node.equals(editingPath.getLastPathComponent())) - { - rendererPane.paintComponent(g, editingComponent.getParent(), null, - bounds); - } - else - { - TreeCellRenderer dtcr = tree.getCellRenderer(); - if (dtcr == null) - dtcr = createDefaultCellRenderer(); - - Component c = dtcr.getTreeCellRendererComponent(tree, node, - selected, - isExpanded, isLeaf, - row, - tree.hasFocus()); - rendererPane.paintComponent(g, c, c.getParent(), bounds); - } + TreeCellRenderer dtcr = tree.getCellRenderer(); + if (dtcr == null) + dtcr = createDefaultCellRenderer(); + + Component c = dtcr.getTreeCellRendererComponent(tree, node, selected, + isExpanded, isLeaf, + row, tree.hasFocus()); + rendererPane.paintComponent(g, c, c.getParent(), bounds); } } @@ -3801,4 +3777,21 @@ public class BasicTreeUI extends TreeUI } return null; } + + /** + * Finish the editing session. + */ + void finish() + { + editingPath = null; + editingRow = -1; + stopEditingInCompleteEditing = false; + isEditing = false; + tree.removeAll(); + validCachedPreferredSize = false; + + // Repaint the region, where was the editing component. + tree.repaint(editingComponent.getParent().getBounds()); + editingComponent = null; + } } // BasicTreeUI diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java b/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java index 28143d5..99c90ac 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java @@ -1,5 +1,5 @@ /* MetalBorders.java - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -249,30 +249,27 @@ public class MetalBorders /** * Returns the insets of the ButtonBorder. * - * @param c the component for which the border is used + * @param c the component for which the border is used (ignored). * - * @return The insets of the ButtonBorder + * @return The insets of the ButtonBorder. */ public Insets getBorderInsets(Component c) { - return getBorderInsets(c, null); + return borderInsets; } /** * Returns the insets of the ButtonBorder in the specified * newInsets object. * - * @param c the component for which the border is used - * @param newInsets the insets object where to put the values (if - * null, a new instance is created). + * @param c the component for which the border is used (ignored). + * @param newInsets the insets object where to put the values ( + * null not permitted). * - * @return The insets. + * @return The newInsets reference. */ public Insets getBorderInsets(Component c, Insets newInsets) { - if (newInsets == null) - newInsets = new Insets(0, 0, 0, 0); - newInsets.bottom = borderInsets.bottom; newInsets.left = borderInsets.left; newInsets.right = borderInsets.right; @@ -352,6 +349,8 @@ public class MetalBorders public static class Flush3DBorder extends AbstractBorder implements UIResource { + private static final Insets borderInsets = new Insets(2, 2, 2, 2); + /** * Creates a new border instance. */ @@ -369,26 +368,25 @@ public class MetalBorders */ public Insets getBorderInsets(Component c) { - return getBorderInsets(c, null); + return borderInsets; } /** * Returns the border insets. * * @param c the component (ignored). - * @return The border insets. + * @param newInsets an existing insets instance, that will be populated + * with the border insets and returned as the result + * (null not permitted). + * + * @return The newInsets reference. */ public Insets getBorderInsets(Component c, Insets newInsets) { - if (newInsets == null) - newInsets = new Insets(2, 2, 2, 2); - else - { - newInsets.top = 2; - newInsets.left = 2; - newInsets.bottom = 2; - newInsets.right = 2; - } + newInsets.top = borderInsets.top; + newInsets.left = borderInsets.left; + newInsets.bottom = borderInsets.bottom; + newInsets.right = borderInsets.right; return newInsets; } @@ -427,6 +425,8 @@ public class MetalBorders public static class PaletteBorder extends AbstractBorder implements UIResource { + private static final Insets borderInsets = new Insets(1, 1, 1, 1); + /** * Creates a new PaletteBorder. */ @@ -444,29 +444,25 @@ public class MetalBorders */ public Insets getBorderInsets(Component c) { - return getBorderInsets(c, null); + return borderInsets; } /** * Returns the border insets. * * @param c the component (ignored). - * @param newInsets the insets object that, if non-null, will - * be populated with the result from this method. - * - * @return The border insets. + * @param newInsets an existing insets instance, that will be populated + * with the border insets and returned as the result + * (null not permitted). + * + * @return The newInsets reference. */ public Insets getBorderInsets(Component c, Insets newInsets) { - if (newInsets == null) - newInsets = new Insets(1, 1, 1, 1); - else - { - newInsets.top = 1; - newInsets.left = 1; - newInsets.bottom = 1; - newInsets.right = 1; - } + newInsets.top = borderInsets.top; + newInsets.left = borderInsets.left; + newInsets.bottom = borderInsets.bottom; + newInsets.right = borderInsets.right; return newInsets; } @@ -555,6 +551,8 @@ public class MetalBorders public static class InternalFrameBorder extends AbstractBorder implements UIResource { + private static final Insets borderInsets = new Insets(5, 5, 5, 5); + /** * Creates a new border instance. */ @@ -572,26 +570,25 @@ public class MetalBorders */ public Insets getBorderInsets(Component c) { - return getBorderInsets(c, null); + return borderInsets; } /** * Returns the border insets. * * @param c the component (ignored). - * @return The border insets. + * @param newInsets an existing insets instance, that will be populated + * with the border insets and returned as the result + * (null not permitted). + * + * @return The newInsets reference. */ public Insets getBorderInsets(Component c, Insets newInsets) { - if (newInsets == null) - newInsets = new Insets(5, 5, 5, 5); - else - { - newInsets.top = 5; - newInsets.left = 5; - newInsets.bottom = 5; - newInsets.right = 5; - } + newInsets.top = borderInsets.top; + newInsets.left = borderInsets.left; + newInsets.bottom = borderInsets.bottom; + newInsets.right = borderInsets.right; return newInsets; } @@ -763,7 +760,7 @@ public class MetalBorders implements UIResource { /** The border insets. */ - protected static Insets borderInsets = new Insets(1, 1, 1, 1); + protected static Insets borderInsets = new Insets(2, 2, 2, 2); /** * Creates a new border instance. diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalFileChooserUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalFileChooserUI.java index 967c40d..cb94c87 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalFileChooserUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalFileChooserUI.java @@ -1545,8 +1545,6 @@ public class MetalFileChooserUI fileListPanel = new JPanel(new BorderLayout()); fileList = new JList(getModel()); scrollPane = new JScrollPane(fileList); - scrollPane.setVerticalScrollBarPolicy - (JScrollPane.VERTICAL_SCROLLBAR_NEVER); fileList.setLayoutOrientation(JList.VERTICAL_WRAP); fileList.setCellRenderer(new FileRenderer()); } @@ -1557,7 +1555,10 @@ public class MetalFileChooserUI scrollPane.getViewport().setView(fileList); } fileListPanel.add(scrollPane); - + // This size was determined using BeanShell and dumping the JFileChooser + // component hierarchy. Sun has an internal FilePane class in there, but + // that probably doesn't matter atm. + fileListPanel.setPreferredSize(new Dimension(405, 135)); return fileListPanel; } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java b/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java index c60b55c..e846446 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java @@ -1171,6 +1171,7 @@ public class MetalLookAndFeel extends BasicLookAndFeel "Spinner.arrowButtonInsets", new InsetsUIResource(0, 0, 0, 0), "Spinner.background", getControl(), + "Spinner.border", MetalBorders.getTextFieldBorder(), "Spinner.font", new FontUIResource("Dialog", Font.BOLD, 12), "Spinner.foreground", getControl(), @@ -1342,4 +1343,16 @@ public class MetalLookAndFeel extends BasicLookAndFeel { return theme; } + + /** + * Returns true because the Metal look + * and feel supports window decorations for toplevel + * containers. + * + * @return true + */ + public boolean getSupportsWindowDecorations() + { + return true; + } } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java index faed803..23051e9 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java @@ -1,5 +1,5 @@ /* MetalRootPaneUI.java - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,23 +38,842 @@ exception statement from your version. */ package javax.swing.plaf.metal; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.LayoutManager2; +import java.awt.Rectangle; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.WindowEvent; +import java.awt.event.WindowFocusListener; +import java.beans.PropertyChangeEvent; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.Icon; +import javax.swing.JButton; import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JLayeredPane; +import javax.swing.JMenu; +import javax.swing.JMenuBar; import javax.swing.JRootPane; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.border.AbstractBorder; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicRootPaneUI; /** - * A UI delegate for the {@link JRootPane} component. This class is not fully - * implemented. + * A UI delegate for the {@link JRootPane} component. This implementation + * supports the JRootPane windowDecorationStyle property. * + * @author Roman Kennke (kennke@aicas.com) + * * @since 1.4 */ public class MetalRootPaneUI extends BasicRootPaneUI { - // FIXME: maybe replace by a Map of instances when this becomes stateful - /** The shared UI instance for MetalRootPaneUIs */ + /** + * The border that is used on JRootPane when the windowDecorationStyle + * property of the JRootPane is set to a different value than NONE. + * + * @author Roman Kennke (kennke@aicas.com) + */ + private static class MetalFrameBorder + extends AbstractBorder + { + /** + * Returns the border insets. + * + * @param c the component + * @param newInsets the insets to be filled with the return value, may be + * null in which case a new object is created + * + * @return the border insets + */ + public Insets getBorderInsets(Component c, Insets newInsets) + { + if (newInsets == null) + newInsets = new Insets(5, 5, 5, 5); + else + { + newInsets.top = 5; + newInsets.left = 5; + newInsets.bottom = 5; + newInsets.right = 5; + } + return newInsets; + } + + /** + * Returns the border insets. + * + * @param c the component + * + * @return the border insets + */ + public Insets getBorderInsets(Component c) + { + return getBorderInsets(c, null); + } + + /** + * Paints the border for the specified component. + * + * @param c the component + * @param g the graphics device + * @param x the x-coordinate + * @param y the y-coordinate + * @param w the width + * @param h the height + */ + public void paintBorder(Component c, Graphics g, int x, int y, int w, + int h) + { + JRootPane f = (JRootPane) c; + Window frame = SwingUtilities.getWindowAncestor(f); + if (frame.isActive()) + g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow()); + else + g.setColor(MetalLookAndFeel.getControlDarkShadow()); + + // Fill the border background. + g.fillRect(x, y, w, 5); + g.fillRect(x, y, 5, h); + g.fillRect(x + w - 5, y, 5, h); + g.fillRect(x, y + h - 5, w, 5); + + // Draw a dot in each corner. + g.setColor(MetalLookAndFeel.getControl()); + g.fillRect(x, y, 1, 1); + g.fillRect(x + w - 1, y, 1, 1); + g.fillRect(x + w - 1, y + h - 1, 1, 1); + g.fillRect(x, y + h - 1, 1, 1); + + // Draw the lines. + g.setColor(MetalLookAndFeel.getBlack()); + g.drawLine(x + 14, y + 2, x + w - 15, y + 2); + g.drawLine(x + 14, y + h - 3, x + w - 15, y + h - 3); + g.drawLine(x + 2, y + 14, x + 2, y + h - 15); + g.drawLine(x + w - 3, y + 14, x + w - 3, y + h - 15); + + // Draw the line highlights. + if (frame.isActive()) + g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + else + g.setColor(MetalLookAndFeel.getControlShadow()); + g.drawLine(x + 15, y + 3, x + w - 14, y + 3); + g.drawLine(x + 15, y + h - 2, x + w - 14, y + h - 2); + g.drawLine(x + 3, y + 15, x + 3, y + h - 14); + g.drawLine(x + w - 2, y + 15, x + w - 2, y + h - 14); + } + } + + /** + * The component that renders the title bar for frames. This duplicates + * most of {@link MetalInternalFrameTitlePane}. It is not reasonably possible + * to reuse that class because that is bound to the JInternalFrame and we + * need to handle JFrames/JRootPanes here. + * + * @author Roman Kennke (kennke@aicas.com) + */ + private static class MetalTitlePane extends JComponent + { + /** + * The Action responsible for closing the JInternalFrame. + */ + private class CloseAction extends AbstractAction + { + /** + * Creates a new action. + */ + public CloseAction() + { + super("Close"); + } + + /** + * This method is called when something closes the frame. + * + * @param e the ActionEvent + */ + public void actionPerformed(ActionEvent e) + { + Window frame = SwingUtilities.getWindowAncestor(rootPane); + if (frame instanceof JFrame) + { + JFrame jframe = (JFrame) frame; + switch (jframe.getDefaultCloseOperation()) + { + case JFrame.EXIT_ON_CLOSE: + jframe.setVisible(false); + jframe.dispose(); + System.exit(0); + break; + case JFrame.DISPOSE_ON_CLOSE: + jframe.setVisible(false); + jframe.dispose(); + break; + case JFrame.HIDE_ON_CLOSE: + jframe.setVisible(false); + break; + case JFrame.DO_NOTHING_ON_CLOSE: + default: + break; + } + } + else if (frame instanceof JDialog) + { + JDialog jdialog = (JDialog) frame; + switch (jdialog.getDefaultCloseOperation()) + { + case JFrame.DISPOSE_ON_CLOSE: + jdialog.setVisible(false); + jdialog.dispose(); + break; + case JFrame.HIDE_ON_CLOSE: + jdialog.setVisible(false); + break; + case JFrame.DO_NOTHING_ON_CLOSE: + default: + break; + } + } + } + } + + /** + * This helper class is used to create the minimize, maximize and close + * buttons in the top right corner of the Title Pane. These buttons are + * special since they cannot be given focus and have no border. + */ + private class PaneButton extends JButton + { + /** + * Creates a new PaneButton object with the given Action. + * + * @param a The Action that the button uses. + */ + public PaneButton(Action a) + { + super(a); + setMargin(new Insets(0, 0, 0, 0)); + } + + /** + * This method returns true if the Component can be focused. + * + * @return false. + */ + public boolean isFocusable() + { + // These buttons cannot be given focus. + return false; + } + + } + + /** + * The layout for the JRootPane when the windowDecorationStyle + * property is set. In addition to the usual JRootPane.RootLayout behaviour + * this lays out the titlePane. + * + * @author Roman Kennke (kennke@aicas.com) + */ + private class MetalTitlePaneLayout implements LayoutManager + { + /** + * Creates a new TitlePaneLayout object. + */ + public MetalTitlePaneLayout() + { + // Do nothing. + } + + /** + * Adds a Component to the Container. + * + * @param name The name to reference the added Component by. + * @param c The Component to add. + */ + public void addLayoutComponent(String name, Component c) + { + // Do nothing. + } + + /** + * This method is called to lay out the children of the Title Pane. + * + * @param c The Container to lay out. + */ + public void layoutContainer(Container c) + { + + Dimension size = c.getSize(); + Insets insets = c.getInsets(); + int width = size.width - insets.left - insets.right; + int height = size.height - insets.top - insets.bottom; + + int loc = width - insets.right - 1; + int top = insets.top + 2; + int buttonHeight = height - 4; + if (closeButton.isVisible()) + { + int buttonWidth = closeIcon.getIconWidth(); + loc -= buttonWidth + 2; + closeButton.setBounds(loc, top, buttonWidth, buttonHeight); + loc -= 6; + } + + if (maxButton.isVisible()) + { + int buttonWidth = maxIcon.getIconWidth(); + loc -= buttonWidth + 4; + maxButton.setBounds(loc, top, buttonWidth, buttonHeight); + } + + if (iconButton.isVisible()) + { + int buttonWidth = minIcon.getIconWidth(); + loc -= buttonWidth + 4; + iconButton.setBounds(loc, top, buttonWidth, buttonHeight); + loc -= 2; + } + + Dimension titlePreferredSize = title.getPreferredSize(); + title.setBounds(insets.left + 5, insets.top, + Math.min(titlePreferredSize.width, loc - insets.left - 10), + height); + + } + + /** + * This method returns the minimum size of the given Container given the + * children that it has. + * + * @param c The Container to get a minimum size for. + * + * @return The minimum size of the Container. + */ + public Dimension minimumLayoutSize(Container c) + { + return preferredLayoutSize(c); + } + + /** + * Returns the preferred size of the given Container taking + * into account the children that it has. + * + * @param c The Container to lay out. + * + * @return The preferred size of the Container. + */ + public Dimension preferredLayoutSize(Container c) + { + return new Dimension(22, 22); + } + + /** + * Removes a Component from the Container. + * + * @param c The Component to remove. + */ + public void removeLayoutComponent(Component c) + { + // Nothing to do here. + } + } + + JRootPane rootPane; + + /** The button that closes the JInternalFrame. */ + JButton closeButton; + + /** The button that iconifies the JInternalFrame. */ + JButton iconButton; + + /** The button that maximizes the JInternalFrame. */ + JButton maxButton; + + Icon minIcon; + + /** The icon displayed in the maximize button. */ + Icon maxIcon; + + /** The icon displayed in the iconify button. */ + private Icon iconIcon; + + /** The icon displayed in the close button. */ + Icon closeIcon; + + /** + * The background color of the TitlePane when the JInternalFrame is not + * selected. + */ + private Color notSelectedTitleColor; + + /** + * The background color of the TitlePane when the JInternalFrame is + * selected. + */ + private Color selectedTitleColor; + + /** + * The label used to display the title. This label is not added to the + * TitlePane. + */ + JLabel title; + + /** The action associated with closing the JInternalFrame. */ + private Action closeAction; + + /** The action associated with iconifying the JInternalFrame. */ + private Action iconifyAction; + + /** The action associated with maximizing the JInternalFrame. */ + private Action maximizeAction; + + /** The JMenuBar that is located at the top left of the Title Pane. */ + private JMenuBar menuBar; + + /** The JMenu inside the menuBar. */ + protected JMenu windowMenu; + + MetalTitlePane(JRootPane rp) + { + rootPane = rp; + setLayout(createLayout()); + title = new JLabel(); + title.setHorizontalAlignment(SwingConstants.LEFT); + title.setHorizontalTextPosition(SwingConstants.LEFT); + title.setOpaque(false); + installTitlePane(); + } + + protected LayoutManager createLayout() + { + return new MetalTitlePaneLayout(); + } + + /** + * This method installs the TitlePane onto the JInternalFrameTitlePane. It + * also creates any children components that need to be created and adds + * listeners to the appropriate components. + */ + protected void installTitlePane() + { + installDefaults(); + installListeners(); + createActions(); + assembleSystemMenu(); + createButtons(); + setButtonIcons(); + addSubComponents(); + enableActions(); + } + + private void enableActions() + { + // TODO: Implement this. + } + + private void addSubComponents() + { + add(menuBar); + add(closeButton); + add(iconButton); + add(maxButton); + } + + private void installListeners() + { + Window window = SwingUtilities.getWindowAncestor(rootPane); + window.addWindowFocusListener(new WindowFocusListener() + { + public void windowGainedFocus(WindowEvent ev) + { + repaint(); + } + public void windowLostFocus(WindowEvent ev) + { + repaint(); + } + }); + } + + private void createActions() + { + closeAction = new CloseAction(); + } + + private void assembleSystemMenu() + { + menuBar = createSystemMenuBar(); + windowMenu = createSystemMenu(); + menuBar.add(windowMenu); + addSystemMenuItems(windowMenu); + enableActions(); + } + + protected JMenuBar createSystemMenuBar() + { + if (menuBar == null) + menuBar = new JMenuBar(); + menuBar.removeAll(); + return menuBar; + } + + protected JMenu createSystemMenu() + { + if (windowMenu == null) + windowMenu = new JMenu(); + windowMenu.removeAll(); + return windowMenu; + } + + private void addSystemMenuItems(JMenu menu) + { + // TODO: Implement this. + } + + protected void createButtons() + { + closeButton = new PaneButton(closeAction); + closeButton.setText(null); + iconButton = new PaneButton(iconifyAction); + iconButton.setText(null); + maxButton = new PaneButton(maximizeAction); + maxButton.setText(null); + closeButton.setBorderPainted(false); + closeButton.setContentAreaFilled(false); + iconButton.setBorderPainted(false); + iconButton.setContentAreaFilled(false); + maxButton.setBorderPainted(false); + maxButton.setContentAreaFilled(false); + } + + protected void setButtonIcons() + { + if (closeIcon != null && closeButton != null) + closeButton.setIcon(closeIcon); + if (iconIcon != null && iconButton != null) + iconButton.setIcon(iconIcon); + if (maxIcon != null && maxButton != null) + maxButton.setIcon(maxIcon); + } + + /** + * Paints a representation of the current state of the internal frame. + * + * @param g the graphics device. + */ + public void paintComponent(Graphics g) + { + Window frame = SwingUtilities.getWindowAncestor(rootPane); + Color savedColor = g.getColor(); + paintTitleBackground(g); + paintChildren(g); + Dimension d = getSize(); + if (frame.isActive()) + g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow()); + else + g.setColor(MetalLookAndFeel.getControlDarkShadow()); + + // put a dot in each of the top corners + g.drawLine(0, 0, 0, 0); + g.drawLine(d.width - 1, 0, d.width - 1, 0); + + g.drawLine(0, d.height - 1, d.width - 1, d.height - 1); + + // draw the metal pattern + if (UIManager.get("InternalFrame.activeTitleGradient") != null + && frame.isActive()) + { + MetalUtils.paintGradient(g, 0, 0, getWidth(), getHeight(), + SwingConstants.VERTICAL, + "InternalFrame.activeTitleGradient"); + } + + Rectangle b = title.getBounds(); + int startX = b.x + b.width + 5; + int endX = startX; + if (iconButton.isVisible()) + endX = Math.max(iconButton.getX(), endX); + else if (maxButton.isVisible()) + endX = Math.max(maxButton.getX(), endX); + else if (closeButton.isVisible()) + endX = Math.max(closeButton.getX(), endX); + endX -= 7; + if (endX > startX) + MetalUtils.fillMetalPattern(this, g, startX, 3, endX - startX, getHeight() - 6, Color.white, Color.gray); + g.setColor(savedColor); + } + + /** + * This method paints the TitlePane's background. + * + * @param g The Graphics object to paint with. + */ + protected void paintTitleBackground(Graphics g) + { + Window frame = SwingUtilities.getWindowAncestor(rootPane); + + if (!isOpaque()) + return; + + Color saved = g.getColor(); + Dimension dims = getSize(); + + Color bg = getBackground(); + if (frame.isActive()) + bg = selectedTitleColor; + else + bg = notSelectedTitleColor; + g.setColor(bg); + g.fillRect(0, 0, dims.width, dims.height); + g.setColor(saved); + } + + /** + * This method installs the defaults determined by the look and feel. + */ + private void installDefaults() + { + title.setFont(UIManager.getFont("InternalFrame.titleFont")); + selectedTitleColor = UIManager.getColor("InternalFrame.activeTitleBackground"); + notSelectedTitleColor = UIManager.getColor("InternalFrame.inactiveTitleBackground"); + closeIcon = UIManager.getIcon("InternalFrame.closeIcon"); + iconIcon = UIManager.getIcon("InternalFrame.iconifyIcon"); + maxIcon = UIManager.getIcon("InternalFrame.maximizeIcon"); + minIcon = MetalIconFactory.getInternalFrameAltMaximizeIcon(16); + Frame frame = (Frame) SwingUtilities.getWindowAncestor(rootPane); + title = new JLabel(frame.getTitle(), + MetalIconFactory.getInternalFrameDefaultMenuIcon(), + SwingConstants.LEFT); + } + } + + private static class MetalRootLayout + implements LayoutManager2 + { + + /** + * The cached layout info for the glass pane. + */ + private Rectangle glassPaneBounds; + + /** + * The cached layout info for the layered pane. + */ + private Rectangle layeredPaneBounds; + + /** + * The cached layout info for the content pane. + */ + private Rectangle contentPaneBounds; + + /** + * The cached layout info for the menu bar. + */ + private Rectangle menuBarBounds; + + /** + * The cached layout info for the title pane. + */ + private Rectangle titlePaneBounds; + + /** + * The cached preferred size. + */ + private Dimension prefSize; + + public void addLayoutComponent(Component component, Object constraints) + { + // Nothing to do here. + } + + public Dimension maximumLayoutSize(Container target) + { + return preferredLayoutSize(target); + } + + public float getLayoutAlignmentX(Container target) + { + return 0.0F; + } + + public float getLayoutAlignmentY(Container target) + { + return 0.0F; + } + + public void invalidateLayout(Container target) + { + synchronized (this) + { + glassPaneBounds = null; + layeredPaneBounds = null; + contentPaneBounds = null; + menuBarBounds = null; + titlePaneBounds = null; + prefSize = null; + } + } + + public void addLayoutComponent(String name, Component component) + { + // Nothing to do here. + } + + public void removeLayoutComponent(Component component) + { + // TODO Auto-generated method stub + + } + + public Dimension preferredLayoutSize(Container parent) + { + JRootPane rp = (JRootPane) parent; + JLayeredPane layeredPane = rp.getLayeredPane(); + Component contentPane = layeredPane.getComponent(0); + Component titlePane = layeredPane.getComponent(1); + Component menuBar = null; + if (layeredPane.getComponentCount() > 2 + && layeredPane.getComponent(2) instanceof JMenuBar) + menuBar = layeredPane.getComponent(2); + + // We must synchronize here, otherwise we cannot guarantee that the + // prefSize is still non-null when returning. + synchronized (this) + { + if (prefSize == null) + { + Insets i = parent.getInsets(); + prefSize = new Dimension(i.left + i.right, i.top + i.bottom); + Dimension contentPrefSize = contentPane.getPreferredSize(); + prefSize.width += contentPrefSize.width; + prefSize.height += contentPrefSize.height + + titlePane.getPreferredSize().height; + if (menuBar != null) + { + Dimension menuBarSize = menuBar.getPreferredSize(); + if (menuBarSize.width > contentPrefSize.width) + prefSize.width += menuBarSize.width - contentPrefSize.width; + prefSize.height += menuBarSize.height; + } + } + // Return a copy here so the cached value won't get trashed by some + // other component. + return new Dimension(prefSize); + } + } + + public Dimension minimumLayoutSize(Container parent) + { + return preferredLayoutSize(parent); + } + + public void layoutContainer(Container parent) + { + JRootPane rp = (JRootPane) parent; + JLayeredPane layeredPane = rp.getLayeredPane(); + Component contentPane = layeredPane.getComponent(0); + Component titlePane = layeredPane.getComponent(1); + Component menuBar = null; + if (layeredPane.getComponentCount() > 2 + && layeredPane.getComponent(2) instanceof JMenuBar) + menuBar = layeredPane.getComponent(2); + Component glassPane = rp.getGlassPane(); + + if (glassPaneBounds == null || layeredPaneBounds == null + || contentPaneBounds == null || menuBarBounds == null) + { + Insets i = rp.getInsets(); + int containerWidth = parent.getBounds().width - i.left - i.right; + int containerHeight = parent.getBounds().height - i.top - i.bottom; + + // 1. The glassPane fills entire viewable region (bounds - insets). + // 2. The layeredPane filles entire viewable region. + // 3. The titlePane is placed at the upper edge of the layeredPane. + // 4. The menuBar is positioned at the upper edge of layeredPane. + // 5. The contentPane fills viewable region minus menuBar minus + // titlePane, if present. + + // +-------------------------------+ + // | JLayeredPane | + // | +--------------------------+ | + // | | titlePane + | + // | +--------------------------+ | + // | +--------------------------+ | + // | | menuBar | | + // | +--------------------------+ | + // | +--------------------------+ | + // | |contentPane | | + // | | | | + // | | | | + // | | | | + // | +--------------------------+ | + // +-------------------------------+ + + // Setup titlePaneBounds. + if (titlePaneBounds == null) + titlePaneBounds = new Rectangle(); + titlePaneBounds.width = containerWidth; + titlePaneBounds.height = titlePane.getPreferredSize().height; + + // Setup menuBarBounds. + if (menuBarBounds == null) + menuBarBounds = new Rectangle(); + menuBarBounds.setBounds(0, + titlePaneBounds.y + titlePaneBounds.height, + containerWidth, 0); + if (menuBar != null) + { + Dimension menuBarSize = menuBar.getPreferredSize(); + if (menuBarSize.height > containerHeight) + menuBarBounds.height = containerHeight; + else + menuBarBounds.height = menuBarSize.height; + } + + // Setup contentPaneBounds. + if (contentPaneBounds == null) + contentPaneBounds = new Rectangle(); + contentPaneBounds.setBounds(0, + menuBarBounds.y + menuBarBounds.height, + containerWidth, + containerHeight - menuBarBounds.y + - menuBarBounds.height); + glassPaneBounds = new Rectangle(i.left, i.top, containerWidth, containerHeight); + layeredPaneBounds = new Rectangle(i.left, i.top, containerWidth, containerHeight); + } + + // Layout components. + glassPane.setBounds(glassPaneBounds); + layeredPane.setBounds(layeredPaneBounds); + if (menuBar != null) + menuBar.setBounds(menuBarBounds); + contentPane.setBounds(contentPaneBounds); + titlePane.setBounds(titlePaneBounds); + } + + } + + /** + * The shared UI instance for MetalRootPaneUIs. + */ private static MetalRootPaneUI instance = null; /** @@ -78,4 +897,84 @@ public class MetalRootPaneUI instance = new MetalRootPaneUI(); return instance; } + + /** + * Installs this UI to the root pane. If the + * windowDecorationsStyle property is set on the root pane, + * the Metal window decorations are installed on the root pane. + * + * @param c + */ + public void installUI(JComponent c) + { + super.installUI(c); + JRootPane rp = (JRootPane) c; + if (rp.getWindowDecorationStyle() != JRootPane.NONE) + installWindowDecorations(rp); + } + + /** + * Uninstalls the UI from the root pane. This performs the superclass + * behaviour and uninstalls the window decorations that have possibly been + * installed by {@link #installUI}. + * + * @param c the root pane + */ + public void uninstallUI(JComponent c) + { + JRootPane rp = (JRootPane) c; + if (rp.getWindowDecorationStyle() != JRootPane.NONE) + uninstallWindowDecorations(rp); + super.uninstallUI(c); + } + + /** + * Receives notification if any of the JRootPane's property changes. In + * particular this catches changes to the windowDecorationStyle + * property and installs the window decorations accordingly. + * + * @param ev the property change event + */ + public void propertyChange(PropertyChangeEvent ev) + { + String propertyName = ev.getPropertyName(); + if (propertyName.equals("windowDecorationStyle")) + { + JRootPane rp = (JRootPane) ev.getSource(); + if (rp.getWindowDecorationStyle() != JRootPane.NONE) + installWindowDecorations(rp); + else + uninstallWindowDecorations(rp); + } + } + + /** + * Installs the window decorations to the root pane. This sets up a border, + * a title pane and a layout manager that can layout the root pane with that + * title pane. + * + * @param rp the root pane. + */ + private void installWindowDecorations(JRootPane rp) + { + rp.setBorder(new MetalFrameBorder()); + rp.setLayout(new MetalRootLayout()); + // We should have a contentPane already. + assert rp.getLayeredPane().getComponentCount() == 1 + : "We should have a contentPane already"; + rp.getLayeredPane().add(new MetalTitlePane(rp), + JLayeredPane.FRAME_CONTENT_LAYER); + } + + /** + * Uninstalls the window decorations from the root pane. This should rarely + * be necessary, but we do it anyway. + * + * @param rp the root pane + */ + private void uninstallWindowDecorations(JRootPane rp) + { + rp.setBorder(null); + rp.getLayeredPane().remove(1); + } } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java index 0ff501f..155bb81 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java @@ -41,6 +41,7 @@ package javax.swing.plaf.metal; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; +import java.awt.Insets; import java.awt.Rectangle; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; @@ -48,6 +49,7 @@ import java.beans.PropertyChangeListener; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JScrollBar; +import javax.swing.SwingConstants; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicScrollBarUI; @@ -465,11 +467,60 @@ public class MetalScrollBarUI extends BasicScrollBarUI */ protected Dimension getMinimumThumbSize() { - if (isFreeStanding) - return MIN_THUMB_SIZE_FREE_STANDING; + Dimension retVal; + if (scrollbar != null) + { + if (isFreeStanding) + retVal = MIN_THUMB_SIZE_FREE_STANDING; + else + retVal = MIN_THUMB_SIZE; + } else - return MIN_THUMB_SIZE; + retVal = new Dimension(0, 0); + return retVal; } - + + /** + * Returns the preferredSize for the specified scroll bar. + * For a vertical scrollbar the height is the sum of the preferred heights + * of the buttons plus 30. The width is fetched from the + * UIManager property ScrollBar.width. + * + * For horizontal scrollbars the width is the sum of the preferred widths + * of the buttons plus 30. The height is fetched from the + * UIManager property ScrollBar.height. + * + * @param c the scrollbar for which to calculate the preferred size + * + * @return the preferredSize for the specified scroll bar + */ + public Dimension getPreferredSize(JComponent c) + { + int height; + int width; + height = width = 0; + + if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL) + { + width += incrButton.getPreferredSize().getWidth(); + width += decrButton.getPreferredSize().getWidth(); + width += 30; + height = UIManager.getInt("ScrollBar.width"); + } + else + { + height += incrButton.getPreferredSize().getHeight(); + height += decrButton.getPreferredSize().getHeight(); + height += 30; + width = UIManager.getInt("ScrollBar.width"); + } + + Insets insets = scrollbar.getInsets(); + + height += insets.top + insets.bottom; + width += insets.left + insets.right; + + return new Dimension(width, height); + } } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java b/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java index 34a964c..9c592bd5 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java @@ -42,11 +42,13 @@ import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.Graphics; +import java.awt.Insets; import java.awt.LayoutManager; import java.awt.Point; import javax.swing.JSplitPane; import javax.swing.SwingConstants; +import javax.swing.border.Border; import javax.swing.plaf.basic.BasicArrowButton; import javax.swing.plaf.basic.BasicSplitPaneDivider; @@ -93,6 +95,12 @@ class MetalSplitPaneDivider extends BasicSplitPaneDivider public void paint(Graphics g) { Dimension s = getSize(); + + // Paint border if one exists. + Border border = getBorder(); + if (border != null) + border.paintBorder(this, g, 0, 0, s.width, s.height); + MetalUtils.fillMetalPattern(splitPane, g, 2, 2, s.width - 4, s.height - 4, light, dark); if (splitPane.isOneTouchExpandable()) diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java b/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java index 50112ce..b9d5ea7 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java @@ -37,6 +37,8 @@ exception statement from your version. */ package javax.swing.plaf.metal; +import gnu.classpath.SystemProperties; + import java.awt.Color; import java.awt.Component; import java.awt.Graphics; @@ -88,7 +90,8 @@ class MetalUtils static void fillMetalPattern(Component c, Graphics g, int x, int y, int w, int h, Color light, Color dark) { - if (g instanceof Graphics2D) + if (g instanceof Graphics2D + && SystemProperties.getProperty("gnu.javax.swing.noGraphics2D") != null) fillMetalPattern2D((Graphics2D) g, x, y, w, h, light, dark); else { diff --git a/libjava/classpath/javax/swing/plaf/synth/ColorType.java b/libjava/classpath/javax/swing/plaf/synth/ColorType.java new file mode 100644 index 0000000..954e309 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/synth/ColorType.java @@ -0,0 +1,130 @@ +/* ColorType.java -- En enumeration of color types + 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 javax.swing.plaf.synth; + +/** + * A typesafe enumeration of color types. + * + * @author Roman Kennke (kennke@aicas.com) + * + * @since 1.5 + */ +public class ColorType +{ + + /** + * A constant used to identify the foreground color of a component. + */ + public static final ColorType FOREGROUND = new ColorType("Foreground"); + + /** + * A constant used to identify the background color of a component. + */ + public static final ColorType BACKGROUND = new ColorType("Background"); + + /** + * A constant used to identify the foreground color of text of a component. + */ + public static final ColorType TEXT_FOREGROUND + = new ColorType("TextForeground"); + + /** + * A constant used to identify the background color of text of a component. + */ + public static final ColorType TEXT_BACKGROUND + = new ColorType("TextBackground"); + + /** + * A constant used to identify the focus color of a component. + */ + public static final ColorType FOCUS = new ColorType("Focus"); + + /** + * The maximum number of color types. + */ + public static final int MAX_COUNT = 5; + + /** + * A counter used to assign an ID to the created color types. + */ + private static int count = 0; + + /** + * The ID of the color type. + */ + private int id; + + /** + * The description of the color type. + */ + private String description; + + /** + * Creates a new Color color type with the specified + * description. + * + * @param desc the textual description of the color type + */ + protected ColorType(String desc) + { + description = desc; + id = count; + count++; + } + + /** + * Returns the unique ID of the color type. + * + * @return the unique ID of the color type + */ + public final int getID() + { + return id; + } + + /** + * Returns the textual description of the color type. + * + * @return the textual description of the color type + */ + public String toString() + { + return description; + } +} diff --git a/libjava/classpath/javax/swing/plaf/synth/Region.java b/libjava/classpath/javax/swing/plaf/synth/Region.java new file mode 100644 index 0000000..7ede65f --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/synth/Region.java @@ -0,0 +1,474 @@ +/* Region.java -- Describes a region within a component + 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 javax.swing.plaf.synth; + +/** + * Describes a region of a component or the complete component. + * + * @author Roman Kennke (kennke@aicas.com) + * + * @since 1.5 + */ +public class Region +{ + + // FIXME: What should ui be for the non-component regions that have + // subregion==false? + + /** + * Specifies an arrow button region. + */ + public static final Region ARROW_BUTTON = + new Region("ArrowButton", null, false); + + /** + * Specifies the region of a standard button. + */ + public static final Region BUTTON = + new Region("Button", "ButtonUI", false); + + /** + * Specifies the region of a check box. + */ + public static final Region CHECK_BOX = + new Region("CheckBox", "CheckBoxUI", false); + + /** + * Specifies the region of a check box menu item. + */ + public static final Region CHECK_BOX_MENU_ITEM = + new Region("CheckBoxMenuItem", "CheckBoxMenuItemUI", false); + + /** + * Specifies the region of a colorchooser. + */ + public static final Region COLOR_CHOOSER = + new Region("ColorChooser", "ColorChooserUI", false); + + /** + * Specifies the region of a combo box. + */ + public static final Region COMBO_BOX = + new Region("ComboBox", "ComboBoxUI", false); + + /** + * Specifies the region of a desktop pane. + */ + public static final Region DESKTOP_PANE = + new Region("DesktopPane", "DesktopPaneUI", false); + + /** + * Specifies the region of a desktop icon. + */ + public static final Region DESKTOP_ICON = + new Region("DesktopIcon", "DesktopIconUI", false); + + /** + * Specifies the region of an editor pane. + */ + public static final Region EDITOR_PANE = + new Region("EditorPane", "EditorPaneUI", false); + + /** + * Specifies the region of a file chooser. + */ + public static final Region FILECHOOSER = + new Region("FileChooser", "FileChooserUI", false); + + /** + * Specifies the region of a formatted text field. + */ + public static final Region FormattedTextField = + new Region("FormattedTextField", "FormattedTextFieldUI", false); + + /** + * Specifies the region of an internal frame. + */ + public static final Region INTERNAL_FRAME = + new Region("InternalFrame", "InternalFrameUI", false); + + /** + * Specifies the region of the title pane of an internal frame. + */ + public static final Region INTERNAL_FRAME_TITLE_PANE = + new Region("InternalFrameTitlePane", "InternalFrameTitlePaneUI", false); + + /** + * Specifies the region of a label. + */ + public static final Region LABEL = + new Region("Label", "LabelUI", false); + + /** + * Specifies the region of a list. + */ + public static final Region LIST = + new Region("List", "ListUI", false); + + /** + * Specifies the region of a menu. + */ + public static final Region MENU = + new Region("Menu", "MenuUI", false); + + /** + * Specifies the region of a menu bar. + */ + public static final Region MENU_BAR = + new Region("MenuBar", "MenuBarUI", false); + + /** + * Specifies the region of a menu item. + */ + public static final Region MENU_ITEM = + new Region("MenuItem", "MenuItemUI", false); + + /** + * Specifies the region of a menu item accelerator. This is a subregion + * of menu item. + */ + public static final Region MENU_ITEM_ACCELERATOR = + new Region("MenuItemAccelerator", null, true); + + /** + * Specifies the region of an option pane. + */ + public static final Region OPTION_PANE = + new Region("OptionPane", "OptionPaneUI", false); + + /** + * Specifies the region of a panel. + */ + public static final Region PANEL = + new Region("Panel", "PanelUI", false); + + /** + * Specifies the region of a password field. + */ + public static final Region PASSWORD_FIELD = + new Region("PasswordField", "PasswordFieldUI", false); + + /** + * Specifies the region of a popup menu. + */ + public static final Region POPUP_MENU = + new Region("PopupMenu", "PopupMenuUI", false); + + /** + * Specifies the region of a popup menu separator. + */ + public static final Region POPUP_MENU_SEPARATOR = + new Region("PopupMenuSeparator", null, false); + + /** + * Specifies the region of a progress bar. + */ + public static final Region PROGRESS_BAR = + new Region("ProgressBar", "ProgressBarUI", false); + + /** + * Specifies the region of a radio button. + */ + public static final Region RADIO_BUTTON = + new Region("RadioButton", "RadioButtonUI", false); + + /** + * Specifies the region of a radio button menu item. + */ + public static final Region RADIO_BUTTON_MENU_ITEM = + new Region("RadioButtonMenuItem", "RadioButtonMenuItemUI", false); + + /** + * Specifies the region of a root pane. + */ + public static final Region ROOT_PANE = + new Region("RootPane", "RootPaneUI", false); + + /** + * Specifies the region of a scroll bar. + */ + public static final Region SCROLL_BAR = + new Region("ScrollBar", "ScrollBarUI", false); + + /** + * Specifies the region of a scroll bar track. This is a subregion of + * scroll bars. + */ + public static final Region SCROLL_BAR_TRACK = + new Region("ScrollBarTrack", null, true); + + /** + * Specifies the region of a scroll bar thumb. This is a subregion of + * scroll bars. + */ + public static final Region SCROLL_BAR_THUMB = + new Region("ScrollBarThumb", null, true); + + /** + * Specifies the region of a scroll pane. + */ + public static final Region SCROLL_PANE = + new Region("ScrollPane", "ScrollPaneUI", false); + + /** + * Specifies the region of a separator. + */ + public static final Region SEPARATOR = + new Region("Separator", "SeparatorUI", false); + + /** + * Specifies the region of a slider. + */ + public static final Region SLIDER = + new Region("Slider", "SliderUI", false); + + /** + * Specifies the region of a slider track. This is a subregion of a slider. + */ + public static final Region SLIDER_TRACK = + new Region("SliderTrack", null, true); + + /** + * Specifies the region of a slider thumb. This is a subregion of a slider. + */ + public static final Region SLIDER_THUMB = + new Region("SliderThumb", null, true); + + /** + * Specifies the region of a spinner. + */ + public static final Region SPINNER = + new Region("Spinner", "SpinnerUI", false); + + /** + * Specifies the region of a split pane. + */ + public static final Region SPLIT_PANE = + new Region("SplitPane", "SplitPaneUI", false); + + /** + * Specifies the region of a split pane divider. This is a subregion of + * a split pane. + */ + public static final Region SPLIT_PANE_DIVIDER = + new Region("SplitPaneDivider", null, true); + + /** + * Specifies the region of a tabbed pane. + */ + public static final Region TABBED_PANE = + new Region("TabbedPane", "TabbedPaneUI", false); + + /** + * This specifies the region of a tab of a tabbed pane. This is a subregion + * of a tabbed pane. + */ + public static final Region TABBED_PANE_TAB = + new Region("TabbedPaneTab", null, true); + + /** + * This specifies the region underneath the tabs of a tabbed pane. This is a + * subregion of a tabbed pane. + */ + public static final Region TABBED_PANE_TAB_AREA = + new Region("TabbedPaneTabArea", null, true); + + /** + * This specifies the region for the content of a tabbed pane. This is a + * subregion of a tabbed pane. + */ + public static final Region TABBED_PANE_CONTENT = + new Region("TabbedPaneContent", null, true); + + /** + * Specifies the region of a table. + */ + public static final Region TABLE = + new Region("Table", "TableUI", false); + + /** + * Specifies the region of a table header. + */ + public static final Region TABLE_HEADER = + new Region("TableHeader", "TableHeaderUI", false); + + /** + * Specifies the region of a text area. + */ + public static final Region TEXT_AREA = + new Region("TextArea", "TextAreaUI", false); + + /** + * Specifies the region of a text field. + */ + public static final Region TEXT_FIELD = + new Region("TextField", "TextFieldUI", false); + + /** + * Specifies the region of a text pane. + */ + public static final Region TEXT_PANE = + new Region("TextPane", "TextPaneUI", false); + + /** + * Specifies the region of a toggle button. + */ + public static final Region TOGGLE_BUTTON = + new Region("ToggleButton", "ToggleButtonUI", false); + + /** + * Specifies the region of a tool bar. + */ + public static final Region TOOL_BAR = + new Region("ToolBar", "ToolBarUI", false); + + /** + * Specifies the content region of a tool bar. This is a subregion of a tool + * bar. + */ + public static final Region TOOL_BAR_CONTENT = + new Region("ToolBarContent", null, true); + + /** + * Specifies the drag window region of a tool bar. This is a subregion of a + * tool bar. + */ + public static final Region TOOL_BAR_DRAG_WINDOW = + new Region("ToolBarDragWindow", null, false); + + /** + * Specifies the region of a tool tip. + */ + public static final Region TOOL_TIP = + new Region("ToolTip", "ToolTipUI", false); + + /** + * Specifies the region of a separator of a tool bar. This is a subregion of + * a tool bar. + */ + public static final Region TOOL_BAR_SEPARATOR = + new Region("ToolBarSeparator", null, false); + + /** + * Specifies the region of a tree. + */ + public static final Region TREE = + new Region("Tree", "TreeUI", false); + + /** + * Specifies the region of a tree cell. This is a subregion of a tree. + */ + public static final Region TREE_CELL = + new Region("TreeCell", null, true); + + /** + * Specifies the region of a viewport. + */ + public static final Region VIEWPORT = + new Region("Viewport", "ViewportUI", false); + + + /** + * The UI class id for the region. This is package private because this will + * be used by other classes in that package. + */ + String ui; + + /** + * The name of the region. + */ + private String name; + + /** + * If this region is a subregion or not. + */ + private boolean subregion; + + /** + * Creates a new Region with the specified name and ui ID. + * The ui must be the same what + * {@link javax.swing.JComponent#getUIClassID()} returns for toplevel regions. For + * subregions this should be null. + * + * @param name the name of the region + * @param ui the UI class ID of the region or null for + * subregions + * @param subregion true if this region is a subregion, + * false otherwise + */ + protected Region(String name, String ui, boolean subregion) + { + this.name = name; + this.ui = ui; + this.subregion = subregion; + } + + /** + * Returns true if this region describes a subregion of a + * component, false if it describes a component region itself. + * + * @return true if this region describes a subregion of a + * component, false if it describes a component region + * itself + */ + public boolean isSubregion() + { + return subregion; + } + + /** + * Returns the name of the region. + * + * @return the name of the region + */ + public String getName() + { + return name; + } + + /** + * Returns the name of the region. + * + * @return the name of the region + */ + public String toString() + { + return name; + } +} diff --git a/libjava/classpath/javax/swing/plaf/synth/SynthConstants.java b/libjava/classpath/javax/swing/plaf/synth/SynthConstants.java new file mode 100644 index 0000000..306024c --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/synth/SynthConstants.java @@ -0,0 +1,85 @@ +/* SynthConstants.java -- A couple of constants used by Synth + 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 javax.swing.plaf.synth; + +/** + * A couple of constants used by the Synth Look and Feel. + * + * @author Roman Kennke (kennke@aicas.com) + * + * @since 1.5 + */ +public interface SynthConstants +{ + /** + * A primary state indicating that a component is enabled. + */ + static final int ENABLED = 1; + + /** + * A primary state indicating that a component is disabled. + */ + static final int DISABLED = 8; + + /** + * A primary state indicating that the mouse is over a region. + */ + static final int MOUSE_OVER = 2; + + /** + * A primary state indicating that the component is in a pressed state (which + * does not necessarily mean that the mouse is pressed over the component). + */ + static final int PRESSED = 4; + + /** + * Indicates that a region has focus. + */ + static final int FOCUSED = 256; + + /** + * Indicates that a region is selected. + */ + static final int SELECTED = 512; + + /** + * Indicates that a region is in its default state. + */ + static final int DEFAULT = 1024; +} diff --git a/libjava/classpath/javax/swing/plaf/synth/SynthContext.java b/libjava/classpath/javax/swing/plaf/synth/SynthContext.java new file mode 100644 index 0000000..83536da --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/synth/SynthContext.java @@ -0,0 +1,134 @@ +/* SynthContext.java -- Contextual information about a region + 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 javax.swing.plaf.synth; + +import javax.swing.JComponent; + +/** + * Contains some contextual information about a region. The information passed + * in objects of this class can only be considered valid during the method call + * that it was passed to. + * + * @author Roman Kennke (kennke@aicas.com) + * + * @since 1.5 + */ +public class SynthContext +{ + + /** + * The component. + */ + private JComponent component; + + /** + * The region of the component. + */ + private Region region; + + /** + * The style of the component. + */ + private SynthStyle style; + + /** + * The state of the component. + */ + private int state; + + /** + * Creates a new SynthContext object. + * + * @param component the component for which this context is used + * @param region the region of the component + * @param style the style associated with the component + * @param state a or'ed bitmask of the constants from {@link SynthConstants} + */ + public SynthContext(JComponent component, Region region, SynthStyle style, + int state) + { + this.component = component; + this.region = region; + this.style = style; + this.state = state; + } + + /** + * Returns the component that contains the region. + * + * @return the component that contains the region + */ + public JComponent getComponent() + { + return component; + } + + /** + * Returns the region that identifies this state. + * + * @return the region that identifies this state + */ + public Region getRegion() + { + return region; + } + + /** + * Returns the style of the region. + * + * @return the style of the region + */ + public SynthStyle getStyle() + { + return style; + } + + /** + * Returns the state of the component. This is a or'ed bitmask of the + * constants defined in {@link SynthConstants}. + * + * @return the state of the component + * + * @see SynthConstants + */ + public int getComponentState() + { + return state; + } +} diff --git a/libjava/classpath/javax/swing/plaf/synth/SynthGraphicsUtils.java b/libjava/classpath/javax/swing/plaf/synth/SynthGraphicsUtils.java new file mode 100644 index 0000000..a68b6f6 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/synth/SynthGraphicsUtils.java @@ -0,0 +1,283 @@ +/* SynthGraphicsUtils.java -- Wrapper for graphics primitives used in Synth + 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 javax.swing.plaf.synth; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Rectangle; + +import javax.swing.Icon; +import javax.swing.SwingUtilities; + +/** + * Wrapper for graphics primitives used in Synth. + * + * @author Roman Kennke (kennke@aicas.com) + * + * @since 1.5 + */ +public class SynthGraphicsUtils + +{ + /** + * Creates a new SynthGraphicsUtils object. + */ + public SynthGraphicsUtils() + { + // Nothing to do here. + } + + /** + * Draws a line from (x1,y1) to (x2,y2). + * + * @param ctx the synth context, identifies the region + * @param paintKey identifies the portion of the component to be painted, may + * be null + * @param g the graphics context to use for painting + * @param x1 the x coordinate of the start point + * @param y1 the y coordinate of the start point + * @param x2 the x coordinate of the end point + * @param y2 the y coordinate of the end point + */ + public void drawLine(SynthContext ctx, Object paintKey, Graphics g, int x1, + int y1, int x2, int y2) + { + // TODO: Correct? + g.drawLine(x1, y1, x2, y2); + } + + /** + * Lays out a label and (if non-null) an icon. The calculated coordinates are + * then stored in viewR, iconR and + * textR. + * + * The alignment and position parameters may be one of the alignment or + * position constants defined in {@link javax.swing.SwingConstants}. + * + * @param ctx the synth context, identifies the current region + * @param fm the font metrics to use to fetch the text measures + * @param text the text to lay out, may be null + * @param icon the icon to lay out, may be null + * @param hAlign the horizontal alignment of the label + * @param vAlign the vertical alignment of the label + * @param hTextPos the horizontal text position + * @param vTextPos the vertical text position + * @param viewR the view rectangle (return parameter) + * @param iconR the icon rectangle (return parameter) + * @param textR the text rectangle (return parameter) + * @param iconTextGap the gap between text and label + * + * @return the label text, may be shortened + */ + public String layoutText(SynthContext ctx, FontMetrics fm, String text, + Icon icon, int hAlign, int vAlign, int hTextPos, + int vTextPos, Rectangle viewR, Rectangle iconR, + Rectangle textR, int iconTextGap) + { + return SwingUtilities.layoutCompoundLabel(fm, text, icon, vAlign, hAlign, + vTextPos, hTextPos, viewR, iconR, + textR, iconTextGap); + } + + /** + * Returns the width of the string text for the specified font + * and font metrics. + * + * @param ctx identifies the current region + * @param font the font + * @param fm the font metrics to use + * @param text the text to be measured + * + * @return the width of the string text for the specified font + * and font metrics + */ + public int computeStringWidth(SynthContext ctx, Font font, FontMetrics fm, + String text) + { + return fm.stringWidth(text); + } + + /** + * Calculates the minimums size that is needed to render the label with + * text and icon correctly. + * + * @param ctx identifies the current region + * @param font the font to use + * @param text the label text + * @param icon the label icon + * @param hAlign the horizontal alignment + * @param vAlign the vertical alignment + * @param hTextPosition the horizontal text position + * @param vTextPosition the vertical text position + * @param iconTextGap the gap between icon and text + * @param mnemonicIndex index to the mnemonic character within + * text + * + * @return the minimums size that is needed to render the label with + * text and icon correctly + */ + public Dimension getMinimumSize(SynthContext ctx, Font font, String text, + Icon icon, int hAlign, int vAlign, + int hTextPosition,int vTextPosition, + int iconTextGap,int mnemonicIndex) + { + // FIXME: Implement this correctly. + return new Dimension(0, 0); + } + + /** + * Calculates the preferred size that is needed to render the label with + * text and icon correctly. + * + * @param ctx identifies the current region + * @param font the font to use + * @param text the label text + * @param icon the label icon + * @param hAlign the horizontal alignment + * @param vAlign the vertical alignment + * @param hTextPosition the horizontal text position + * @param vTextPosition the vertical text position + * @param iconTextGap the gap between icon and text + * @param mnemonicIndex index to the mnemonic character within + * text + * + * @return the preferred size that is needed to render the label with + * text and icon correctly + */ + public Dimension getPreferredSize(SynthContext ctx, Font font, String text, + Icon icon, int hAlign, int vAlign, + int hTextPosition,int vTextPosition, + int iconTextGap,int mnemonicIndex) + { + // FIXME: Implement this correctly. + return new Dimension(0, 0); + } + + /** + * Calculates the maximum size that is needed to render the label with + * text and icon correctly. + * + * @param ctx identifies the current region + * @param font the font to use + * @param text the label text + * @param icon the label icon + * @param hAlign the horizontal alignment + * @param vAlign the vertical alignment + * @param hTextPosition the horizontal text position + * @param vTextPosition the vertical text position + * @param iconTextGap the gap between icon and text + * @param mnemonicIndex index to the mnemonic character within + * text + * + * @return the maximum size that is needed to render the label with + * text and icon correctly + */ + public Dimension getMaximumSize(SynthContext ctx, Font font, String text, + Icon icon, int hAlign, int vAlign, + int hTextPosition,int vTextPosition, + int iconTextGap,int mnemonicIndex) + { + // FIXME: Implement this correctly. + return new Dimension(0, 0); + } + + /** + * Returns the maximum character height of the font from the component of the + * passed in context. + * + * @param context identifies the current component and region + * + * @return the maximum character height of the font from the component of the + * passed in context + */ + public int getMaximumCharHeight(SynthContext context) + { + Component comp = context.getComponent(); + Font font = comp.getFont(); + return comp.getFontMetrics(font).getHeight(); + } + + /** + * Renders the specified text within the bounds. + * + * @param ctx identifies the component and region + * @param g the graphics context for drawing the tetx + * @param text the text to be rendered + * @param bounds the bounds within which the text should be rendered + * @param mnemonicIndex the index of the mnemonic character within + * text + */ + public void paintText(SynthContext ctx, Graphics g, String text, + Rectangle bounds, int mnemonicIndex) + { + // FIXME: This is very primitive and should be improved to paint the + // mnemonic char. + g.drawString(text, bounds.x, bounds.y); + } + + /** + * Renders the specified text at the specified location. + * + * @param ctx identifies the component and region + * @param g the graphics context for drawing the tetx + * @param text the text to be rendered + * @param x the X location where the text should be rendered + * @param y the Y location where the text should be rendered + * @param mnemonicIndex the index of the mnemonic character within + * text + */ + public void paintText(SynthContext ctx, Graphics g, String text, + int x, int y, int mnemonicIndex) + { + // FIXME: This is very primitive and should be improved to paint the + // mnemonic char. + g.drawString(text, x, y); + } + + public void paintText(SynthContext ctx, Graphics g, String text, Icon icon, + int hAlign, int vAlign, int hTextPosition, + int vTextPosition, int iconTextGap, int mnemonicIndex, + int textOffset) + { + // FIXME: Implement this correctly. + } +} diff --git a/libjava/classpath/javax/swing/plaf/synth/SynthLookAndFeel.java b/libjava/classpath/javax/swing/plaf/synth/SynthLookAndFeel.java new file mode 100644 index 0000000..8d0596d --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/synth/SynthLookAndFeel.java @@ -0,0 +1,272 @@ +/* SynthLookAndFeel.java -- A skinnable Swing look and feel + 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 javax.swing.plaf.synth; + +import java.awt.Component; +import java.io.InputStream; +import java.text.ParseException; + +import javax.swing.JComponent; +import javax.swing.UIDefaults; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicLookAndFeel; + + +/** + * A look and feel that can be customized either by providing a file to + * {@link #load} or by setting a {@link SynthStyleFactory} using + * {@link #setStyleFactory}. + * + * @author Roman Kennke (kennke@aicas.com) + * + * @since 1.5 + */ +public class SynthLookAndFeel + extends BasicLookAndFeel +{ + + /** + * The style factory that will be used by the UI classes to load their + * style sets from. + */ + private static SynthStyleFactory styleFactory; + + /** + * Creates a new instance of SynthLookAndFeel. In order to use + * the Synth look and feel you either need to call {@link #load} to load a + * set of styles from an XML file, or you need to call + * {@link #setStyleFactory} to provide your own style factory. + */ + public SynthLookAndFeel() + { + // FIXME: What to do here, if anything? + } + + /** + * Sets the style factory that the UI classes of Synth will use to load their + * sets of styles. + * + * @param sf the style factory to set + */ + public static void setStyleFactory(SynthStyleFactory sf) + { + styleFactory = sf; + } + + /** + * Returns the current style factory that the UI classes of Synth will use to + * load their sets of styles. + * + * @return the current style factory + */ + public static SynthStyleFactory getStyleFactory() + { + return styleFactory; + } + + /** + * Returns the style for the specified component and region. + * + * @param c the component for which to return the style + * @param r the region of the component for which to return the style + * + * @return the style for the specified component and region + */ + public static SynthStyle getStyle(JComponent c, Region r) + { + return getStyleFactory().getStyle(c, r); + } + + /** + * Updates all style information of the component and it's children. + * + * @param c the componenent for which to update the style + */ + public static void updateStyles(Component c) + { + // FIXME: Implement this properly. + } + + /** + * Returns the region for a given Swing component. + * + * @param c the Swing component for which to fetch the region + * + * @return the region for a given Swing component + */ + public static Region getRegion(JComponent c) + { + // FIXME: This can be implemented as soon as we have the component UI + // classes in place, since this region will be matched via the UI classes. + return null; + } + + /** + * Creates the Synth look and feel component UI instance for the given + * component. + * + * @param c the component for which to create a UI instance + * + * @return the Synth look and feel component UI instance for the given + * component + */ + public static ComponentUI createUI(JComponent c) + { + // FIXME: This can be implemented as soon as we have the component UI + // classes in place. + return null; + } + + /** + * Initializes this look and feel. + */ + public void initialize() + { + super.initialize(); + // TODO: Implement at least the following here: + // if (styleFactory != null) + // styleFactory = new DefaultStyleFactory(); + } + + /** + * Uninitializes the look and feel. + */ + public void uninitialize() + { + super.uninitialize(); + // TODO: What to do here? + } + + /** + * Returns the UI defaults of this look and feel. + * + * @return the UI defaults of this look and feel + */ + public UIDefaults getDefaults() + { + // FIXME: This is certainly wrong. The defaults should be fetched/merged + // from the file from which the l&f is loaded. + return super.getDefaults(); + } + + /** + * FIXME: DOCUMENT ME! + * + * @return FIXME + */ + public boolean shouldUpdateStyleOnAncestorChanged() + { + return false; + } + + /** + * Loads a set of {@link SynthStyle}s that are used for the look and feel of + * the components. The resourceBase parameter is used to resolve + * references against, like icons and other files. + * + * @param in the input stream from where to load the styles + * @param resourceBase the base against which references are resolved. + * + * @throws ParseException if the input stream cannot be parsed + * @throws IllegalArgumentException if one of the parameters is + * null + */ + // FIXME: The signature in the JDK has a Class here. Should be fixed as + // soon as we switch to the generics branch. + public void load(InputStream in, Class resourceBase) + throws ParseException, IllegalArgumentException + { + // FIXME: Implement this correctly. + } + + /** + * Returns a textual description of the Synth look and feel. This returns + * "Synt look and feel". + * + * @return a textual description of the Synth look and feel + */ + public String getDescription() + { + return "Synth look and feel"; + } + + /** + * Returns the ID of the Synth look and feel. This returns "Synth". + * + * @return the ID of the Synth look and feel + */ + public String getID() + { + return "Synth"; + } + + /** + * Returns the name of the Synth look and feel. This returns + * "Synt look and feel". + * + * @return the name of the Synth look and feel + */ + public String getName() + { + return "Synth look and feel"; + } + + /** + * Returns false since the Synth look and feel is not a native + * look and feel. + * + * @return false + */ + public boolean isNativeLookAndFeel() + { + return false; + } + + /** + * Returns true since the Synth look and feel is always a + * supported look and feel. + * + * @return true + */ + public boolean isSupportedLookAndFeel() + { + return true; + } + +} diff --git a/libjava/classpath/javax/swing/plaf/synth/SynthPainter.java b/libjava/classpath/javax/swing/plaf/synth/SynthPainter.java new file mode 100644 index 0000000..0d63c6d --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/synth/SynthPainter.java @@ -0,0 +1,80 @@ +/* SynthPainter.java -- An abstract painter for synth components + 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 javax.swing.plaf.synth; + +import java.awt.Graphics; + +/** + * The abstract definition of a delegate that takes the responsibility of + * painting for the components. + * + * This class is defined to be abstract and all methods are no-ops. + * + * @author Roman Kennke (kennke@aicas.com) + * + * @since 1.5 + */ +public abstract class SynthPainter +{ + + /** + * Creates a new SynthPainter object. + */ + public SynthPainter() + { + // Nothing to do here. + } + + /** + * Paints the background of an arrow button. + * + * @param ctx the synth context identifying the component and region for + * painting + * @param g the graphics context to use for painting + * @param x the X coordinate of the area to paint + * @param y the Y coordinate of the area to paint + * @param w the width of the area to paint + * @param h the height of the area to paint + */ + public void paintArrowButtonBackground(SynthContext ctx, Graphics g, int x, + int y, int w, int h) + { + // Nothing to do here. + } +} diff --git a/libjava/classpath/javax/swing/plaf/synth/SynthStyle.java b/libjava/classpath/javax/swing/plaf/synth/SynthStyle.java new file mode 100644 index 0000000..e0a8dbc --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/synth/SynthStyle.java @@ -0,0 +1,144 @@ +/* SynthStyle.java -- A set of style properties + 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 javax.swing.plaf.synth; + +import java.awt.Color; +import java.awt.Font; +import java.awt.Insets; + +import javax.swing.Icon; + +/** + * A set of style properties that can be installed on a component. + * + * @author Roman Kennke (kennke@aicas.com) + * + * @since 1.5 + */ +public abstract class SynthStyle +{ + + /** + * Creates a new SynthStyle object. + */ + public SynthStyle() + { + // FIXME: Implement this correctly. + } + + public SynthGraphicsUtils getGraphicsUtils(SynthContext ctx) + { + // FIXME: Implement this correctly. + return null; + } + + public Color getColor(SynthContext ctx, ColorType type) + { + // FIXME: Implement this correctly. + return null; + } + + public abstract Color getColorForState(SynthContext ctx, ColorType type); + + public Font getFont(SynthContext ctx) + { + // FIXME: Implement this correctly. + return null; + } + + public abstract Font getFontForState(SynthContext ctx); + + public Insets getInsets(SynthContext ctx) + { + // FIXME: Implement this correctly. + return null; + } + + public SynthPainter getPainted(SynthContext ctx) + { + // FIXME: Implement this correctly. + return null; + } + + public boolean isOpaque(SynthContext ctx) + { + // FIXME: Implement this correctly. + return true; + } + + public Object get(SynthContext ctx, Object key) + { + // FIXME: Implement this correctly. + return null; + } + + public void installDefaults(SynthContext ctx) + { + // FIXME: Implement this correctly. + } + + public void uninstallDefaults(SynthContext ctx) + { + // FIXME: Implement this correctly. + } + + public int getInt(SynthContext ctx, Object key, int defaultValue) + { + // FIXME: Implement this correctly. + return -1; + } + + public boolean getBoolean(SynthContext ctx, Object key, boolean defaultValue) + { + // FIXME: Implement this correctly. + return false; + } + + public Icon getIcon(SynthContext ctx, Object key) + { + // FIXME: Implement this correctly. + return null; + } + + public String getString(SynthContext ctx, Object key, String defaultValue) + { + // FIXME: Implement this correctly. + return null; + } +} diff --git a/libjava/classpath/javax/swing/plaf/synth/SynthStyleFactory.java b/libjava/classpath/javax/swing/plaf/synth/SynthStyleFactory.java new file mode 100644 index 0000000..569753d --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/synth/SynthStyleFactory.java @@ -0,0 +1,64 @@ +/* SynthStyleFactory.java -- A factory for SynthStyles + 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 javax.swing.plaf.synth; + +import javax.swing.JComponent; + +public abstract class SynthStyleFactory +{ + + /** + * Creates a new SynthStyleFactory. + */ + public SynthStyleFactory() + { + // Nothing to do here. + } + + /** + * Returns a {@link SynthStyle} for the specified region of the specified + * component. + * + * @param c the component for which to create a style + * @param id the region of the component + * + * @return a style for the specified region of the specified component + */ + public abstract SynthStyle getStyle(JComponent c, Region id); +} diff --git a/libjava/classpath/javax/swing/plaf/synth/package.html b/libjava/classpath/javax/swing/plaf/synth/package.html new file mode 100644 index 0000000..b977e46 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/synth/package.html @@ -0,0 +1,47 @@ + + + + +GNU Classpath - javax.swing.plaf.synth + + +

Provides a look and feel that can be customized by and XML file or by + providing a custom {@link SynthStyleFactory}. +

+ + diff --git a/libjava/classpath/javax/swing/table/DefaultTableCellRenderer.java b/libjava/classpath/javax/swing/table/DefaultTableCellRenderer.java index 233528c..0d9b625 100644 --- a/libjava/classpath/javax/swing/table/DefaultTableCellRenderer.java +++ b/libjava/classpath/javax/swing/table/DefaultTableCellRenderer.java @@ -127,7 +127,8 @@ public class DefaultTableCellRenderer extends JLabel * Get the string value of the object and pass it to setText(). * * @param table the JTable - * @param value the value of the object + * @param value the value of the object. For the text content, + * null is rendered as an empty cell. * @param isSelected is the cell selected? * @param hasFocus has the cell the focus? * @param row the row to render @@ -140,13 +141,7 @@ public class DefaultTableCellRenderer extends JLabel boolean hasFocus, int row, int column) { - if (value != null) - { - if (value instanceof JTextField) - return new JTextField(((JTextField)value).getText()); - super.setText(value.toString()); - } - + setValue(value); setOpaque(true); if (table == null) @@ -274,6 +269,10 @@ public class DefaultTableCellRenderer extends JLabel */ protected void setValue(Object value) { - super.setText((value!=null) ? value.toString() : ""); + if (value != null) + setText(value.toString()); + else + // null is rendered as an empty cell. + setText(""); } } diff --git a/libjava/classpath/javax/swing/table/DefaultTableModel.java b/libjava/classpath/javax/swing/table/DefaultTableModel.java index 6844f2a..c281caa 100644 --- a/libjava/classpath/javax/swing/table/DefaultTableModel.java +++ b/libjava/classpath/javax/swing/table/DefaultTableModel.java @@ -486,7 +486,10 @@ public class DefaultTableModel extends AbstractTableModel } /** - * Returns the name of the specified column. + * Get the name of the column. If the column has the column identifier set, + * the return value is the result of the .toString() method call on that + * identifier. If the identifier is not explicitly set, the returned value + * is calculated by {@link AbstractTableModel#getColumnName(int)}. * * @param column the column index. * diff --git a/libjava/classpath/javax/swing/table/JTableHeader.java b/libjava/classpath/javax/swing/table/JTableHeader.java index 163509a..4e8dcd7 100644 --- a/libjava/classpath/javax/swing/table/JTableHeader.java +++ b/libjava/classpath/javax/swing/table/JTableHeader.java @@ -67,6 +67,11 @@ import javax.swing.event.TableColumnModelEvent; import javax.swing.event.TableColumnModelListener; import javax.swing.plaf.TableHeaderUI; +/** + * Represents the table header. The header displays the column header values, + * is always visible event if the rest of the table scrolls up and down and + * supports column reordering and resizing with mouse. + */ public class JTableHeader extends JComponent implements TableColumnModelListener, Accessible { @@ -306,7 +311,10 @@ public class JTableHeader extends JComponent } }; } - + + /** + * Use serialVersionUid for interoperability. + */ private static final long serialVersionUID = 5144633983372967710L; /** @@ -409,9 +417,10 @@ public class JTableHeader extends JComponent } /** - * Get the value of the {@link #draggedColumn} property. + * Get the column that is currently being dragged. This is used when + * handling the column reordering with mouse. * - * @return The current value of the property + * @return the column being dragged, null if none. */ public TableColumn getDraggedColumn() { @@ -429,29 +438,34 @@ public class JTableHeader extends JComponent } /** - * Get the value of the {@link #reorderingAllowed} property. + * Check if it is possible to reorder the table columns by dragging column + * header with mouse. The table reordering is enabled by default, but can be + * disabled with {@link #setReorderingAllowed(boolean)}. * - * @return The current value of the property - */ + * @return true if reordering is allowed, false otherwise. + */ public boolean getReorderingAllowed() { return reorderingAllowed; } /** - * Get the value of the {@link #resizingAllowed} property. + * Check if it is possible to resize the table columns by dragging the column + * boundary in the table header with mouse. The resizing is enabled + * by default, but can be disabled with {@link #setResizingAllowed(boolean)}. * - * @return The current value of the property - */ + * @return true if resizing is allowed, false otherwise. + */ public boolean getResizingAllowed() { return resizingAllowed; } /** - * Get the value of the {@link #resizingColumn} property. + * Get the column that is currently being resized. This is used when + * handling the column resizing with mouse. * - * @return The current value of the property + * @return the column being currently resized, null if none. */ public TableColumn getResizingColumn() { @@ -459,9 +473,9 @@ public class JTableHeader extends JComponent } /** - * Get the value of the {@link #table} property. + * Get the table, having this header. * - * @return The current value of the property + * @return the table, having this header. */ public JTable getTable() { @@ -501,13 +515,15 @@ public class JTableHeader extends JComponent } /** - * Set the value of the {@link #draggedColumn} property. + * Set the column that is currently being dragged. This is used when + * dragging the column with mouse. Setting to null will stop the + * dragging session immediately. * - * @param d The new value of the property + * @param draggingIt the column being currently dragged, null if none. */ - public void setDraggedColumn(TableColumn d) + public void setDraggedColumn(TableColumn draggingIt) { - draggedColumn = d; + draggedColumn = draggingIt; } /** @@ -531,33 +547,39 @@ public class JTableHeader extends JComponent } /** - * Set the value of the {@link #reorderingAllowed} property. + * Set the table ability to reorder columns by dragging column header + * with mouse. The table reordering is enabled by default, but can be + * disabled with this method. * - * @param r The new value of the property + * @param allowed true if reordering is allowed, false otherwise. */ - public void setReorderingAllowed(boolean r) + public void setReorderingAllowed(boolean allowed) { - reorderingAllowed = r; + reorderingAllowed = allowed; } /** - * Set the value of the {@link #resizingAllowed} property. + * Set the table ability to resize columns by dragging the column + * boundary in the table header with mouse. The resizing is enabled + * by default, but can be disabled using this method. * - * @param r The new value of the property + * @param allowed true if resizing is allowed, false otherwise. */ - public void setResizingAllowed(boolean r) + public void setResizingAllowed(boolean allowed) { - resizingAllowed = r; + resizingAllowed = allowed; } /** - * Set the value of the {@link #resizingColumn} property. + * The the column that is currently being resized. This property is used + * when handling table resizing with mouse. Setting to null would stop + * the resizing session immediately. * - * @param r The new value of the property + * @param resizingIt the column being currently resized */ - public void setResizingColumn(TableColumn r) + public void setResizingColumn(TableColumn resizingIt) { - resizingColumn = r; + resizingColumn = resizingIt; } /** @@ -609,7 +631,14 @@ public class JTableHeader extends JComponent { this.cellRenderer = cellRenderer; } - + + /** + * Get the rectangle, occupied by the header of the given column. + * + * @param column the column, for that the header area is requested. + * + * @return the column header area. + */ public Rectangle getHeaderRect(int column) { Rectangle r = getTable().getCellRect(-1, column, false); diff --git a/libjava/classpath/javax/swing/text/AbstractDocument.java b/libjava/classpath/javax/swing/text/AbstractDocument.java index c735388..a3e8c46 100644 --- a/libjava/classpath/javax/swing/text/AbstractDocument.java +++ b/libjava/classpath/javax/swing/text/AbstractDocument.java @@ -538,18 +538,24 @@ public abstract class AbstractDocument implements Document, Serializable DefaultDocumentEvent event = new DefaultDocumentEvent(offset, text.length(), DocumentEvent.EventType.INSERT); - - writeLock(); - UndoableEdit undo = content.insertString(offset, text); - if (undo != null) - event.addEdit(undo); - insertUpdate(event, attributes); - writeUnlock(); + try + { + writeLock(); + UndoableEdit undo = content.insertString(offset, text); + if (undo != null) + event.addEdit(undo); + + insertUpdate(event, attributes); - fireInsertUpdate(event); - if (undo != null) - fireUndoableEditUpdate(new UndoableEditEvent(this, undo)); + fireInsertUpdate(event); + if (undo != null) + fireUndoableEditUpdate(new UndoableEditEvent(this, undo)); + } + finally + { + writeUnlock(); + } } /** @@ -640,6 +646,12 @@ public abstract class AbstractDocument implements Document, Serializable // more times than you've previously called lock, but it doesn't make // sure that the threads calling unlock were the same ones that called lock + // If the current thread holds the write lock, and attempted to also obtain + // a readLock, then numReaders hasn't been incremented and we don't need + // to unlock it here. + if (currentWriter == Thread.currentThread()) + return; + // FIXME: the reference implementation throws a // javax.swing.text.StateInvariantError here if (numReaders == 0) @@ -675,18 +687,21 @@ public abstract class AbstractDocument implements Document, Serializable new DefaultDocumentEvent(offset, length, DocumentEvent.EventType.REMOVE); - removeUpdate(event); - - boolean shouldFire = content.getString(offset, length).length() != 0; - - writeLock(); - UndoableEdit temp = content.remove(offset, length); - writeUnlock(); - - postRemoveUpdate(event); - - if (shouldFire) - fireRemoveUpdate(event); + try + { + writeLock(); + + // The order of the operations below is critical! + removeUpdate(event); + UndoableEdit temp = content.remove(offset, length); + + postRemoveUpdate(event); + fireRemoveUpdate(event); + } + finally + { + writeUnlock(); + } } /** @@ -841,7 +856,7 @@ public abstract class AbstractDocument implements Document, Serializable */ protected void writeLock() { - if (currentWriter!= null && currentWriter.equals(Thread.currentThread())) + if (currentWriter != null && currentWriter.equals(Thread.currentThread())) return; synchronized (documentCV) { @@ -1330,11 +1345,11 @@ public abstract class AbstractDocument implements Document, Serializable public Object getAttribute(Object key) { Object result = attributes.getAttribute(key); - if (result == null && element_parent != null) + if (result == null) { - AttributeSet parentSet = element_parent.getAttributes(); - if (parentSet != null) - result = parentSet.getAttribute(key); + AttributeSet resParent = getResolveParent(); + if (resParent != null) + result = resParent.getAttribute(key); } return result; } @@ -1371,9 +1386,7 @@ public abstract class AbstractDocument implements Document, Serializable */ public AttributeSet getResolveParent() { - if (attributes.getResolveParent() != null) - return attributes.getResolveParent(); - return element_parent.getAttributes(); + return attributes.getResolveParent(); } /** @@ -1573,6 +1586,18 @@ public abstract class AbstractDocument implements Document, Serializable private Element[] children = new Element[0]; /** + * The cached startOffset value. This is used in the case when a + * BranchElement (temporarily) has no child elements. + */ + private int startOffset; + + /** + * The cached endOffset value. This is used in the case when a + * BranchElement (temporarily) has no child elements. + */ + private int endOffset; + + /** * Creates a new BranchElement with the specified * parent and attributes. * @@ -1583,6 +1608,8 @@ public abstract class AbstractDocument implements Document, Serializable public BranchElement(Element parent, AttributeSet attributes) { super(parent, attributes); + startOffset = -1; + endOffset = -1; } /** @@ -1655,7 +1682,7 @@ public abstract class AbstractDocument implements Document, Serializable // return 0 if (offset < getStartOffset()) return 0; - + // XXX: There is surely a better algorithm // as beginning from first element each time. for (int index = 0; index < children.length - 1; ++index) @@ -1695,9 +1722,15 @@ public abstract class AbstractDocument implements Document, Serializable */ public int getEndOffset() { - if (getElementCount() == 0) - throw new NullPointerException("This BranchElement has no children."); - return children[children.length - 1].getEndOffset(); + if (children.length == 0) + { + if (endOffset == -1) + throw new NullPointerException("BranchElement has no children."); + } + else + endOffset = children[children.length - 1].getEndOffset(); + + return endOffset; } /** @@ -1718,13 +1751,20 @@ public abstract class AbstractDocument implements Document, Serializable * * @return the start offset of this element inside the document model * - * @throws NullPointerException if this branch element has no children + * @throws NullPointerException if this branch element has no children and + * no startOffset value has been cached */ public int getStartOffset() { - if (getElementCount() == 0) - throw new NullPointerException("This BranchElement has no children."); - return children[0].getStartOffset(); + if (children.length == 0) + { + if (startOffset == -1) + throw new NullPointerException("BranchElement has no children."); + } + else + startOffset = children[0].getStartOffset(); + + return startOffset; } /** @@ -2022,13 +2062,29 @@ public abstract class AbstractDocument implements Document, Serializable /** The serialization UID (compatible with JDK1.5). */ private static final long serialVersionUID = -8906306331347768017L; - /** Manages the start offset of this element. */ - Position startPos; + /** + * Manages the start offset of this element. + */ + private Position startPos; + + /** + * Manages the end offset of this element. + */ + private Position endPos; - /** Manages the end offset of this element. */ - Position endPos; + /** + * This gets possible added to the startOffset when a startOffset + * outside the document range is requested. + */ + private int startDelta; /** + * This gets possible added to the endOffset when a endOffset + * outside the document range is requested. + */ + private int endDelta; + + /** * Creates a new LeafElement. * * @param parent the parent of this LeafElement @@ -2040,20 +2096,18 @@ public abstract class AbstractDocument implements Document, Serializable int end) { super(parent, attributes); - { - try + int len = content.length(); + startDelta = 0; + if (start > len) + startDelta = start - len; + endDelta = 0; + if (end > len) + endDelta = end - len; + try { - if (parent != null) - { - startPos = parent.getDocument().createPosition(start); - endPos = parent.getDocument().createPosition(end); - } - else - { - startPos = createPosition(start); - endPos = createPosition(end); + startPos = createPosition(start - startDelta); + endPos = createPosition(end - endDelta); } - } catch (BadLocationException ex) { AssertionError as; @@ -2064,7 +2118,6 @@ public abstract class AbstractDocument implements Document, Serializable as.initCause(ex); throw as; } - } } /** @@ -2136,7 +2189,7 @@ public abstract class AbstractDocument implements Document, Serializable */ public int getEndOffset() { - return endPos.getOffset(); + return endPos.getOffset() + endDelta; } /** @@ -2162,7 +2215,7 @@ public abstract class AbstractDocument implements Document, Serializable */ public int getStartOffset() { - return startPos.getOffset(); + return startPos.getOffset() + startDelta; } /** diff --git a/libjava/classpath/javax/swing/text/AsyncBoxView.java b/libjava/classpath/javax/swing/text/AsyncBoxView.java new file mode 100644 index 0000000..1988bba --- /dev/null +++ b/libjava/classpath/javax/swing/text/AsyncBoxView.java @@ -0,0 +1,1480 @@ +/* AsyncBoxView.java -- A box view that performs layout asynchronously + 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 javax.swing.text; + +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.awt.Shape; +import java.util.ArrayList; + +import javax.swing.event.DocumentEvent; +import javax.swing.text.Position.Bias; + +/** + * A {@link View} implementation that lays out its child views in a box, either + * vertically or horizontally. The difference to {@link BoxView} is that the + * layout is performed in an asynchronous manner. This helps to keep the + * eventqueue free from non-GUI related tasks. + * + * This view is currently not used in standard text components. In order to + * use it you would have to implement a special {@link EditorKit} with a + * {@link ViewFactory} that returns this view. For example: + * + *
+ * static class AsyncEditorKit extends StyledEditorKit implements ViewFactory
+ * {
+ *   public View create(Element el)
+ *   {
+ *     if (el.getName().equals(AbstractDocument.SectionElementName))
+ *       return new AsyncBoxView(el, View.Y_AXIS);
+ *     return super.getViewFactory().create(el);
+ *   }
+ *   public ViewFactory getViewFactory() {
+ *     return this;
+ *   }
+ * }
+ * 
+ * + * @author Roman Kennke (kennke@aicas.com) + * + * @since 1.3 + */ +public class AsyncBoxView + extends View +{ + + /** + * Manages the effective position of child views. That keeps the visible + * layout stable while the AsyncBoxView might be changing until the layout + * thread decides to publish the new layout. + */ + public class ChildLocator + { + + /** + * The last valid location. + */ + protected ChildState lastValidOffset; + + /** + * The last allocation. + */ + protected Rectangle lastAlloc; + + /** + * A Rectangle used for child allocation calculation to avoid creation + * of lots of garbage Rectangle objects. + */ + protected Rectangle childAlloc; + + /** + * Creates a new ChildLocator. + */ + public ChildLocator() + { + lastAlloc = new Rectangle(); + childAlloc = new Rectangle(); + } + + /** + * Receives notification that a child has changed. This is called by + * child state objects that have changed it's major span. + * + * This sets the {@link #lastValidOffset} field to cs if + * the new child state's view start offset is smaller than the start offset + * of the current child state's view or when lastValidOffset + * is null. + * + * @param cs the child state object that has changed + */ + public synchronized void childChanged(ChildState cs) + { + if (lastValidOffset == null + || cs.getChildView().getStartOffset() + < lastValidOffset.getChildView().getStartOffset()) + { + lastValidOffset = cs; + } + } + + /** + * Returns the view index of the view that occupies the specified area, or + * -1 if there is no such child view. + * + * @param x the x coordinate (relative to a) + * @param y the y coordinate (relative to a) + * @param a the current allocation of this view + * + * @return the view index of the view that occupies the specified area, or + * -1 if there is no such child view + */ + public int getViewIndexAtPoint(float x, float y, Shape a) + { + setAllocation(a); + float targetOffset = (getMajorAxis() == X_AXIS) ? x - lastAlloc.x + : y - lastAlloc.y; + int index = getViewIndexAtVisualOffset(targetOffset); + return index; + } + + /** + * Returns the current allocation for a child view. This updates the + * offsets for all children before the requested child view. + * + * @param index the index of the child view + * @param a the current allocation of this view + * + * @return the current allocation for a child view + */ + public synchronized Shape getChildAllocation(int index, Shape a) + { + if (a == null) + return null; + setAllocation(a); + ChildState cs = getChildState(index); + if (cs.getChildView().getStartOffset() + > lastValidOffset.getChildView().getStartOffset()) + { + updateChildOffsetsToIndex(index); + } + Shape ca = getChildAllocation(index); + return ca; + } + + /** + * Paints all child views. + * + * @param g the graphics context to use + */ + public synchronized void paintChildren(Graphics g) + { + Rectangle clip = g.getClipBounds(); + float targetOffset = (getMajorAxis() == X_AXIS) ? clip.x - lastAlloc.x + : clip.y - lastAlloc.y; + int index = getViewIndexAtVisualOffset(targetOffset); + int n = getViewCount(); + float offs = getChildState(index).getMajorOffset(); + for (int i = index; i < n; i++) + { + ChildState cs = getChildState(i); + cs.setMajorOffset(offs); + Shape ca = getChildAllocation(i); + if (ca.intersects(clip)) + { + synchronized (cs) + { + View v = cs.getChildView(); + v.paint(g, ca); + } + } + else + { + // done painting intersection + break; + } + offs += cs.getMajorSpan(); + } + } + + /** + * Returns the current allocation of the child view with the specified + * index. Note that this will not update any location information. + * + * @param index the index of the requested child view + * + * @return the current allocation of the child view with the specified + * index + */ + protected Shape getChildAllocation(int index) + { + ChildState cs = getChildState(index); + if (! cs.isLayoutValid()) + cs.run(); + + if (getMajorAxis() == X_AXIS) + { + childAlloc.x = lastAlloc.x + (int) cs.getMajorOffset(); + childAlloc.y = lastAlloc.y + (int) cs.getMinorOffset(); + childAlloc.width = (int) cs.getMajorSpan(); + childAlloc.height = (int) cs.getMinorSpan(); + } + else + { + childAlloc.y = lastAlloc.y + (int) cs.getMajorOffset(); + childAlloc.x = lastAlloc.x + (int) cs.getMinorOffset(); + childAlloc.height = (int) cs.getMajorSpan(); + childAlloc.width = (int) cs.getMinorSpan(); + } + return childAlloc; + } + + /** + * Sets the current allocation for this view. + * + * @param a the allocation to set + */ + protected void setAllocation(Shape a) + { + if (a instanceof Rectangle) + lastAlloc.setBounds((Rectangle) a); + else + lastAlloc.setBounds(a.getBounds()); + + setSize(lastAlloc.width, lastAlloc.height); + } + + /** + * Returns the index of the view at the specified offset along the major + * layout axis. + * + * @param targetOffset the requested offset + * + * @return the index of the view at the specified offset along the major + * layout axis + */ + protected int getViewIndexAtVisualOffset(float targetOffset) + { + int n = getViewCount(); + if (n > 0) + { + if (lastValidOffset == null) + lastValidOffset = getChildState(0); + if (targetOffset > majorSpan) + return 0; + else if (targetOffset > lastValidOffset.getMajorOffset()) + return updateChildOffsets(targetOffset); + else + { + float offs = 0f; + for (int i = 0; i < n; i++) + { + ChildState cs = getChildState(i); + float nextOffs = offs + cs.getMajorSpan(); + if (targetOffset < nextOffs) + return i; + offs = nextOffs; + } + } + } + return n - 1; + } + + /** + * Updates all the child view offsets up to the specified targetOffset. + * + * @param targetOffset the offset up to which the child view offsets are + * updated + * + * @return the index of the view at the specified offset + */ + private int updateChildOffsets(float targetOffset) + { + int n = getViewCount(); + int targetIndex = n - 1;; + int pos = lastValidOffset.getChildView().getStartOffset(); + int startIndex = getViewIndexAtPosition(pos, Position.Bias.Forward); + float start = lastValidOffset.getMajorOffset(); + float lastOffset = start; + for (int i = startIndex; i < n; i++) + { + ChildState cs = getChildState(i); + cs.setMajorOffset(lastOffset); + lastOffset += cs.getMajorSpan(); + if (targetOffset < lastOffset) + { + targetIndex = i; + lastValidOffset = cs; + break; + } + } + return targetIndex; + } + + /** + * Updates the offsets of the child views up to the specified index. + * + * @param index the index up to which the offsets are updated + */ + private void updateChildOffsetsToIndex(int index) + { + int pos = lastValidOffset.getChildView().getStartOffset(); + int startIndex = getViewIndexAtPosition(pos, Position.Bias.Forward); + float lastOffset = lastValidOffset.getMajorOffset(); + for (int i = startIndex; i <= index; i++) + { + ChildState cs = getChildState(i); + cs.setMajorOffset(lastOffset); + lastOffset += cs.getMajorSpan(); + } + } + } + + /** + * Represents the layout state of a child view. + */ + public class ChildState + implements Runnable + { + + /** + * The child view for this state record. + */ + private View childView; + + /** + * Indicates if the minor axis requirements of this child view are valid + * or not. + */ + private boolean minorValid; + + /** + * Indicates if the major axis requirements of this child view are valid + * or not. + */ + private boolean majorValid; + + /** + * Indicates if the current child size is valid. This is package private + * to avoid synthetic accessor method. + */ + boolean childSizeValid; + + /** + * The child views minimumSpan. This is package private to avoid accessor + * method. + */ + float minimum; + + /** + * The child views preferredSpan. This is package private to avoid accessor + * method. + */ + float preferred; + + /** + * The current span of the child view along the major axis. + */ + private float majorSpan; + + /** + * The current offset of the child view along the major axis. + */ + private float majorOffset; + + /** + * The current span of the child view along the minor axis. + */ + private float minorSpan; + + /** + * The current offset of the child view along the major axis. + */ + private float minorOffset; + + /** + * The child views maximumSpan. + */ + private float maximum; + + /** + * Creates a new ChildState object for the specified child + * view. + * + * @param view the child view for which to create the state record + */ + public ChildState(View view) + { + childView = view; + } + + /** + * Returns the child view for which this ChildState represents + * the layout state. + * + * @return the child view for this child state object + */ + public View getChildView() + { + return childView; + } + + /** + * Returns true if the current layout information is valid, + * false otherwise. + * + * @return true if the current layout information is valid, + * false otherwise + */ + public boolean isLayoutValid() + { + return minorValid && majorValid && childSizeValid; + } + + /** + * Performs the layout update for the child view managed by this + * ChildState. + */ + public void run() + { + Document doc = getDocument(); + if (doc instanceof AbstractDocument) + { + AbstractDocument abstractDoc = (AbstractDocument) doc; + abstractDoc.readLock(); + } + + try + { + + if (!(minorValid && majorValid && childSizeValid) + && childView.getParent() == AsyncBoxView.this) + { + synchronized(AsyncBoxView.this) + { + changing = this; + } + update(); + synchronized(AsyncBoxView.this) + { + changing = null; + } + // Changing the major axis may cause the minor axis + // requirements to have changed, so we need to do this again. + update(); + } + } + finally + { + if (doc instanceof AbstractDocument) + { + AbstractDocument abstractDoc = (AbstractDocument) doc; + abstractDoc.readUnlock(); + } + } + } + + /** + * Performs the actual update after the run methods has made its checks + * and locked the document. + */ + private void update() + { + int majorAxis = getMajorAxis(); + boolean minorUpdated = false; + synchronized (this) + { + if (! minorValid) + { + int minorAxis = getMinorAxis(); + minimum = childView.getMinimumSpan(minorAxis); + preferred = childView.getPreferredSpan(minorAxis); + maximum = childView.getMaximumSpan(minorAxis); + minorValid = true; + minorUpdated = true; + } + } + if (minorUpdated) + minorRequirementChange(this); + + boolean majorUpdated = false; + float delta = 0.0F; + synchronized (this) + { + if (! majorValid) + { + float oldSpan = majorSpan; + majorSpan = childView.getPreferredSpan(majorAxis); + delta = majorSpan - oldSpan; + majorValid = true; + majorUpdated = true; + } + } + if (majorUpdated) + { + majorRequirementChange(this, delta); + locator.childChanged(this); + } + + synchronized (this) + { + if (! childSizeValid) + { + float w; + float h; + if (majorAxis == X_AXIS) + { + w = majorSpan; + h = getMinorSpan(); + } + else + { + w = getMinorSpan(); + h = majorSpan; + } + childSizeValid = true; + childView.setSize(w, h); + } + } + } + + /** + * Returns the span of the child view along the minor layout axis. + * + * @return the span of the child view along the minor layout axis + */ + public float getMinorSpan() + { + float retVal; + if (maximum < minorSpan) + retVal = maximum; + else + retVal = Math.max(minimum, minorSpan); + return retVal; + } + + /** + * Returns the offset of the child view along the minor layout axis. + * + * @return the offset of the child view along the minor layout axis + */ + public float getMinorOffset() + { + float retVal; + if (maximum < minorSpan) + { + float align = childView.getAlignment(getMinorAxis()); + retVal = ((minorSpan - maximum) * align); + } + else + retVal = 0f; + + return retVal; + } + + /** + * Returns the span of the child view along the major layout axis. + * + * @return the span of the child view along the major layout axis + */ + + public float getMajorSpan() + { + return majorSpan; + } + + /** + * Returns the offset of the child view along the major layout axis. + * + * @return the offset of the child view along the major layout axis + */ + public float getMajorOffset() + { + return majorOffset; + } + + /** + * Sets the offset of the child view along the major layout axis. This + * should only be called by the ChildLocator of that child view. + * + * @param offset the offset to set + */ + public void setMajorOffset(float offset) + { + majorOffset = offset; + } + + /** + * Mark the preferences changed for that child. This forwards to + * {@link AsyncBoxView#preferenceChanged}. + * + * @param width true if the width preference has changed + * @param height true if the height preference has changed + */ + public void preferenceChanged(boolean width, boolean height) + { + if (getMajorAxis() == X_AXIS) + { + if (width) + majorValid = false; + if (height) + minorValid = false; + } + else + { + if (width) + minorValid = false; + if (height) + majorValid = false; + } + childSizeValid = false; + } + } + + /** + * Flushes the requirements changes upwards asynchronously. + */ + private class FlushTask implements Runnable + { + /** + * Starts the flush task. This obtains a readLock on the document + * and then flushes all the updates using + * {@link AsyncBoxView#flushRequirementChanges()} after updating the + * requirements. + */ + public void run() + { + try + { + // Acquire a lock on the document. + Document doc = getDocument(); + if (doc instanceof AbstractDocument) + { + AbstractDocument abstractDoc = (AbstractDocument) doc; + abstractDoc.readLock(); + } + + int n = getViewCount(); + if (minorChanged && (n > 0)) + { + LayoutQueue q = getLayoutQueue(); + ChildState min = getChildState(0); + ChildState pref = getChildState(0); + for (int i = 1; i < n; i++) + { + ChildState cs = getChildState(i); + if (cs.minimum > min.minimum) + min = cs; + if (cs.preferred > pref.preferred) + pref = cs; + } + synchronized (AsyncBoxView.this) + { + minReq = min; + prefReq = pref; + } + } + + flushRequirementChanges(); + } + finally + { + // Release the lock on the document. + Document doc = getDocument(); + if (doc instanceof AbstractDocument) + { + AbstractDocument abstractDoc = (AbstractDocument) doc; + abstractDoc.readUnlock(); + } + } + } + + } + + /** + * The major layout axis. + */ + private int majorAxis; + + /** + * The top inset. + */ + private float topInset; + + /** + * The bottom inset. + */ + private float bottomInset; + + /** + * The left inset. + */ + private float leftInset; + + /** + * Indicates if the major span should be treated as beeing estimated or not. + */ + private boolean estimatedMajorSpan; + + /** + * The right inset. + */ + private float rightInset; + + /** + * The children and their layout statistics. + */ + private ArrayList childStates; + + /** + * The currently changing child state. May be null if there is no child state + * updating at the moment. This is package private to avoid a synthetic + * accessor method inside ChildState. + */ + ChildState changing; + + /** + * Represents the minimum requirements. This is used in + * {@link #getMinimumSpan(int)}. + */ + ChildState minReq; + + /** + * Represents the minimum requirements. This is used in + * {@link #getPreferredSpan(int)}. + */ + ChildState prefReq; + + /** + * Indicates that the major axis requirements have changed. + */ + private boolean majorChanged; + + /** + * Indicates that the minor axis requirements have changed. This is package + * private to avoid synthetic accessor method. + */ + boolean minorChanged; + + /** + * The current span along the major layout axis. This is package private to + * avoid synthetic accessor method. + */ + float majorSpan; + + /** + * The current span along the minor layout axis. This is package private to + * avoid synthetic accessor method. + */ + float minorSpan; + + /** + * This tasked is placed on the layout queue to flush updates up to the + * parent view. + */ + private Runnable flushTask; + + /** + * The child locator for this view. + */ + protected ChildLocator locator; + + /** + * Creates a new AsyncBoxView that represents the specified + * element and layouts its children along the specified axis. + * + * @param elem the element + * @param axis the layout axis + */ + public AsyncBoxView(Element elem, int axis) + { + super(elem); + majorAxis = axis; + childStates = new ArrayList(); + flushTask = new FlushTask(); + locator = new ChildLocator(); + minorSpan = Short.MAX_VALUE; + } + + /** + * Returns the major layout axis. + * + * @return the major layout axis + */ + public int getMajorAxis() + { + return majorAxis; + } + + /** + * Returns the minor layout axis, that is the axis orthogonal to the major + * layout axis. + * + * @return the minor layout axis + */ + public int getMinorAxis() + { + return majorAxis == X_AXIS ? Y_AXIS : X_AXIS; + } + + /** + * Returns the view at the specified index. + * + * @param index the index of the requested child view + * + * @return the view at the specified index + */ + public View getView(int index) + { + View view = null; + synchronized(childStates) + { + if ((index >= 0) && (index < childStates.size())) + { + ChildState cs = (ChildState) childStates.get(index); + view = cs.getChildView(); + } + } + return view; + } + + /** + * Returns the number of child views. + * + * @return the number of child views + */ + public int getViewCount() + { + synchronized(childStates) + { + return childStates.size(); + } + } + + /** + * Returns the view index of the child view that represents the specified + * model position. + * + * @param pos the model position for which we search the view index + * @param bias the bias + * + * @return the view index of the child view that represents the specified + * model position + */ + public int getViewIndex(int pos, Position.Bias bias) + { + int retVal = -1; + + if (bias == Position.Bias.Backward) + pos = Math.max(0, pos - 1); + + // TODO: A possible optimization would be to implement a binary search + // here. + int numChildren = childStates.size(); + if (numChildren > 0) + { + for (int i = 0; i < numChildren; ++i) + { + View child = ((ChildState) childStates.get(i)).getChildView(); + if (child.getStartOffset() <= pos && child.getEndOffset() > pos) + { + retVal = i; + break; + } + } + } + return retVal; + } + + /** + * Returns the top inset. + * + * @return the top inset + */ + public float getTopInset() + { + return topInset; + } + + /** + * Sets the top inset. + * + * @param top the top inset + */ + public void setTopInset(float top) + { + topInset = top; + } + + /** + * Returns the bottom inset. + * + * @return the bottom inset + */ + public float getBottomInset() + { + return bottomInset; + } + + /** + * Sets the bottom inset. + * + * @param bottom the bottom inset + */ + public void setBottomInset(float bottom) + { + bottomInset = bottom; + } + + /** + * Returns the left inset. + * + * @return the left inset + */ + public float getLeftInset() + { + return leftInset; + } + + /** + * Sets the left inset. + * + * @param left the left inset + */ + public void setLeftInset(float left) + { + leftInset = left; + } + + /** + * Returns the right inset. + * + * @return the right inset + */ + public float getRightInset() + { + return rightInset; + } + + /** + * Sets the right inset. + * + * @param right the right inset + */ + public void setRightInset(float right) + { + rightInset = right; + } + + /** + * Loads the child views of this view. This is triggered by + * {@link #setParent(View)}. + * + * @param f the view factory to build child views with + */ + protected void loadChildren(ViewFactory f) + { + Element e = getElement(); + int n = e.getElementCount(); + if (n > 0) + { + View[] added = new View[n]; + for (int i = 0; i < n; i++) + { + added[i] = f.create(e.getElement(i)); + } + replace(0, 0, added); + } + } + + /** + * Returns the span along an axis that is taken up by the insets. + * + * @param axis the axis + * + * @return the span along an axis that is taken up by the insets + * + * @since 1.4 + */ + protected float getInsetSpan(int axis) + { + float span; + if (axis == X_AXIS) + span = leftInset + rightInset; + else + span = topInset + bottomInset; + return span; + } + + /** + * Sets the estimatedMajorSpan property that determines if + * the major span should be treated as beeing estimated. + * + * @param estimated if the major span should be treated as estimated or not + * + * @since 1.4 + */ + public void setEstimatedMajorSpan(boolean estimated) + { + estimatedMajorSpan = estimated; + } + + /** + * Determines whether the major span should be treated as estimated or as + * beeing accurate. + * + * @return true if the major span should be treated as + * estimated, false if the major span should be treated + * as accurate + * + * @since 1.4 + */ + public boolean getEstimatedMajorSpan() + { + return estimatedMajorSpan; + } + + /** + * Receives notification from the child states that the requirements along + * the minor axis have changed. + * + * @param cs the child state from which this notification is messaged + */ + protected synchronized void minorRequirementChange(ChildState cs) + { + minorChanged = true; + } + + /** + * Receives notification from the child states that the requirements along + * the major axis have changed. + * + * @param cs the child state from which this notification is messaged + */ + protected void majorRequirementChange(ChildState cs, float delta) + { + if (! estimatedMajorSpan) + majorSpan += delta; + majorChanged = true; + } + + /** + * Sets the parent for this view. This calls loadChildren if + * parent is not null and there have not been any + * child views initializes. + * + * @param parent the new parent view; null if this view is + * removed from the view hierarchy + * + * @see View#setParent(View) + */ + public void setParent(View parent) + { + super.setParent(parent); + if ((parent != null) && (getViewCount() == 0)) + { + ViewFactory f = getViewFactory(); + loadChildren(f); + } + } + + /** + * Sets the size of this view. This is ususally called before {@link #paint} + * is called to make sure the view has a valid layout. + * + * This implementation queues layout requests for every child view if the + * minor axis span has changed. (The major axis span is requested to never + * change for this view). + * + * @param width the width of the view + * @param height the height of the view + */ + public void setSize(float width, float height) + { + float targetSpan; + if (majorAxis == X_AXIS) + targetSpan = height - getTopInset() - getBottomInset(); + else + targetSpan = width - getLeftInset() - getRightInset(); + + if (targetSpan != minorSpan) + { + minorSpan = targetSpan; + + int n = getViewCount(); + LayoutQueue q = getLayoutQueue(); + for (int i = 0; i < n; i++) + { + ChildState cs = getChildState(i); + cs.childSizeValid = false; + q.addTask(cs); + } + q.addTask(flushTask); + } + } + + /** + * Replaces child views with new child views. + * + * This creates ChildState objects for all the new views and adds layout + * requests for them to the layout queue. + * + * @param offset the offset at which to remove/insert + * @param length the number of child views to remove + * @param views the new child views to insert + */ + public void replace(int offset, int length, View[] views) + { + synchronized(childStates) + { + LayoutQueue q = getLayoutQueue(); + for (int i = 0; i < length; i++) + childStates.remove(offset); + + for (int i = views.length - 1; i >= 0; i--) + childStates.add(offset, createChildState(views[i])); + + // We need to go through the new child states _after_ they have been + // added to the childStates list, otherwise the layout tasks may find + // an incomplete child list. That means we have to loop through + // them again, but what else can we do? + if (views.length != 0) + { + for (int i = 0; i < views.length; i++) + { + ChildState cs = (ChildState) childStates.get(i + offset); + cs.getChildView().setParent(this); + q.addTask(cs); + } + q.addTask(flushTask); + } + } + } + + /** + * Paints the view. This requests the {@link ChildLocator} to paint the views + * after setting the allocation on it. + * + * @param g the graphics context to use + * @param s the allocation for this view + */ + public void paint(Graphics g, Shape s) + { + synchronized (locator) + { + locator.setAllocation(s); + locator.paintChildren(g); + } + } + + /** + * Returns the preferred span of this view along the specified layout axis. + * + * @return the preferred span of this view along the specified layout axis + */ + public float getPreferredSpan(int axis) + { + float retVal; + if (majorAxis == axis) + retVal = majorSpan; + + else if (prefReq != null) + { + View child = prefReq.getChildView(); + retVal = child.getPreferredSpan(axis); + } + + // If we have no layout information yet, then return insets + 30 as + // an estimation. + else + { + if (axis == X_AXIS) + retVal = getLeftInset() + getRightInset() + 30; + else + retVal = getTopInset() + getBottomInset() + 30; + } + return retVal; + } + + /** + * Maps a model location to view coordinates. + * + * @param pos the model location + * @param a the current allocation of this view + * @param b the bias + * + * @return the view allocation for the specified model location + */ + public Shape modelToView(int pos, Shape a, Bias b) + throws BadLocationException + { + int index = getViewIndexAtPosition(pos, b); + Shape ca = locator.getChildAllocation(index, a); + + ChildState cs = getChildState(index); + synchronized (cs) + { + View cv = cs.getChildView(); + Shape v = cv.modelToView(pos, ca, b); + return v; + } + } + + /** + * Maps view coordinates to a model location. + * + * @param x the x coordinate (relative to a) + * @param y the y coordinate (relative to a) + * @param b holds the bias of the model location on method exit + * + * @return the model location for the specified view location + */ + public int viewToModel(float x, float y, Shape a, Bias[] b) + { + int pos; + int index; + Shape ca; + + synchronized (locator) + { + index = locator.getViewIndexAtPoint(x, y, a); + ca = locator.getChildAllocation(index, a); + } + + ChildState cs = getChildState(index); + synchronized (cs) + { + View v = cs.getChildView(); + pos = v.viewToModel(x, y, ca, b); + } + return pos; + } + + /** + * Returns the child allocation for the child view with the specified + * index. + * + * @param index the index of the child view + * @param a the current allocation of this view + * + * @return the allocation of the child view + */ + public Shape getChildAllocation(int index, Shape a) + { + Shape ca = locator.getChildAllocation(index, a); + return ca; + } + + /** + * Returns the maximum span of this view along the specified axis. + * This is implemented to return the preferredSpan for the + * major axis (that means the box can't be resized along the major axis) and + * {@link Short#MAX_VALUE} for the minor axis. + * + * @param axis the axis + * + * @return the maximum span of this view along the specified axis + */ + public float getMaximumSpan(int axis) + { + float max; + if (axis == majorAxis) + max = getPreferredSpan(axis); + else + max = Short.MAX_VALUE; + return max; + } + + /** + * Returns the minimum span along the specified axis. + */ + public float getMinimumSpan(int axis) + { + float min; + if (axis == majorAxis) + min = getPreferredSpan(axis); + else + { + if (minReq != null) + { + View child = minReq.getChildView(); + min = child.getMinimumSpan(axis); + } + else + { + // No layout information yet. Return insets + 5 as some kind of + // estimation. + if (axis == X_AXIS) + min = getLeftInset() + getRightInset() + 5; + else + min = getTopInset() + getBottomInset() + 5; + } + } + return min; + } + + /** + * Receives notification that one of the child views has changed its + * layout preferences along one or both axis. + * + * This queues a layout request for that child view if necessary. + * + * @param view the view that has changed its preferences + * @param width true if the width preference has changed + * @param height true if the height preference has changed + */ + public synchronized void preferenceChanged(View view, boolean width, + boolean height) + { + if (view == null) + getParent().preferenceChanged(this, width, height); + else + { + if (changing != null) + { + View cv = changing.getChildView(); + if (cv == view) + { + changing.preferenceChanged(width, height); + return; + } + } + int index = getViewIndexAtPosition(view.getStartOffset(), + Position.Bias.Forward); + ChildState cs = getChildState(index); + cs.preferenceChanged(width, height); + LayoutQueue q = getLayoutQueue(); + q.addTask(cs); + q.addTask(flushTask); + } + } + + /** + * Updates the layout for this view. This is implemented to trigger + * {link ChildLocator#childChanged} for the changed view, if there is + * any. + * + * @param ec the element change, may be null if there were + * no changes to the element of this view + * @param e the document event + * @param a the current allocation of this view + */ + protected void updateLayout(DocumentEvent.ElementChange ec, + DocumentEvent e, Shape a) + { + if (ec != null) + { + int index = Math.max(ec.getIndex() - 1, 0); + ChildState cs = getChildState(index); + locator.childChanged(cs); + } + } + + + /** + * Returns the ChildState object associated with the child view + * at the specified index. + * + * @param index the index of the child view for which to query the state + * + * @return the child state for the specified child view + */ + protected ChildState getChildState(int index) { + synchronized (childStates) + { + return (ChildState) childStates.get(index); + } + } + + /** + * Returns the LayoutQueue used for layouting the box view. + * This simply returns {@link LayoutQueue#getDefaultQueue()}. + * + * @return the LayoutQueue used for layouting the box view + */ + protected LayoutQueue getLayoutQueue() + { + return LayoutQueue.getDefaultQueue(); + } + + /** + * Returns the child view index of the view that represents the specified + * position in the document model. + * + * @param pos the position in the model + * @param b the bias + * + * @return the child view index of the view that represents the specified + * position in the document model + */ + protected synchronized int getViewIndexAtPosition(int pos, Position.Bias b) + { + if (b == Position.Bias.Backward) + pos = Math.max(0, pos - 1); + Element elem = getElement(); + return elem.getElementIndex(pos); + } + + /** + * Creates a ChildState object for the specified view. + * + * @param v the view for which to create a child state object + * + * @return the created child state + */ + protected ChildState createChildState(View v) + { + return new ChildState(v); + } + + /** + * Flushes the requirements changes upwards to the parent view. This is + * called from the layout thread. + */ + protected synchronized void flushRequirementChanges() + { + if (majorChanged || minorChanged) + { + View p = getParent(); + if (p != null) + { + boolean horizontal; + boolean vertical; + if (majorAxis == X_AXIS) + { + horizontal = majorChanged; + vertical = minorChanged; + } + else + { + vertical = majorChanged; + horizontal = minorChanged; + } + + p.preferenceChanged(this, horizontal, vertical); + majorChanged = false; + minorChanged = false; + + Component c = getContainer(); + if (c != null) + c.repaint(); + } + } + } +} diff --git a/libjava/classpath/javax/swing/text/BoxView.java b/libjava/classpath/javax/swing/text/BoxView.java index 5c9587d..b5907dc 100644 --- a/libjava/classpath/javax/swing/text/BoxView.java +++ b/libjava/classpath/javax/swing/text/BoxView.java @@ -43,6 +43,7 @@ import java.awt.Rectangle; import java.awt.Shape; import javax.swing.SizeRequirements; +import javax.swing.event.DocumentEvent; /** * An implementation of {@link CompositeView} that arranges its children in @@ -58,49 +59,37 @@ public class BoxView /** * The axis along which this BoxView is laid out. */ - int myAxis; + private int myAxis; /** - * Indicates wether the layout in X_AXIS is valid. + * Indicates if the layout is valid along X_AXIS or Y_AXIS. */ - boolean xLayoutValid; + private boolean[] layoutValid = new boolean[2]; /** - * Indicates whether the layout in Y_AXIS is valid. + * The spans along the X_AXIS and Y_AXIS. */ - boolean yLayoutValid; + private int[][] spans = new int[2][]; /** - * The spans in X direction of the children. + * The offsets of the children along the X_AXIS and Y_AXIS. */ - int[] spansX; + private int[][] offsets = new int[2][]; /** - * The spans in Y direction of the children. + * The size requirements along the X_AXIS and Y_AXIS. */ - int[] spansY; + private SizeRequirements[] requirements = new SizeRequirements[2]; /** - * The offsets of the children in X direction relative to this BoxView's - * inner bounds. + * The current span along X_AXIS or Y_AXIS. */ - int[] offsetsX; + private int[] span = new int[2]; /** - * The offsets of the children in Y direction relative to this BoxView's - * inner bounds. + * The SizeRequirements of the child views along the X_AXIS and Y_AXIS. */ - int[] offsetsY; - - /** - * The current width. - */ - int width; - - /** - * The current height. - */ - int height; + private SizeRequirements[][] childReqs = new SizeRequirements[2][]; /** * Creates a new BoxView for the given @@ -114,23 +103,26 @@ public class BoxView { super(element); myAxis = axis; - xLayoutValid = false; - yLayoutValid = false; + layoutValid[0] = false; + layoutValid[1] = false; + span[0] = 0; + span[1] = 0; + requirements[0] = new SizeRequirements(); + requirements[1] = new SizeRequirements(); // Initialize the cache arrays. - spansX = new int[0]; - spansY = new int[0]; - offsetsX = new int[0]; - offsetsY = new int[0]; - - width = 0; - height = 0; + spans[0] = new int[0]; + spans[1] = new int[0]; + offsets[0] = new int[0]; + offsets[1] = new int[0]; } /** * Returns the axis along which this BoxView is laid out. * * @return the axis along which this BoxView is laid out + * + * @since 1.3 */ public int getAxis() { @@ -144,6 +136,8 @@ public class BoxView * {@link View#Y_AXIS}. * * @param axis the axis along which this BoxView is laid out + * + * @since 1.3 */ public void setAxis(int axis) { @@ -163,20 +157,14 @@ public class BoxView * {@link View#Y_AXIS}. * * @param axis an int value + * + * @since 1.3 */ public void layoutChanged(int axis) { - switch (axis) - { - case X_AXIS: - xLayoutValid = false; - break; - case Y_AXIS: - yLayoutValid = false; - break; - default: - throw new IllegalArgumentException("Invalid axis parameter."); - } + if (axis != X_AXIS && axis != Y_AXIS) + throw new IllegalArgumentException("Invalid axis parameter."); + layoutValid[axis] = false; } /** @@ -190,22 +178,14 @@ public class BoxView * * @return true if the layout along the specified * axis is valid, false otherwise + * + * @since 1.4 */ protected boolean isLayoutValid(int axis) { - boolean valid = false; - switch (axis) - { - case X_AXIS: - valid = xLayoutValid; - break; - case Y_AXIS: - valid = yLayoutValid; - break; - default: - throw new IllegalArgumentException("Invalid axis parameter."); - } - return valid; + if (axis != X_AXIS && axis != Y_AXIS) + throw new IllegalArgumentException("Invalid axis parameter."); + return layoutValid[axis]; } /** @@ -242,40 +222,44 @@ public class BoxView */ public void replace(int offset, int length, View[] views) { + int numViews = 0; + if (views != null) + numViews = views.length; + // Resize and copy data for cache arrays. // The spansX cache. int oldSize = getViewCount(); - int[] newSpansX = new int[oldSize - length + views.length]; - System.arraycopy(spansX, 0, newSpansX, 0, offset); - System.arraycopy(spansX, offset + length, newSpansX, - offset + views.length, + int[] newSpansX = new int[oldSize - length + numViews]; + System.arraycopy(spans[X_AXIS], 0, newSpansX, 0, offset); + System.arraycopy(spans[X_AXIS], offset + length, newSpansX, + offset + numViews, oldSize - (offset + length)); - spansX = newSpansX; + spans[X_AXIS] = newSpansX; // The spansY cache. - int[] newSpansY = new int[oldSize - length + views.length]; - System.arraycopy(spansY, 0, newSpansY, 0, offset); - System.arraycopy(spansY, offset + length, newSpansY, - offset + views.length, + int[] newSpansY = new int[oldSize - length + numViews]; + System.arraycopy(spans[Y_AXIS], 0, newSpansY, 0, offset); + System.arraycopy(spans[Y_AXIS], offset + length, newSpansY, + offset + numViews, oldSize - (offset + length)); - spansY = newSpansY; + spans[Y_AXIS] = newSpansY; // The offsetsX cache. - int[] newOffsetsX = new int[oldSize - length + views.length]; - System.arraycopy(offsetsX, 0, newOffsetsX, 0, offset); - System.arraycopy(offsetsX, offset + length, newOffsetsX, - offset + views.length, + int[] newOffsetsX = new int[oldSize - length + numViews]; + System.arraycopy(offsets[X_AXIS], 0, newOffsetsX, 0, offset); + System.arraycopy(offsets[X_AXIS], offset + length, newOffsetsX, + offset + numViews, oldSize - (offset + length)); - offsetsX = newOffsetsX; + offsets[X_AXIS] = newOffsetsX; // The offsetsY cache. - int[] newOffsetsY = new int[oldSize - length + views.length]; - System.arraycopy(offsetsY, 0, newOffsetsY, 0, offset); - System.arraycopy(offsetsY, offset + length, newOffsetsY, - offset + views.length, + int[] newOffsetsY = new int[oldSize - length + numViews]; + System.arraycopy(offsets[Y_AXIS], 0, newOffsetsY, 0, offset); + System.arraycopy(offsets[Y_AXIS], offset + length, newOffsetsY, + offset + numViews, oldSize - (offset + length)); - offsetsY = newOffsetsY; + offsets[Y_AXIS] = newOffsetsY; // Actually perform the replace. super.replace(offset, length, views); @@ -294,13 +278,10 @@ public class BoxView */ public void paint(Graphics g, Shape a) { - // Adjust size if the size is changed. - Rectangle bounds = a.getBounds(); - - if (bounds.width != getWidth() || bounds.height != getHeight()) - setSize(bounds.width, bounds.height); - Rectangle inside = getInsideAllocation(a); + // TODO: Used for debugging. + //g.drawRect(inside.x, inside.y, inside.width, inside.height); + Rectangle copy = new Rectangle(inside); int count = getViewCount(); for (int i = 0; i < count; ++i) @@ -323,22 +304,50 @@ public class BoxView */ public float getPreferredSpan(int axis) { - SizeRequirements sr = new SizeRequirements(); - int pref = baselineRequirements(axis, sr).preferred; - return (float) pref; + updateRequirements(axis); + return requirements[axis].preferred; } + /** + * Returns the maximum span of this view along the specified axis. + * This returns Integer.MAX_VALUE for the minor axis + * and the preferred span for the major axis. + * + * @param axis the axis + * + * @return the maximum span of this view along the specified axis + */ public float getMaximumSpan(int axis) { - if (axis == getAxis()) - return getPreferredSpan(axis); + float max; + if (axis == myAxis) + max = getPreferredSpan(axis); else - return Integer.MAX_VALUE; + max = Integer.MAX_VALUE; + return max; } /** - * Calculates the size requirements for this BoxView along - * the specified axis. + * Returns the minimum span of this view along the specified axis. + * This calculates the minimum span using + * {@link #calculateMajorAxisRequirements} or + * {@link #calculateMinorAxisRequirements} (depending on the axis) and + * returns the resulting minimum span. + * + * @param axis the axis + * + * @return the minimum span of this view along the specified axis + */ + public float getMinimumSpan(int axis) + { + updateRequirements(axis); + return requirements[axis].minimum; + } + + /** + * This method is obsolete and no longer in use. It is replaced by + * {@link #calculateMajorAxisRequirements(int, SizeRequirements)} and + * {@link #calculateMinorAxisRequirements(int, SizeRequirements)}. * * @param axis the axis that is examined * @param sr the SizeRequirements object to hold the result, @@ -350,12 +359,45 @@ public class BoxView protected SizeRequirements baselineRequirements(int axis, SizeRequirements sr) { - SizeRequirements result; - if (axis == myAxis) - result = calculateMajorAxisRequirements(axis, sr); - else - result = calculateMinorAxisRequirements(axis, sr); - return result; + updateChildRequirements(axis); + + SizeRequirements res = sr; + if (res == null) + res = new SizeRequirements(); + + float minLeft = 0; + float minRight = 0; + float prefLeft = 0; + float prefRight = 0; + float maxLeft = 0; + float maxRight = 0; + for (int i = 0; i < childReqs[axis].length; i++) + { + float myMinLeft = childReqs[axis][i].minimum * childReqs[axis][i].alignment; + float myMinRight = childReqs[axis][i].minimum - myMinLeft; + minLeft = Math.max(myMinLeft, minLeft); + minRight = Math.max(myMinRight, minRight); + float myPrefLeft = childReqs[axis][i].preferred * childReqs[axis][i].alignment; + float myPrefRight = childReqs[axis][i].preferred - myPrefLeft; + prefLeft = Math.max(myPrefLeft, prefLeft); + prefRight = Math.max(myPrefRight, prefRight); + float myMaxLeft = childReqs[axis][i].maximum * childReqs[axis][i].alignment; + float myMaxRight = childReqs[axis][i].maximum - myMaxLeft; + maxLeft = Math.max(myMaxLeft, maxLeft); + maxRight = Math.max(myMaxRight, maxRight); + } + int minSize = (int) (minLeft + minRight); + int prefSize = (int) (prefLeft + prefRight); + int maxSize = (int) (maxLeft + maxRight); + float align = prefLeft / (prefRight + prefLeft); + if (Float.isNaN(align)) + align = 0; + + res.alignment = align; + res.maximum = maxSize; + res.preferred = prefSize; + res.minimum = minSize; + return res; } /** @@ -370,10 +412,13 @@ public class BoxView protected void baselineLayout(int span, int axis, int[] offsets, int[] spans) { - if (axis == myAxis) - layoutMajorAxis(span, axis, offsets, spans); - else - layoutMinorAxis(span, axis, offsets, spans); + updateChildRequirements(axis); + updateRequirements(axis); + + // Calculate the spans and offsets using the SizeRequirements uility + // methods. + SizeRequirements.calculateAlignedPositions(span, requirements[axis], + childReqs[axis], offsets, spans); } /** @@ -390,8 +435,34 @@ public class BoxView protected SizeRequirements calculateMajorAxisRequirements(int axis, SizeRequirements sr) { - SizeRequirements[] childReqs = getChildRequirements(axis); - return SizeRequirements.getTiledSizeRequirements(childReqs); + updateChildRequirements(axis); + + SizeRequirements result = sr; + if (result == null) + result = new SizeRequirements(); + + long minimum = 0; + long preferred = 0; + long maximum = 0; + for (int i = 0; i < children.length; i++) + { + minimum += childReqs[axis][i].minimum; + preferred += childReqs[axis][i].preferred; + maximum += childReqs[axis][i].maximum; + } + // Overflow check. + if (minimum > Integer.MAX_VALUE) + minimum = Integer.MAX_VALUE; + if (preferred > Integer.MAX_VALUE) + preferred = Integer.MAX_VALUE; + if (maximum > Integer.MAX_VALUE) + maximum = Integer.MAX_VALUE; + + result.minimum = (int) minimum; + result.preferred = (int) preferred; + result.maximum = (int) maximum; + result.alignment = 0.5F; + return result; } /** @@ -407,11 +478,49 @@ public class BoxView * the specified axis */ protected SizeRequirements calculateMinorAxisRequirements(int axis, - SizeRequirements sr) + SizeRequirements sr) { - SizeRequirements[] childReqs = getChildRequirements(axis); - return SizeRequirements.getAlignedSizeRequirements(childReqs); + updateChildRequirements(axis); + + SizeRequirements res = sr; + if (res == null) + res = new SizeRequirements(); + + float minLeft = 0; + float minRight = 0; + float prefLeft = 0; + float prefRight = 0; + float maxLeft = 0; + float maxRight = 0; + for (int i = 0; i < childReqs[axis].length; i++) + { + float myMinLeft = childReqs[axis][i].minimum * childReqs[axis][i].alignment; + float myMinRight = childReqs[axis][i].minimum - myMinLeft; + minLeft = Math.max(myMinLeft, minLeft); + minRight = Math.max(myMinRight, minRight); + float myPrefLeft = childReqs[axis][i].preferred * childReqs[axis][i].alignment; + float myPrefRight = childReqs[axis][i].preferred - myPrefLeft; + prefLeft = Math.max(myPrefLeft, prefLeft); + prefRight = Math.max(myPrefRight, prefRight); + float myMaxLeft = childReqs[axis][i].maximum * childReqs[axis][i].alignment; + float myMaxRight = childReqs[axis][i].maximum - myMaxLeft; + maxLeft = Math.max(myMaxLeft, maxLeft); + maxRight = Math.max(myMaxRight, maxRight); + } + int minSize = (int) (minLeft + minRight); + int prefSize = (int) (prefLeft + prefRight); + int maxSize = (int) (maxLeft + maxRight); + float align = prefLeft / (prefRight + prefLeft); + if (Float.isNaN(align)) + align = 0; + + res.alignment = align; + res.maximum = maxSize; + res.preferred = prefSize; + res.minimum = minSize; + return res; } + /** * Returns true if the specified point lies before the @@ -511,10 +620,10 @@ public class BoxView if (! isAllocationValid()) layout(a.width, a.height); - a.x += offsetsX[index]; - a.y += offsetsY[index]; - a.width = spansX[index]; - a.height = spansY[index]; + a.x += offsets[X_AXIS][index]; + a.y += offsets[Y_AXIS][index]; + a.width = spans[X_AXIS][index]; + a.height = spans[Y_AXIS][index]; } /** @@ -528,8 +637,49 @@ public class BoxView */ protected void layout(int width, int height) { - baselineLayout(width, X_AXIS, offsetsX, spansX); - baselineLayout(height, Y_AXIS, offsetsY, spansY); + int[] newSpan = new int[]{ width, height }; + int count = getViewCount(); + + // Update minor axis as appropriate. We need to first update the minor + // axis layout because that might affect the children's preferences along + // the major axis. + int minorAxis = myAxis == X_AXIS ? Y_AXIS : X_AXIS; + if ((! isLayoutValid(minorAxis)) || newSpan[minorAxis] != span[minorAxis]) + { + layoutValid[minorAxis] = false; + span[minorAxis] = newSpan[minorAxis]; + layoutMinorAxis(span[minorAxis], minorAxis, offsets[minorAxis], + spans[minorAxis]); + + // Update the child view's sizes. + for (int i = 0; i < count; ++i) + { + getView(i).setSize(spans[X_AXIS][i], spans[Y_AXIS][i]); + } + layoutValid[minorAxis] = true; + } + + + // Update major axis as appropriate. + if ((! isLayoutValid(myAxis)) || newSpan[myAxis] != span[myAxis]) + { + layoutValid[myAxis] = false; + span[myAxis] = newSpan[myAxis]; + layoutMajorAxis(span[myAxis], myAxis, offsets[myAxis], + spans[myAxis]); + + // Update the child view's sizes. + for (int i = 0; i < count; ++i) + { + getView(i).setSize(spans[X_AXIS][i], spans[Y_AXIS][i]); + } + layoutValid[myAxis] = true; + } + + if (layoutValid[myAxis] == false) + System.err.println("WARNING: Major axis layout must be valid after layout"); + if (layoutValid[minorAxis] == false) + System.err.println("Minor axis layout must be valid after layout"); } /** @@ -544,12 +694,15 @@ public class BoxView protected void layoutMajorAxis(int targetSpan, int axis, int[] offsets, int[] spans) { - SizeRequirements[] childReqs = getChildRequirements(axis); + updateChildRequirements(axis); + updateRequirements(axis); + // Calculate the spans and offsets using the SizeRequirements uility // methods. - SizeRequirements.calculateTiledPositions(targetSpan, null, childReqs, + SizeRequirements.calculateTiledPositions(targetSpan, requirements[axis], + childReqs[axis], offsets, spans); - validateLayout(axis); + } /** @@ -564,18 +717,14 @@ public class BoxView protected void layoutMinorAxis(int targetSpan, int axis, int[] offsets, int[] spans) { - SizeRequirements[] childReqs = getChildRequirements(axis); + updateChildRequirements(axis); + updateRequirements(axis); + // Calculate the spans and offsets using the SizeRequirements uility // methods. - // TODO: This might be an opportunity for performance optimization. Here - // we could use a cached instance of SizeRequirements instead of passing - // null to baselineRequirements. However, this would involve rewriting - // the baselineRequirements() method to not use the SizeRequirements - // utility method, since they cannot reuse a cached instance. - SizeRequirements total = baselineRequirements(axis, null); - SizeRequirements.calculateAlignedPositions(targetSpan, total, childReqs, - offsets, spans); - validateLayout(axis); + SizeRequirements.calculateAlignedPositions(targetSpan, requirements[axis], + childReqs[axis], offsets, + spans); } /** @@ -597,7 +746,7 @@ public class BoxView */ public int getWidth() { - return width; + return span[X_AXIS]; } /** @@ -607,7 +756,7 @@ public class BoxView */ public int getHeight() { - return height; + return span[Y_AXIS]; } /** @@ -619,54 +768,7 @@ public class BoxView */ public void setSize(float width, float height) { - if (this.width != (int) width) - layoutChanged(X_AXIS); - if (this.height != (int) height) - layoutChanged(Y_AXIS); - - this.width = (int) width; - this.height = (int) height; - - Rectangle outside = new Rectangle(0, 0, this.width, this.height); - Rectangle inside = getInsideAllocation(outside); - if (!isAllocationValid()) - layout(inside.width, inside.height); - } - - /** - * Sets the layout to valid for a specific axis. - * - * @param axis the axis for which to validate the layout - */ - void validateLayout(int axis) - { - if (axis == X_AXIS) - xLayoutValid = true; - if (axis == Y_AXIS) - yLayoutValid = true; - } - - /** - * Returns the size requirements of this view's children for the major - * axis. - * - * @return the size requirements of this view's children for the major - * axis - */ - SizeRequirements[] getChildRequirements(int axis) - { - // Allocate SizeRequirements for each child view. - int count = getViewCount(); - SizeRequirements[] childReqs = new SizeRequirements[count]; - for (int i = 0; i < count; ++i) - { - View view = getView(i); - childReqs[i] = new SizeRequirements((int) view.getMinimumSpan(axis), - (int) view.getPreferredSpan(axis), - (int) view.getMaximumSpan(axis), - view.getAlignment(axis)); - } - return childReqs; + layout((int) width, (int) height); } /** @@ -682,10 +784,9 @@ public class BoxView */ protected int getSpan(int axis, int childIndex) { - if (axis == X_AXIS) - return spansX[childIndex]; - else - return spansY[childIndex]; + if (axis != X_AXIS && axis != Y_AXIS) + throw new IllegalArgumentException("Illegal axis argument"); + return spans[axis][childIndex]; } /** @@ -701,10 +802,9 @@ public class BoxView */ protected int getOffset(int axis, int childIndex) { - if (axis == X_AXIS) - return offsetsX[childIndex]; - else - return offsetsY[childIndex]; + if (axis != X_AXIS && axis != Y_AXIS) + throw new IllegalArgumentException("Illegal axis argument"); + return offsets[axis][childIndex]; } /** @@ -719,10 +819,15 @@ public class BoxView */ public float getAlignment(int axis) { + float align; if (axis == myAxis) - return 0.5F; + align = 0.5F; else - return baselineRequirements(axis, null).alignment; + { + updateRequirements(axis); + align = requirements[axis].alignment; + } + return align; } /** @@ -732,12 +837,12 @@ public class BoxView * @param height indicates that the preferred height of the child changed. * @param child the child View. */ - public void preferenceChanged (View child, boolean width, boolean height) + public void preferenceChanged(View child, boolean width, boolean height) { if (width) - xLayoutValid = false; + layoutValid[X_AXIS] = false; if (height) - yLayoutValid = false; + layoutValid[Y_AXIS] = false; super.preferenceChanged(child, width, height); } @@ -751,11 +856,118 @@ public class BoxView throws BadLocationException { // Make sure everything is allocated properly and then call super - if (!isAllocationValid()) + if (! isAllocationValid()) { Rectangle bounds = a.getBounds(); - setSize(bounds.width, bounds.height); + layout(bounds.width, bounds.height); } return super.modelToView(pos, a, bias); } + + /** + * Returns the resize weight of this view. A value of 0 or less + * means this view is not resizeable. Positive values make the view + * resizeable. This implementation returns 0 for the major + * axis and 1 for the minor axis of this box view. + * + * @param axis the axis + * + * @return the resizability of this view along the specified axis + * + * @throws IllegalArgumentException if axis is invalid + */ + public int getResizeWeight(int axis) + { + if (axis != X_AXIS && axis != Y_AXIS) + throw new IllegalArgumentException("Illegal axis argument"); + int weight = 1; + if (axis == myAxis) + weight = 0; + return weight; + } + + /** + * Returns the child allocation for the child view with the specified + * index. If the layout is invalid, this returns + * null. + * + * @param index the child view index + * @param a the allocation to this view + * + * @return the child allocation for the child view with the specified + * index or null if the layout is invalid + * or a is null + */ + public Shape getChildAllocation(int index, Shape a) + { + Shape ret = null; + if (isAllocationValid() && a != null) + ret = super.getChildAllocation(index, a); + return ret; + } + + protected void forwardUpdate(DocumentEvent.ElementChange ec, DocumentEvent e, + Shape a, ViewFactory vf) + { + // FIXME: What to do here? + super.forwardUpdate(ec, e, a, vf); + } + + public int viewToModel(float x, float y, Shape a, Position.Bias[] bias) + { + // FIXME: What to do here? + return super.viewToModel(x, y, a, bias); + } + + protected boolean flipEastAndWestEnds(int position, Position.Bias bias) + { + // FIXME: What to do here? + return super.flipEastAndWestAtEnds(position, bias); + } + + /** + * Updates the child requirements along the specified axis. The requirements + * are only updated if the layout for the specified axis is marked as + * invalid. + * + * @param axis the axis to be updated + */ + private void updateChildRequirements(int axis) + { + if (! isLayoutValid(axis)) + { + int numChildren = getViewCount(); + if (childReqs[axis] == null || childReqs[axis].length != numChildren) + childReqs[axis] = new SizeRequirements[numChildren]; + for (int i = 0; i < numChildren; ++i) + { + View child = getView(i); + childReqs[axis][i] = + new SizeRequirements((int) child.getMinimumSpan(axis), + (int) child.getPreferredSpan(axis), + (int) child.getMaximumSpan(axis), + child.getAlignment(axis)); + } + } + } + + /** + * Updates the view's cached requirements along the specified axis if + * necessary. The requirements are only updated if the layout for the + * specified axis is marked as invalid. + * + * @param axis the axis + */ + private void updateRequirements(int axis) + { + if (! layoutValid[axis]) + { + if (axis == myAxis) + requirements[axis] = calculateMajorAxisRequirements(axis, + requirements[axis]); + else + requirements[axis] = calculateMinorAxisRequirements(axis, + requirements[axis]); + } + } } diff --git a/libjava/classpath/javax/swing/text/ComponentView.java b/libjava/classpath/javax/swing/text/ComponentView.java index 2846f8b..a7d237a 100644 --- a/libjava/classpath/javax/swing/text/ComponentView.java +++ b/libjava/classpath/javax/swing/text/ComponentView.java @@ -228,8 +228,9 @@ public class ComponentView extends View * * @param p the parent view to set */ - void setParentImpl(View p) + private void setParentImpl(View p) { + super.setParent(p); if (p != null) { Component c = getComponent(); diff --git a/libjava/classpath/javax/swing/text/CompositeView.java b/libjava/classpath/javax/swing/text/CompositeView.java index cd66452..a10aca7 100644 --- a/libjava/classpath/javax/swing/text/CompositeView.java +++ b/libjava/classpath/javax/swing/text/CompositeView.java @@ -218,20 +218,43 @@ public abstract class CompositeView throws BadLocationException { int childIndex = getViewIndex(pos, bias); + Shape ret = null; if (childIndex != -1) { View child = getView(childIndex); - Rectangle r = a.getBounds(); - childAllocation(childIndex, r); - Shape result = child.modelToView(pos, r, bias); - if (result == null) - throw new AssertionError("" + child.getClass().getName() - + ".modelToView() must not return null"); - return result; + Shape childAlloc = getChildAllocation(childIndex, a); + if (childAlloc == null) + ret = createDefaultLocation(a, bias); + Shape result = child.modelToView(pos, childAlloc, bias); + if (result != null) + ret = result; + else + ret = createDefaultLocation(a, bias); } else - throw new BadLocationException("No child view for the specified location", - pos); + ret = createDefaultLocation(a, bias); + return ret; + } + + /** + * A helper method for {@link #modelToView(int, Position.Bias, int, + * Position.Bias, Shape)}. This creates a default location when there is + * no child view that can take responsibility for mapping the position to + * view coordinates. Depending on the specified bias this will be the + * left or right edge of this view's allocation. + * + * @param a the allocation for this view + * @param bias the bias + * + * @return a default location + */ + private Shape createDefaultLocation(Shape a, Position.Bias bias) + { + Rectangle alloc = a.getBounds(); + Rectangle location = new Rectangle(alloc.x, alloc.y, 1, alloc.height); + if (bias == Position.Bias.Forward) + location.x = alloc.x + alloc.width; + return location; } /** @@ -350,7 +373,8 @@ public abstract class CompositeView */ public int getViewIndex(int pos, Position.Bias b) { - // FIXME: Handle bias somehow. + if (b == Position.Bias.Backward && pos != 0) + pos -= 1; return getViewIndexAtPosition(pos); } diff --git a/libjava/classpath/javax/swing/text/DefaultCaret.java b/libjava/classpath/javax/swing/text/DefaultCaret.java index 776ef69..f2a68c0 100644 --- a/libjava/classpath/javax/swing/text/DefaultCaret.java +++ b/libjava/classpath/javax/swing/text/DefaultCaret.java @@ -148,14 +148,16 @@ public class DefaultCaret extends Rectangle */ public void removeUpdate(DocumentEvent event) { - if (policy == ALWAYS_UPDATE || - (SwingUtilities.isEventDispatchThread() && - policy == UPDATE_WHEN_ON_EDT)) + if (policy == ALWAYS_UPDATE + || (SwingUtilities.isEventDispatchThread() + && policy == UPDATE_WHEN_ON_EDT)) { int dot = getDot(); setDot(dot - event.getLength()); } - else if (policy == NEVER_UPDATE) + else if (policy == NEVER_UPDATE + || (! SwingUtilities.isEventDispatchThread() + && policy == UPDATE_WHEN_ON_EDT)) { int docLength = event.getDocument().getLength(); if (getDot() > docLength) @@ -364,7 +366,8 @@ public class DefaultCaret extends Rectangle *