summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew John Hughes <gnu_andrew@member.fsf.org>2006-11-13 00:29:48 +0000
committerAndrew John Hughes <gnu_andrew@member.fsf.org>2006-11-13 00:29:48 +0000
commit2a2b91f336fe4f6c2a314db2bc4cdffff6cf5a61 (patch)
tree21df1df36e4070dbe32198f06ea33964e82a998b
parent237bdd93058f891ae4567cf4e051c5831bd4646b (diff)
downloadclasspath-2a2b91f336fe4f6c2a314db2bc4cdffff6cf5a61.tar.gz
2006-11-13 Andrew John Hughes <gnu_andrew@member.fsf.org>
* Merge of HEAD-->generics from 2006/11/04-2006/11/12.
-rw-r--r--ChangeLog561
-rw-r--r--examples/Makefile.am7
-rw-r--r--examples/gnu/classpath/examples/swing/HtmlDemo.java266
-rw-r--r--examples/gnu/classpath/examples/swing/forms.html69
-rw-r--r--examples/gnu/classpath/examples/swing/textstyles.html78
-rw-r--r--examples/gnu/classpath/examples/swing/welcome.html52
-rw-r--r--gnu/java/awt/peer/gtk/CairoGraphics2D.java21
-rw-r--r--gnu/java/awt/peer/gtk/ComponentGraphics.java225
-rw-r--r--gnu/java/awt/peer/gtk/GtkImageConsumer.java43
-rw-r--r--gnu/java/awt/peer/gtk/VolatileImageGraphics.java4
-rw-r--r--gnu/java/awt/peer/headless/HeadlessGraphicsEnvironment.java88
-rw-r--r--gnu/java/awt/peer/headless/HeadlessToolkit.java371
-rw-r--r--gnu/java/awt/peer/swing/SwingButtonPeer.java22
-rw-r--r--gnu/java/awt/peer/swing/SwingComponent.java6
-rw-r--r--gnu/java/awt/peer/swing/SwingComponentPeer.java196
-rw-r--r--gnu/java/awt/peer/swing/SwingContainerPeer.java209
-rw-r--r--gnu/java/awt/peer/swing/SwingFramePeer.java11
-rw-r--r--gnu/java/awt/peer/swing/SwingLabelPeer.java48
-rw-r--r--gnu/java/awt/peer/swing/SwingListPeer.java352
-rw-r--r--gnu/java/awt/peer/swing/SwingMenuBarPeer.java2
-rw-r--r--gnu/java/awt/peer/swing/SwingPanelPeer.java4
-rw-r--r--gnu/java/awt/peer/swing/SwingTextAreaPeer.java317
-rw-r--r--gnu/java/awt/peer/swing/SwingTextFieldPeer.java32
-rw-r--r--gnu/java/awt/peer/swing/SwingWindowPeer.java8
-rw-r--r--gnu/java/net/protocol/jar/Handler.java46
-rw-r--r--gnu/javax/swing/text/html/css/BorderWidth.java (renamed from gnu/javax/swing/text/html/parser/HTML_401Swing.java)65
-rw-r--r--gnu/javax/swing/text/html/css/CSSColor.java29
-rw-r--r--gnu/javax/swing/text/html/css/CSSParser.java23
-rw-r--r--gnu/javax/swing/text/html/css/CSSParserCallback.java2
-rw-r--r--gnu/javax/swing/text/html/css/CSSScanner.java1
-rw-r--r--gnu/javax/swing/text/html/css/Length.java64
-rw-r--r--gnu/javax/swing/text/html/css/Selector.java233
-rw-r--r--gnu/javax/swing/text/html/parser/GnuParserDelegator.java3
-rw-r--r--gnu/javax/swing/text/html/parser/support/Parser.java21
-rw-r--r--include/gnu_java_net_VMPlainDatagramSocketImpl.h30
-rw-r--r--include/gnu_java_nio_channels_FileChannelImpl.h46
-rw-r--r--java/awt/FlowLayout.java5
-rw-r--r--java/awt/TextComponent.java4
-rw-r--r--java/awt/TextField.java12
-rw-r--r--java/awt/Toolkit.java9
-rw-r--r--java/beans/SimpleBeanInfo.java15
-rw-r--r--java/beans/beancontext/BeanContextSupport.java75
-rw-r--r--java/io/OutputStreamWriter.java6
-rw-r--r--java/util/Collections.java15
-rw-r--r--java/util/regex/Matcher.java1
-rw-r--r--javax/swing/JLabel.java35
-rw-r--r--javax/swing/JTree.java88
-rw-r--r--javax/swing/text/ComponentView.java19
-rw-r--r--javax/swing/text/CompositeView.java2
-rw-r--r--javax/swing/text/FlowView.java31
-rw-r--r--javax/swing/text/GlyphView.java71
-rw-r--r--javax/swing/text/ParagraphView.java16
-rw-r--r--javax/swing/text/View.java21
-rw-r--r--javax/swing/text/html/BlockView.java204
-rw-r--r--javax/swing/text/html/CSS.java56
-rw-r--r--javax/swing/text/html/CSSBorder.java420
-rw-r--r--javax/swing/text/html/HTMLDocument.java152
-rw-r--r--javax/swing/text/html/HTMLEditorKit.java10
-rw-r--r--javax/swing/text/html/HTMLWriter.java50
-rw-r--r--javax/swing/text/html/InlineView.java102
-rw-r--r--javax/swing/text/html/ListView.java3
-rw-r--r--javax/swing/text/html/ParagraphView.java119
-rw-r--r--javax/swing/text/html/StyleSheet.java278
-rw-r--r--javax/swing/text/html/TableView.java616
-rw-r--r--javax/swing/text/html/parser/DocumentParser.java4
-rw-r--r--javax/swing/text/html/parser/ParserDelegator.java4
-rw-r--r--native/jni/java-net/gnu_java_net_VMPlainDatagramSocketImpl.c406
-rw-r--r--native/jni/java-nio/Makefile.am1
-rw-r--r--native/jni/java-nio/gnu_java_nio_VMChannel.c4
-rw-r--r--native/jni/java-nio/gnu_java_nio_channels_FileChannelImpl.c773
70 files changed, 5124 insertions, 2058 deletions
diff --git a/ChangeLog b/ChangeLog
index e19e1bb74..8e4952f17 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,564 @@
+2006-11-11 Andreas Tobler <a.tobler@schweiz.org>
+
+ * gnu/java/awt/peer/gtk/GtkImageConsumer.java (setPixels): Handle data
+ from big endian systems correctly.
+
+2006-11-11 Roman Kennke <kennke@aicas.com>
+
+ * gnu/javax/swing/text/html/css/CSSColor.java
+ (isValidColor): New helper method. Checks strings if they
+ form a valid color value.
+ * gnu/javax/swing/text/html/css/Length.java
+ (Length): Catch number format exceptions.
+ * javax/swing/text/html/CSS.java
+ (addInternal): New method. Checks for shorthand CSS attributes
+ and parses them.
+ (parseBackgroundShorthand): New method. Parses the background
+ shorthand attribute.
+ * javax/swing/text/html/HTMLDocument.java
+ (HTMLReader.LinkAction): Made class a subclass of HiddenAction.
+ (HTMLReader.LinkAction.start): Implemented to load the linked
+ stylesheet.
+ (HTMLReader.LinkAction.end): Removed. This is not needed.
+ * javax/swing/text/html/StyleSheet.java
+ (CSSStyleSheetParserCallback.declaration): Push declaration
+ through CSS.addInternal() to parse shorthand attributes.
+ (addCSSAttribute): Push declaration through CSS.addInternal()
+ to parse shorthand attributes.
+ (importStyleSheet): Implemented. This adds a stylesheet from
+ an URL.
+ * javax/swing/text/html/TableView.java
+ (calculateColumnRequirements): Increase column index for
+ non CellView children to avoid endless loop.
+ * javax/swing/text/CompositeView.java
+ (setParent): Comparen with numChildren not with real arraylength.
+
+2006-11-11 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/beans/beancontext/BeanContextSupport.java
+ (getChildBeanContextChild): Implemented.
+
+2006-11-10 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/View.java
+ (updateLayout): Only repaint when needed.
+
+2006-11-10 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/util/Collections.java
+ (sort(List)): Minor API doc addition,
+ (sort(List, Comparator)): Likewise.
+
+2006-11-10 David Fu <fchoong@netbeans.jp>
+
+ * javax/swing/text/html/HTMLWriter.java
+ (traverse): Removed Classpath specific handling of implied
+ tags.
+ (traverseHtmlFragment): Removed Classpath specific handling of
+ implied tags.
+
+2006-11-10 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/ParagraphView.java
+ (Row.getMaximumSize): Removed. This method is not necessary.
+ * javax/swing/text/html/TableView.java
+ (CellView): Moved attribute init to setPropertiesFromAttributes().
+ (setPropertiesFromAttributes): Fetch attributes here.
+ (RowView.RowView): Documented.
+ (RowView.getMaximumSpan): Overridden to restrict the max span
+ in the Y direction.
+ (RowView.layoutMajorAxis): Correctly layout the spans.
+ (columnWidths): New field. Stores the width attributes of
+ the columns.
+ (calculateColumnRequirements): Added support for relative
+ (== percent) width attributes.
+ (calculateMajorAxisRequirements): Removed.
+ (calculateMinorAxisRequirements): Removed unnecessary code.
+ (getMaximumSpan): Overridden to restrict the table's width.
+ (layoutColumns): Documented. Implement more clever table layout,
+ i.e. for relative columns etc.
+ (layoutMinorAxis): Don't mark rows invalid.
+ (updateGrid): Added docs. Initialize column widths.
+
+2006-11-09 Roman Kennke <kennke@aicas.com>
+
+ * gnu/java/awt/peer/headless/HeadlessGraphicsEnvironment,
+ * gnu/java/awt/peer/headless/HeadlessToolkit: New classes.
+ Implement basic headless toolkit.
+ * java/awt/Toolkit.java
+ (getDefaultToolkit): Check headless property and create
+ headless toolkit when true.
+
+2006-11-09 Ingo Proetel <proetel@aicas.com>
+2006-11-09 Roman Kennke <kennke@aicas.com>
+
+ * gnu/java/awt/peer/swing/SwingButtonPeer.java
+ (SwingButton.button): New field.
+ (SwingButton.SwingButton): Added constructor.
+ (SwingButton.isShowing): Access button field instead of
+ the surrounding class.
+ (SwingButton.getParent): Access button field instead of
+ the surrounding class.
+ (SwingButtonPeer): Call new SwingButton constructor.
+ * gnu/java/awt/peer/swing/SwingComponent.java:
+ Several documentation updates.
+ * gnu/java/awt/peer/swing/SwingComponentPeer.java
+ (currentPaintEvents): New field.
+ (peerFont): New field.
+ (SwingComponentPeer): Initialize currentPaintEvents fields.
+ (coalescePaintEvents): Implemented.
+ (dispose): Unregister peer from heavyweight list of its container.
+ (getGraphics): Fetch graphics from parent component.
+ (handleEvent): Discard paint event if its coalesced.
+ (init): Register component with its container for proper painting.
+ (paint): Call peerPaint().
+ (peerPaint): Added argument that indicates if we should update.
+ Call paint or update on the actual AWT component.
+ (peerPaintComponent): New method. Paints the peer (Swing) component.
+ (setFont): Set peerFont field.
+ * gnu/java/awt/peer/swing/SwingContainerPeer.java
+ (backbuffer): New field.
+ (focusOwner): New field.
+ (heavyweightDescendents): New field.
+ (SwingContainerPeer): Take Container as argument. Don't call init
+ yet.
+ (addHeavyweightDescendent): New method.
+ (getFocusOwner): New helper method.
+ (getInsets): Delegate to insets().
+ (handleKeyEvent): Dispatch event to focus owner.
+ (handleMouseEvent): Dispatch to child component.
+ (isDoubleBuffering): New helper method.
+ (peerPaint): Overridden to implement container painting with
+ double buffering.
+ (peerPaintChildren): New method. Paints the descendents of this
+ container.
+ (removeHeavyweightDescendent): New helper method.
+ * gnu/java/awt/peer/swing/SwingFramePeer.java
+ (peerPaint): Removed.
+ (peerPaintComponent): Overridden to paint the menu bar.
+ * gnu/java/awt/peer/swing/SwingLabelPeer.java
+ (SwingLabel.label): New field.
+ (SwingLabel.SwingLabel): Added constructor with Label argument.
+ (SwingLabel.getGraphics): Implemented to fetch the graphics from
+ the actual AWT component.
+ (SwingLabel.getParent): Implemented to fetch the parent from
+ the AWT component.
+ (SwingLabel.isShowing): Access the label field.
+ (SwingLabelPeer): Set alignment from label.
+ * gnu/java/awt/peer/swing/SwingListPeer.java: New class.
+ * gnu/java/awt/peer/swing/SwingMenuBarPeer.java: Documentation
+ fixlet.
+ * gnu/java/awt/peer/swing/SwingPanelPeer.java:
+ Don't be a lighweight peer.
+ (SwingPanelPeer): Call init.
+ * gnu/java/awt/peer/swing/SwingTextAreaPeer.java: New class.
+ * gnu/java/awt/peer/swing/SwingTextFieldPeer.java
+ (SwingTextField.textField): New field.
+ (SwingTextField.SwingTextField): New constructor.
+ (SwingTextField.isShowing): Access field not enclosing class.
+ (SwingTextField.getGraphics): New method.
+ (SwingTextField.getParent): New method.
+ (SwingTextFieldPeer): Call new constructor.
+ (select): Renamed arguments.
+ * gnu/java/awt/peer/swing/SwingWindowPeer.java
+ (SwingWindowPeer): Call init.
+
+2006-11-09 Tania Bento <tbento@redhat.com>
+
+ * javax/swing/JLabel.java
+ (JLabel(Icon)): Changed documentation; Changed text to null.
+ (JLabel(Icon,int)): Likewise.
+ (JLabel(text)): Changed documenation.
+ (JLabel(text,int)): Likewise.
+ (JLabel(text,Icon,int)): Changed documentation; Throw
+ IllegalArgumentException if int is not one of LEFT, RIGHT,
+ CENTER, LEADING or TRAILING.
+
+2006-11-09 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/beans/beancontext/BeanContextSupport.java
+ (BeanContextSupport): Use correct dtime default,
+ (BeanContextSupport(BeanContext)): Likewise,
+ (BeanContextSupport(BeanContext, Locale)): Likewise, plus renamed
+ locale argument,
+ (BeanContextSupport(BeanContext, Locale, boolean)): Likewise,
+ (BeanContextSupport(BeanContext, Locale, boolean, boolean)): Likewise.
+
+2006-11-09 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/beans/beancontext/BeanContextSupport.java
+ (getBeanContextPeer): Implemented.
+
+2006-11-09 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/html/BlockView.java
+ (cssHeight): Removed.
+ (cssWidth): Removed.
+ (cssSpans): New field. Replaces the two fields above.
+ (BlockView): Allocate cssSpans array.
+ (layoutMinorAxis): Fetch and use child span, not this view's span.
+ (setCSSSpan): Adjusted to use cssSpans array.
+ (setPropertiesFromAttributes): Adjusted to use cssSpans array.
+
+2006-11-09 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/html/InlineView.java
+ (nowrap): New field.
+ (getBreakWeight): Add support for nowrap.
+ (setPropertiesFromAttributes): Fetch the nowrap setting.
+
+2006-11-09 Roman Kennke <kennke@aicas.com>
+
+ * gnu/javax/swing/text/html/css/CSSParser.java
+ (parseRuleset): Use new Selector class.
+ (parseValue): Parse multiple anys, not only one.
+ (main): Allow stylesheet be specified on the command line.
+ Use new Selector class.
+ * gnu/javax/swing/text/html/css/CSSParserCallback.java
+ (startStatement): Use Selector class.
+ * gnu/javax/swing/text/html/css/CSSScanner.java
+ (readName): Actually read a character in the loop to avoid
+ endless loop.
+ * gnu/javax/swing/text/html/css/Length.java
+ (getValue): Only multiply when we have a percentage value.
+ * gnu/javax/swing/text/html/css/Selector.java:
+ New class. Provides handling of CSS selectors.
+ * javax/swing/text/html/StyleSheet.java
+ (CSSStyle.PREC_AUTHOR_IMPORTANT): New constant field.
+ (CSSStyle.PREC_AUTHOR_NORMAL): New constant field.
+ (CSSStyle.PREC_NORM): New constant field.
+ (CSSStyle.PREC_UA): New constant field.
+ (CSSStyle.PREC_USER_IMPORTANT): New constant field.
+ (CSSStyle.precedence): New field.
+ (CSSStyle.priority): Removed.
+ (CSSStyle.selector): New field.
+ (CSSStyle.CSSStyle(int,Selector)): Initialize with Selector
+ and precendence.
+ (CSSStyle.compareTo): Adjusted to use the precedence and
+ specificity of the selector.
+ (CSSStyleSheetParserCallback.precedence): New field.
+ (CSSStyleSheetParserCallback.selector): Removed.
+ (CSSStyleSheetParserCallback.style): New field.
+ (CSSStyleSheetParserCallback.CSSStyleSheetParserCallback):
+ Initialize with precedence.
+ (CSSStyleSheetParserCallback.declaration): Don't look up
+ existing rule, simply create new one.
+ (CSSStyleSheetParserCallback.endStatement): Append style
+ to stylesheet.
+ (CSSStyleSheetParserCallback.startStatement): Use new Selector
+ class.
+ (css): Changed to be ArrayList.
+ (addRule): Create parser with author-normal precendence.
+ (getRule): Fixed implementation.
+ (loadRules): Create parser with UA precendence.
+ (resolveStyle): Use Selector class for resolving and matching
+ stylesheet rules.
+ (translateHTMLToCSS): Added mappings for a couple of HTML
+ attributes.
+
+2006-11-09 David Gilbert <david.gilbert@object-refinery.com>
+
+ Fixes bug #29770
+ * java/beans/SimpleBeanInfo.java
+ (loadImage): Check for nulls.
+
+2006-11-09 Robert Schuster <robertschuster@fsfe.org>
+
+ * native/jni/java-nio/gnu_java_nio_VMChannel.c:
+ (getpeername): Added 16 byte offset to memcpy operation.
+
+2006-11-09 Robert Schuster <robertschuster@fsfe.org>
+
+ * native/jni/java-nio/gnu_java_nio_VMChannel.c:
+ (getsockname): Added 16 byte offset to memcpy operation.
+
+2006-11-08 Mark Wielaard <mark@klomp.org>
+
+ Fixes bug #29754
+ * java/io/OutputStreamWriter.java
+ (OutputStreamWriter(OutputStream,Charset)): Set encodingName.
+ (OutputStreamWriter(OutputStream,CharsetEncoder)): Likewise.
+
+2006-11-08 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/html/HTMLEditorKit.java
+ (getParser): Use plain HTML_401F DTD.
+ * javax/swing/text/html/HTMLDocument.java
+ (HTMLReader.print): Removed method and all calls to it.
+ (HTMLReader.printBuffer): Removed method and all calls to it.
+ (HTMLReader.inImpliedParagraph): New field.
+ (HTMLReader.inParagraph): New field.
+ (HTMLReader.addContent): Create implied p-tag if necessary.
+ (HTMLReader.addSpecialElement): Create implied p-tag if necessary.
+ (HTMLReader.blockClose): Close implied p-tag if necessary.
+ (HTMLReader.blockOpen): Close implied p-tag if necessary.
+ * gnu/javax/swing/text/html/parser/HTML_401Swing.java: Removed.
+
+2006-11-08 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/html/HTMLEditorKit.java
+ (HTMLFactory.create): Removed mapping for TD tag. This
+ is done in TableView.
+ * javax/swing/text/html/TableView.java:
+ Implemented from scratch.
+
+2006-11-07 Roman Kennke <kennke@aicas.com>
+
+ * gnu/javax/swing/text/html/parser/support/Parser.java
+ (_handleText): Check if text content is actually allowed before
+ passing empty text fragments on to the parser callbacks.
+
+2006-11-07 Mark Wielaard <mark@klomp.org>
+
+ * gnu/java/net/protocol/jar/Handler.java (parseURL): Flatten jar
+ path.
+ (flat): New method.
+
+2006-11-07 Tania Bento <tbento@redhat.com>
+
+ * java/awt/FlowLayout.java
+ (getSize): If parent does not have a component, then a
+ different formula is used to calcuate the width.
+
+2006-11-07 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/html/HTMLEditorKit.java
+ (HTMLFactory.create): Include ListView.
+ * javax/swing/text/html/ListView.java
+ (paint): Removed comment.
+ * javax/swing/text/html/StyleSheet.java
+ (CSSStyle.priority): New field.
+ (CSSStyle.CSSStyle(int)): New constructor with priority.
+ (CSSStyle.compareTo): New method. Used for sorting the styles.
+ (CSSStyleSheetParserCallback.declaration): Store the style
+ with the complete selector.
+ (ListPainter.attributes): Renamed as field.
+ (ListPainter.styleSheet): New field.
+ (ListPainter.type): New field.
+ (ListPainter.ListPainter): Pass StyleSheet to constructor.
+ (ListPainter.paint): Provide simplistic implementation.
+ (getListPainter): Pass StyleSheet to constructor.
+ (resolveStyle): Fixed CSS style resolving.
+
+2006-11-07 Roman Kennke <kennke@aicas.com>
+
+ * gnu/javax/swing/text/html/css/BorderWidth.java:
+ New class. Handles CSS border width values.
+ * gnu/javax/swing/text/html/css/Length.java
+ (floatValue): Made protected so that BorderWidth can access it.
+ * javax/swing/text/html/CSS.java
+ (Attribute.BORDER_BOTTOM_COLOR): New static field.
+ (Attribute.BORDER_BOTTOM_STYLE): New static field.
+ (Attribute.BORDER_LEFT_COLOR): New static field.
+ (Attribute.BORDER_LEFT_STYLE): New static field.
+ (Attribute.BORDER_RIGHT_COLOR): New static field.
+ (Attribute.BORDER_RIGHT_STYLE): New static field.
+ (Attribute.BORDER_TOP_COLOR): New static field.
+ (Attribute.BORDER_TOP_STYLE): New static field.
+ (getValue): Added some mappings for the border color and
+ border width values.
+ * javax/swing/text/html/CSSBorder.java: New class. Implements
+ CSS borders.
+ * javax/swing/text/html/StyleSheet.java
+ (BoxPainter.background): New field.
+ (BoxPainter.border): New field.
+ (BoxPainter.bottomInset): Documented.
+ (BoxPainter.leftInset): Documented.
+ (BoxPainter.rightInset): Documented.
+ (BoxPainter.topInset): Documented.
+ (BoxPainter.BoxPainter): Added support for borders and background.
+ (BoxPainter.getInset): Add border insets.
+ (BoxPainter.paint): Implemented. Paints the background and the
+ CSS border.
+ (addRule): Be less picky about parse and IO exceptions.
+ (getBoxPainter): Adjust to new BoxPainter constructor.
+
+2006-11-07 Andreas <a.tobler@schweiz.org>
+
+ * examples/Makefile.am: Add rule to install the *.html files we use
+ in the Swing Demo.
+
+2006-11-06 Francis Kung <fkung@redhat.com>
+
+ * gnu/java/awt/peer/gtk/ComponentGraphics.java
+ (fillRect): Handle custom composites.
+ (drawRenderedImage): Handle custom composites.
+ (drawImage): Handle custom composites.
+ (createBuffer): New method.
+ (drawLine): Handle custom composites.
+ (drawComposite): New method.
+ (fill): Handle custom composites.
+ (getNativeCM): New method.
+ (drawGlyphVector): Handle custom composites.
+ (drawRect): Handle custom composites.
+ (draw): Handle custom composites.
+ * gnu/java/awt/peer/gtk/VolatileImageGraphics.java
+ (drawComposite): Unset composite during draw call, to prevent parent
+ from handling composite again.
+ * gnu/java/awt/peer/gtk/CairoGraphics2D.java
+ (getBufferCM): Added comments.
+ (getNativeCM): Made abstract.
+ (setComposite): Removed comments.
+
+2006-11-06 Roman Kennke <kennke@aicas.com>
+
+ * examples/gnu/classpath/examples/swing/HtmlDemo.java:
+ Fixed initial window size and start document.
+
+2006-11-06 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/html/HTMLDocument.java
+ (HTMLReader.addSpecialElement): Removed comment about
+ htmlAttributeSet.
+ (HTMLReader.handleComment): Create SimpleAttributeSet instead
+ of htmlAttributeSet.
+ * javax/swing/text/html/parser/DocumentParser.java
+ (gnuParser.handleStartTag): Use SimpleAttributeSet instead
+ of htmlAttributeSet.
+ * javax/swing/text/html/parser/ParserDelegator.java
+ (gnuParser.handleStartTag): Use SimpleAttributeSet instead
+ of htmlAttributeSet.
+ * gnu/javax/swing/text/html/parser/GnuParserDelegator.java
+ (gnuParser.handleStartTag): Use SimpleAttributeSet instead
+ of htmlAttributeSet.
+ * gnu/javax/swing/text/html/parser/support/Parser.java
+ (getAttributes): Return a SimpleAttributeSet.
+ (restOfTag): Don't set resolving parent here.
+
+2006-11-06 Tania Bento <tbento@redhat.com>
+
+ * java/awt/TextComponent.java
+ (setSelectionStart): Added check.
+
+2006-11-06 Tania Bento <tbento@redhat.com>
+
+ * java/awt/TextField.java
+ (minimumSize(int)): Check if minimum size has been previously
+ set and changed values of Dimension returned if peer == null.
+ (preferredSize(int)): Check if preferred size has been previously
+ set and changed values of Dimension returned if peer == null.
+
+2006-11-06 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/JTree.java
+ (TreeModelHandler.treeNodesRemoved): Implemented.
+ (TreeModelHandler.treeStructureChanged): Implemented.
+ (nodeStates): Made package private.
+
+2006-11-06 Francis Kung <fkung@redhat.com>
+
+ PR 29420
+ * javax/swing/JTree.java
+ (clearSelectionPathStates): New private method to clean up nodeStates.
+ (removeSelectionPath): Call clearSelectionPathStates().
+ (removeSelectionPaths): Call clearSelectionPathStates().
+ (removeSelectionRow): Call clearSelectionPathStates().
+ (setSelectionPath): Call clearSelectionPathStates().
+ (setSelectionPaths): Call clearSelectionPathStates().
+ (setSelectionRow): Call clearSelectionPathStates().
+
+2006-11-06 Ito Kazumitsu <kaz@maczuka.gcd.org>
+
+ Fixes bug #29703
+ * java/util/regex/Matcher.java(reset): Reset inputCharIndexed.
+
+2006-11-06 Roman Kennke <kennke@aicas.com>
+
+ * examples/gnu/classpath/examples/swing/HtmlDemo.java:
+ Changed to implement a minimalistic browser.
+ * examples/gnu/classpath/examples/swing/forms.html,
+ * examples/gnu/classpath/examples/swing/textstyles.html,
+ * examples/gnu/classpath/examples/swing/welcome.html:
+ Some example content.
+
+2006-11-06 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/ComponentView.java
+ (setParent): Lock the document and repaint the hosting
+ container.
+ * javax/swing/text/FlowView.java
+ (FlowStrategy.createView): Removed comment.
+ (FlowView): Initialize span with Short.MAX_VALUE.
+ (getFlowStart): Return 0 unconditionally.
+ (layout): Moved code around to make it more readable.
+ (loadChildren): Always set the parent.
+ * javax/swing/text/GlyphView.java
+ (DefaultGlyphPainter.fontMetrics): New field.
+ (DefaultGlyphPainter.getAscent): Use new helper method to
+ synchronize the font metrics.
+ (DefaultGlyphPainter.getBoundedPosition): Use new helper method
+ to synchronize the font metrics.
+ (DefaultGlyphPainter.getDescent): Use new helper method to
+ synchronize the font metrics.
+ (DefaultGlyphPainter.getHeight): Use new helper method to
+ synchronize the font metrics.
+ (DefaultGlyphPainter.getSpan): Use new helper method to
+ synchronize the font metrics.
+ (DefaultGlyphPainter.modelToView): Use new helper method to
+ synchronize the font metrics.
+ (DefaultGlyphPainter.updateFontMetrics): New helper method for
+ font metrics caching.
+ (DefaultGlyphPainter.viewToModel): Use new helper method to
+ synchronize the font metrics. Fixed view to model mapping.
+ * javax/swing/text/View.java
+ (removeAll): Pass null to replace().
+ (setParent): Only reparent children that have this view as parent.
+
+2006-11-05 Mark Wielaard <mark@klomp.org>
+
+ * include/gnu_java_net_VMPlainDatagramSocketImpl.h: Removed.
+ * include/gnu_java_nio_channels_FileChannelImpl.h: Removed.
+ * native/jni/java-net/gnu_java_net_VMPlainDatagramSocketImpl.c:
+ Removed.
+ * native/jni/java-nio/gnu_java_nio_channels_FileChannelImpl.c:
+ Removed.
+ * native/jni/java-nio/Makefile.am (libjavanio_la_SOURCES):
+ Remove gnu_java_nio_channels_FileChannelImpl.c.
+
+2006-11-03 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/html/BlockView.java
+ (attributes): New field.
+ (cssHeight): New field.
+ (cssWidth): New field.
+ (painter): New field.
+ (calculateMajorAxisRequirements): Overridden to account for
+ CSS settings.
+ (calculateMinorAxisRequirements): Overridden to account for
+ CSS settings.
+ (layoutMinorAxis): Overridden to account for CSS settings.
+ (changedUpdate): Formatting fixlet.
+ (constrainSize): New helper method.
+ (getAlignment): Fix alignment.
+ (getAttributes): Cache attributes for better performance.
+ (getStyleSheet): Fetch stylesheet from document rather than creating
+ a new one.
+ (paint): Remove comment.
+ (setCSSSpan): New helper method.
+ (setPropertiesFromAttributes): Implemented to fetch the
+ recognized properties.
+ * javax/swing/text/html/CSS.java
+ (getValue): Added mapping for width and height attributes.
+ * javax/swing/text/html/InlineView.java
+ (longestWord): New field.
+ (getLongestWord): New helper method.
+ (calculateLongestWord): New helper method.
+ (getMinimumSpan): Overridden to constrain the minimum span by the
+ longest word.
+ * javax/swing/text/html/ParagraphView.java
+ (cssHeight): New field.
+ (cssWidth): New field.
+ (calculateMinorAxisRequirements): Overridden to account for
+ CSS settings.
+ (setCSSSpan): New helper method.
+ (setPropertiesFromAttributes): Fetch CSS width and height. Added
+ null check.
+ * gnu/javax/swing/text/html/css/Length.java
+ (percentage): New field.
+ (Length): Determine percentage values.
+ (getValue(float)): New method for handling percentage values.
+ (isPercentage): New method.
+
2006-11-03 Tania Bento <tbento@redhat.com>
* java/awt/TextArea.java
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 43df1bdcf..6940bdf25 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -36,11 +36,14 @@ BUILT_SOURCES = $(EXAMPLE_ZIP)
# the png icons we use in some of the examples.
EXAMPLE_ICONS = $(srcdir)/gnu/classpath/examples/icons/*.png
+# the html pages we use in the swing demo example.
+EXAMPLE_HTML = $(srcdir)/gnu/classpath/examples/swing/*.html
+
# The example specific README files.
READMES = $(srcdir)/gnu/classpath/examples/CORBA/swing/README.html
# All the files we find "interesting"
-ALL_EXAMPLE_FILES = $(EXAMPLE_JAVA_FILES) $(EXAMPLE_C_FILES) $(EXAMPLE_CH_FILES) $(EXAMPLE_ICONS) $(READMES)
+ALL_EXAMPLE_FILES = $(EXAMPLE_JAVA_FILES) $(EXAMPLE_C_FILES) $(EXAMPLE_CH_FILES) $(EXAMPLE_ICONS) $(EXAMPLE_HTML) $(READMES)
# Some architecture independent data to be installed.
example_DATA = $(EXAMPLE_ZIP) README
@@ -100,6 +103,8 @@ dist-hook:
$(EXAMPLE_ZIP): $(EXAMPLE_JAVA_FILES)
mkdir -p classes/gnu/classpath/examples/icons
cp $(EXAMPLE_ICONS) classes/gnu/classpath/examples/icons
+ mkdir -p classes/gnu/classpath/examples/swing
+ cp $(EXAMPLE_HTML) classes/gnu/classpath/examples/swing
$(JCOMPILER) -d classes $(EXAMPLE_JAVA_FILES)
(cd classes; \
if test "$(ZIP)" != ""; then $(ZIP) -r ../$(EXAMPLE_ZIP) .; fi; \
diff --git a/examples/gnu/classpath/examples/swing/HtmlDemo.java b/examples/gnu/classpath/examples/swing/HtmlDemo.java
index d31d8cc9d..4cbf3ce47 100644
--- a/examples/gnu/classpath/examples/swing/HtmlDemo.java
+++ b/examples/gnu/classpath/examples/swing/HtmlDemo.java
@@ -40,21 +40,22 @@ package gnu.classpath.examples.swing;
import java.awt.BorderLayout;
import java.awt.Dimension;
-import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.io.IOException;
+import java.net.URL;
+import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
-import javax.swing.JTextArea;
+import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
-import javax.swing.text.AbstractDocument;
-import javax.swing.text.Element;
-import javax.swing.text.html.HTMLDocument;
+import javax.swing.event.HyperlinkEvent;
+import javax.swing.event.HyperlinkListener;
/**
* Parses and displays HTML content.
@@ -64,49 +65,36 @@ import javax.swing.text.html.HTMLDocument;
public class HtmlDemo extends JPanel
{
+ private class LoadActionListener
+ implements ActionListener
+ {
+
+ public void actionPerformed(ActionEvent event)
+ {
+ String urlStr = url.getText();
+ try
+ {
+ html.setPage(url.getText());
+ }
+ catch (IOException ex)
+ {
+ System.err.println("exception while loading: " + ex);
+ ex.printStackTrace();
+ }
+ }
+ }
+
/**
* Setting this to true causes the parsed element structure to be dumped.
*/
private static final boolean DEBUG = true;
- JTextPane html = new JTextPane();
-
- JTextArea text = new JTextArea("<html><body>\n"
+ /**
+ * The URL entry field.
+ */
+ JTextField url = new JTextField();
- + "<h1>H1 Headline</h1>\n"
- + "<h2>H2 Headline</h2>\n"
- + "<h3>H3 Headline</h3>\n"
- + "<h4>H4 Headline</h3>\n"
- + "<h5>H5 Headline</h5>\n"
- + "<h6>H6 Headline</h6>\n"
- + "<h1>CSS colors via font tag</h1>\n"
- + "<p>"
- + "<font color=\"maroon\">maroon</font>\n"
- + "<font color=\"red\">red</font>\n"
- + "<font color=\"orange\">orange</font>\n"
- + "<font color=\"yellow\">yellow</font>\n"
- + "<font color=\"olive\">olive</font>\n"
- + "<font color=\"purple\">purlpe</font>\n"
- + "<font color=\"fuchsia\">fuchsia</font>\n"
- + "<font color=\"white\">white</font>\n"
- + "<font color=\"lime\">lime</font>\n"
- + "<font color=\"green\">green</font>\n"
- + "<font color=\"navy\">navy</font>\n"
- + "<font color=\"blue\">blue</font>\n"
- + "<font color=\"aqua\">aqua</font>\n"
- + "<font color=\"teal\">teal</font>\n"
- + "<font color=\"black\">black</font>\n"
- + "<font color=\"silver\">silver</font>\n"
- + "<font color=\"gray\">gray</font>\n"
- + "</p>"
- + "<h1>Some HTML formatting tags</h1>\n"
- + "<p>Normal <b>Bold</b> <i>Italic</i> <b><i>Bold + Italic</i></b></p>\n"
- + "<p><big>Big</big> <em>Emphasized</em> <small>Small</small>\n"
- + "<strike>Strike</strike> <strong>Strong</strong> <u>Underline</u></p>\n"
- + "<p>Normal vs <sup>Superscript</sup> vs <sub>Subscript</sub> text</p>\n"
- + "</body></html>\n");
-
- JPanel buttons;
+ JTextPane html = new JTextPane();
int n;
@@ -116,7 +104,7 @@ public class HtmlDemo extends JPanel
html.setContentType("text/html"); // not now.
createContent();
}
-
+
/**
* Returns a panel with the demo content. The panel uses a BorderLayout(), and
* the BorderLayout.SOUTH area is empty, to allow callers to add controls to
@@ -126,158 +114,56 @@ public class HtmlDemo extends JPanel
private void createContent()
{
setLayout(new BorderLayout());
-
- JPanel center = new JPanel();
- GridLayout layout = new GridLayout();
- layout.setRows(2);
- center.setLayout(layout);
- center.add(new JScrollPane(text));
- center.add(new JScrollPane(html));
-
- buttons = new JPanel();
-
- JButton parse = new JButton("parse");
- parse.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent event)
- {
- String t = text.getText();
- System.out.println("HtmlDemo.java.createContent:Parsing started");
- html.setText(t);
- System.out.println("HtmlDemo.java.createContent:Parsing completed");
- if (DEBUG)
- ((AbstractDocument) html.getDocument()).dump(System.out);
- }
- });
-
- buttons.add(parse);
-
- JButton insertBeforeEnd = new JButton("before end");
- insertBeforeEnd.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent event)
- {
- HTMLDocument doc = (HTMLDocument) html.getDocument();
- Element el = doc.getElement("insertHere");
- System.out.println("Element found:"+el);
- try
- {
- doc.insertBeforeEnd(el,"before end "+(n++));
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- }
- });
-
- JButton insertBeforeStart = new JButton("before start");
- insertBeforeStart.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent event)
- {
- HTMLDocument doc = (HTMLDocument) html.getDocument();
- Element el = doc.getElement("insertHere");
- System.out.println("Element found:"+el);
- try
- {
- doc.insertBeforeStart(el,"before start "+(n++));
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- }
- });
-
- JButton insertAfterEnd = new JButton("after end");
- insertAfterEnd.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent event)
- {
- HTMLDocument doc = (HTMLDocument) html.getDocument();
- Element el = doc.getElement("insertHere");
- System.out.println("Element found:"+el);
- try
- {
- doc.insertAfterEnd(el,"after end "+(n++));
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- }
- });
-
- JButton insertAfterStart = new JButton("after start");
- insertAfterStart.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent event)
- {
- HTMLDocument doc = (HTMLDocument) html.getDocument();
- Element el = doc.getElement("insertHere");
- System.out.println("Element found:"+el);
- try
- {
- doc.insertAfterStart(el,"after start "+(n++));
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- }
- });
-
- JButton setInner = new JButton("inner");
- setInner.addActionListener(new ActionListener()
+ html.setEditable(false);
+ html.addHyperlinkListener(new HyperlinkListener()
+ {
+
+ public void hyperlinkUpdate(HyperlinkEvent event)
{
- public void actionPerformed(ActionEvent event)
+ URL u = event.getURL();
+ if (u != null)
{
- HTMLDocument doc = (HTMLDocument) html.getDocument();
- Element el = doc.getElement("insertHere");
- System.out.println("Element found:"+el);
+ url.setText(u.toString());
try
{
- doc.setInnerHTML(el,"inner "+(n++));
+ html.setPage(u);
}
- catch (Exception e)
+ catch (IOException ex)
{
- e.printStackTrace();
+ ex.printStackTrace();
}
}
- });
-
- JButton setOuter = new JButton("outer");
- setOuter.addActionListener(new ActionListener()
+ }
+
+ });
+
+ JScrollPane scroller = new JScrollPane(html);
+ JPanel urlPanel = new JPanel();
+ urlPanel.setLayout(new BoxLayout(urlPanel, BoxLayout.X_AXIS));
+ url.setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
+ LoadActionListener action = new LoadActionListener();
+ url.addActionListener(action);
+ urlPanel.add(url);
+ JButton loadButton = new JButton("go");
+ urlPanel.add(loadButton);
+ loadButton.addActionListener(action);
+ add(urlPanel, BorderLayout.NORTH);
+ add(scroller, BorderLayout.CENTER);
+
+ // Load start page.
+ URL startpage = getClass().getResource("welcome.html");
+ try
{
- public void actionPerformed(ActionEvent event)
- {
- HTMLDocument doc = (HTMLDocument) html.getDocument();
- Element el = doc.getElement("insertHere");
- System.out.println("Element found:"+el);
- try
- {
- doc.setOuterHTML(el,"outer "+(n++));
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- }
- });
-
-
- buttons.add(insertBeforeStart);
- buttons.add(insertAfterStart);
- buttons.add(insertBeforeEnd);
- buttons.add(insertAfterEnd);
+ html.setPage(startpage);
+ url.setText(startpage.toString());
+ }
+ catch (IOException ex)
+ {
+ System.err.println("couldn't load page: " + startpage);
+ }
- buttons.add(setInner);
- buttons.add(setOuter);
-
- add(center, BorderLayout.CENTER);
- add(buttons, BorderLayout.SOUTH);
+ setPreferredSize(new Dimension(600, 400));
}
/**
@@ -294,18 +180,6 @@ public class HtmlDemo extends JPanel
public void run()
{
HtmlDemo demo = new HtmlDemo();
-
- JButton exit = new JButton("exit");
- exit.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent event)
- {
- System.exit(0);
- }
- });
-
- demo.buttons.add(exit);
-
JFrame frame = new JFrame();
frame.getContentPane().add(demo);
frame.setSize(new Dimension(700, 480));
diff --git a/examples/gnu/classpath/examples/swing/forms.html b/examples/gnu/classpath/examples/swing/forms.html
new file mode 100644
index 000000000..2cfdb4bcc
--- /dev/null
+++ b/examples/gnu/classpath/examples/swing/forms.html
@@ -0,0 +1,69 @@
+<!-- welcome.html -- Some HTML stuff to show Swing HTML
+ 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. -->
+
+<html>
+
+ <head>
+ <title>HTML text styles</title>
+ </head>
+ <body>
+ <a href="welcome.html">Back to start page</a>
+ <h1>Some form elements</h1>
+ <h2>Textarea</h2>
+ <textarea cols="30" rows="5">
+ Hello GNU Classpath world. This text should show up in a text area
+ that has a size of 30 columns and 5 rows
+ </textarea>
+
+ <h2>Buttons</h2>
+ <p>
+ <input type="submit"></input>
+ <input type="reset"></input>
+ <input type="button" value="Some button"></input>
+ </p>
+
+ <h2>Checkboxes and Radiobuttons</h2>
+ <p>
+ <input type="checkbox">Check this!</input>
+ <input type="checkbox">Or this</input>
+ </p>
+ <p>
+ <input type="radio">A radio button</input>
+ <input type="radio">Another radio</input>
+ </p>
+ </body>
+</html> \ No newline at end of file
diff --git a/examples/gnu/classpath/examples/swing/textstyles.html b/examples/gnu/classpath/examples/swing/textstyles.html
new file mode 100644
index 000000000..786e18b77
--- /dev/null
+++ b/examples/gnu/classpath/examples/swing/textstyles.html
@@ -0,0 +1,78 @@
+<!-- welcome.html -- Some HTML stuff to show Swing HTML
+ 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. -->
+
+<html>
+
+ <head>
+ <title>HTML text styles</title>
+ </head>
+ <body>
+ <a href="welcome.html">Back to start page</a>
+ <h1>Colors</h1>
+ <p>The following are the 16 named colors in HTML. Of course you can also
+ use all RGB colors by specifying a value in the <code>#RRGGBB</code>
+ notation.</p>
+ <p>
+ <font color="black">Black</font>, <font color="gray">Gray</font>,
+ <font color="maroon">Maroon</font>, <font color="red">Red</font>,
+ <font color="green">Green</font>, <font color="lime">Lime</font>,
+ <font color="olive">Olive</font>, <font color="yellow">Yellow</font>,
+ <font color="navy">Navy</font>, <font color="blue">Blue</font>,
+ <font color="purple">Purple</font>, <font color="fuchsia">Fuchsia</font>,
+ <font color="teal">Teal</font>, <font color="aque">Aqua</font>,
+ <font color="silver">Silver</font>, <font color="white">White</font></p>
+ <h1>Font styles</h1>
+ <p>The following lists the logical and physical font styles that can be set
+ by certain HTML tags</p>
+ <p>
+ <!--<abbr>Abbreviation</abbr>, <acronym>Acronym</acronym>,-->
+ <address>Address</address>, <b>Bold</b>, <big>Big</big>,
+ <cite>Citation</cite>, <code>Code</code>, <del>Deleted</del>,
+ <em>Emphasized<em>, <i>Italic</i>, <ins>Inserted</ins>, <q>Quote</q>,
+ <s>Stroke-Through</s>, <samp>Example</samp>, <small>Small</small>,
+ <strike>Strike</strike>, <strong>Strong</strong>, <sub>Subscript</sub>,
+ <sup>Superscript</sup>, <u>Underlined</u>, <var>Variable</var>
+ </p>
+ <h1>Header Level 1</h1>
+ <h2>Header Level 2</h2>
+ <h3>Header Level 3</h3>
+ <h4>Header Level 4</h4>
+ <h5>Header Level 5</h5>
+ <h6>Header Level 6</h6>
+ <center>Some centered Text</center>
+ </body>
+</html> \ No newline at end of file
diff --git a/examples/gnu/classpath/examples/swing/welcome.html b/examples/gnu/classpath/examples/swing/welcome.html
new file mode 100644
index 000000000..62fb51429
--- /dev/null
+++ b/examples/gnu/classpath/examples/swing/welcome.html
@@ -0,0 +1,52 @@
+<!-- welcome.html -- Some HTML stuff to show Swing HTML
+ 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. -->
+
+<html>
+ <head>
+ <title>GNU Classpath HTML Browser</title>
+ </head>
+ <body>
+ <img src="../icons/badge.png">
+ <h1>Welcome to GNU Classpath</h1>
+ <p>These pages are here to demonstrate the HTML rendering capabilities
+ of GNU Classpath's Swing.</p>
+ <ul>
+ <li><a href="textstyles.html">Text styles</li>
+ <li><a href="forms.html">Form elements</li>
+ </ul>
+ </body>
+</html> \ No newline at end of file
diff --git a/gnu/java/awt/peer/gtk/CairoGraphics2D.java b/gnu/java/awt/peer/gtk/CairoGraphics2D.java
index 7f55747c6..ce3041d73 100644
--- a/gnu/java/awt/peer/gtk/CairoGraphics2D.java
+++ b/gnu/java/awt/peer/gtk/CairoGraphics2D.java
@@ -985,10 +985,6 @@ public abstract class CairoGraphics2D extends Graphics2D
if (sm != null)
sm.checkPermission(new AWTPermission("readDisplayPixels"));
- // FIXME: implement general Composite support
- //throw new java.lang.UnsupportedOperationException();
- // this is in progress! yay!
- //compCtx = comp.createContext(getNativeCM(), getNativeCM(), hints);
compCtx = comp.createContext(getBufferCM(), getNativeCM(), hints);
}
}
@@ -1000,18 +996,17 @@ public abstract class CairoGraphics2D extends Graphics2D
*
* @return ColorModel the ColorModel of native data in this peer
*/
- /* protected abstract ColorModel getNativeCM(); */
- protected ColorModel getNativeCM()
- {
- // This stub should be removed and the method made abstract once I'm done
- // implementing custom composites across all the peers... but we need it
- // for now, so that the build doesn't break.
- return null;
- }
+ protected abstract ColorModel getNativeCM();
- // This may be overridden by some subclasses
+ /**
+ * Returns the Color Model describing the buffer that this peer uses
+ * for custom composites.
+ *
+ * @return ColorModel the ColorModel of the composite buffer in this peer.
+ */
protected ColorModel getBufferCM()
{
+ // This may be overridden by some subclasses
return getNativeCM();
}
diff --git a/gnu/java/awt/peer/gtk/ComponentGraphics.java b/gnu/java/awt/peer/gtk/ComponentGraphics.java
index d9d173118..c8ec2c95e 100644
--- a/gnu/java/awt/peer/gtk/ComponentGraphics.java
+++ b/gnu/java/awt/peer/gtk/ComponentGraphics.java
@@ -38,22 +38,31 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
+import gnu.classpath.Pointer;
+
+import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
+import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.Toolkit;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
+import java.awt.geom.Line2D;
+import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
+import java.awt.image.Raster;
import java.awt.image.RenderedImage;
-import gnu.classpath.Pointer;
+import java.awt.image.WritableRaster;
+import java.util.Hashtable;
/**
* ComponentGraphics - context for drawing directly to a component,
@@ -67,6 +76,7 @@ public class ComponentGraphics extends CairoGraphics2D
private GtkComponentPeer component;
protected long cairo_t;
+ private BufferedImage buffer, componentBuffer;
private static ThreadLocal hasLock = new ThreadLocal();
private static Integer ONE = Integer.valueOf(1);
@@ -227,7 +237,20 @@ public class ComponentGraphics extends CairoGraphics2D
lock();
try
{
- super.draw(s);
+ if (comp == null || comp instanceof AlphaComposite)
+ super.draw(s);
+
+ else
+ {
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setStroke(this.getStroke());
+ g2d.setColor(this.getColor());
+ g2d.draw(s);
+
+ drawComposite(s.getBounds2D(), null);
+ }
}
finally
{
@@ -240,7 +263,20 @@ public class ComponentGraphics extends CairoGraphics2D
lock();
try
{
- super.fill(s);
+ if (comp == null || comp instanceof AlphaComposite)
+ super.fill(s);
+
+ else
+ {
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setPaint(this.getPaint());
+ g2d.setColor(this.getColor());
+ g2d.fill(s);
+
+ drawComposite(s.getBounds2D(), null);
+ }
}
finally
{
@@ -253,7 +289,19 @@ public class ComponentGraphics extends CairoGraphics2D
lock();
try
{
- super.drawRenderedImage(image, xform);
+ if (comp == null || comp instanceof AlphaComposite)
+ super.drawRenderedImage(image, xform);
+
+ else
+ {
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setRenderingHints(this.getRenderingHints());
+ g2d.drawRenderedImage(image, xform);
+
+ drawComposite(buffer.getRaster().getBounds(), null);
+ }
}
finally
{
@@ -268,7 +316,44 @@ public class ComponentGraphics extends CairoGraphics2D
lock();
try
{
- rv = super.drawImage(img, xform, bgcolor, obs);
+ if (comp == null || comp instanceof AlphaComposite)
+ rv = super.drawImage(img, xform, bgcolor, obs);
+
+ else
+ {
+ // Get buffered image of source
+ if( !(img instanceof BufferedImage) )
+ {
+ ImageProducer source = img.getSource();
+ if (source == null)
+ return false;
+ img = Toolkit.getDefaultToolkit().createImage(source);
+ }
+ BufferedImage bImg = (BufferedImage) img;
+
+ // Find translated bounds
+ Point2D origin = new Point2D.Double(bImg.getMinX(), bImg.getMinY());
+ Point2D pt = new Point2D.Double(bImg.getWidth() + bImg.getMinX(),
+ bImg.getHeight() + bImg.getMinY());
+ if (xform != null)
+ {
+ origin = xform.transform(origin, origin);
+ pt = xform.transform(pt, pt);
+ }
+
+ // Create buffer and draw image
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setRenderingHints(this.getRenderingHints());
+ g2d.drawImage(img, xform, obs);
+
+ // Perform compositing
+ rv = drawComposite(new Rectangle2D.Double(origin.getX(),
+ origin.getY(),
+ pt.getX(), pt.getY()),
+ obs);
+ }
}
finally
{
@@ -282,7 +367,23 @@ public class ComponentGraphics extends CairoGraphics2D
lock();
try
{
- super.drawGlyphVector(gv, x, y);
+ if (comp == null || comp instanceof AlphaComposite)
+ super.drawGlyphVector(gv, x, y);
+
+ else
+ {
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setPaint(this.getPaint());
+ g2d.setStroke(this.getStroke());
+ g2d.drawGlyphVector(gv, x, y);
+
+ Rectangle2D bounds = gv.getLogicalBounds();
+ bounds = new Rectangle2D.Double(x + bounds.getX(), y + bounds.getY(),
+ bounds.getWidth(), bounds.getHeight());
+ drawComposite(bounds, null);
+ }
}
finally
{
@@ -384,7 +485,11 @@ public class ComponentGraphics extends CairoGraphics2D
lock();
try
{
- super.drawLine(x1, y1, x2, y2);
+ if (comp == null || comp instanceof AlphaComposite)
+ super.drawLine(x1, y1, x2, y2);
+
+ else
+ draw(new Line2D.Double(x1, y1, x2, y2));
}
finally
{
@@ -397,7 +502,11 @@ public class ComponentGraphics extends CairoGraphics2D
lock();
try
{
- super.drawRect(x, y, width, height);
+ if (comp == null || comp instanceof AlphaComposite)
+ super.drawRect(x, y, width, height);
+
+ else
+ draw(new Rectangle2D.Double(x, y, width, height));
}
finally
{
@@ -410,7 +519,11 @@ public class ComponentGraphics extends CairoGraphics2D
lock();
try
{
- super.fillRect(x, y, width, height);
+ if (comp == null || comp instanceof AlphaComposite)
+ super.fillRect(x, y, width, height);
+
+ else
+ fill(new Rectangle2D.Double(x, y, width, height));
}
finally
{
@@ -431,5 +544,99 @@ public class ComponentGraphics extends CairoGraphics2D
}
}
+
+ private boolean drawComposite(Rectangle2D bounds, ImageObserver observer)
+ {
+ // Clip source to visible areas that need updating
+ Rectangle2D clip = this.getClipBounds();
+ Rectangle2D.intersect(bounds, clip, bounds);
+ clip = new Rectangle(buffer.getMinX(), buffer.getMinY(),
+ buffer.getWidth(), buffer.getHeight());
+ Rectangle2D.intersect(bounds, clip, bounds);
+
+ BufferedImage buffer2 = buffer;
+ if (!bounds.equals(buffer2.getRaster().getBounds()))
+ buffer2 = buffer2.getSubimage((int)bounds.getX(), (int)bounds.getY(),
+ (int)bounds.getWidth(),
+ (int)bounds.getHeight());
+
+ // Get destination clip to bounds
+ double[] points = new double[] {bounds.getX(), bounds.getY(),
+ bounds.getMaxX(), bounds.getMaxY()};
+ transform.transform(points, 0, points, 0, 2);
+
+ Rectangle2D deviceBounds = new Rectangle2D.Double(points[0], points[1],
+ points[2] - points[0],
+ points[3] - points[1]);
+
+ Rectangle2D.intersect(deviceBounds, this.getClipInDevSpace(), deviceBounds);
+
+ // Get current image on the component
+ unlock();
+ GtkImage img = grab(component);
+ Graphics gr = componentBuffer.createGraphics();
+ gr.drawImage(img, 0, 0, null);
+ gr.dispose();
+ lock();
+
+ BufferedImage cBuffer = componentBuffer;
+ if (!deviceBounds.equals(cBuffer.getRaster().getBounds()))
+ cBuffer = cBuffer.getSubimage((int)deviceBounds.getX(),
+ (int)deviceBounds.getY(),
+ (int)deviceBounds.getWidth(),
+ (int)deviceBounds.getHeight());
+
+ // Perform actual composite operation
+ compCtx.compose(buffer2.getRaster(), cBuffer.getRaster(),
+ cBuffer.getRaster());
+
+ // This MUST call directly into the "action" method in CairoGraphics2D,
+ // not one of the wrappers, to ensure that the composite isn't processed
+ // more than once!
+ boolean rv = super.drawImage(cBuffer,
+ AffineTransform.getTranslateInstance(bounds.getX(),
+ bounds.getY()),
+ null, null);
+ return rv;
+ }
+
+ private void createBuffer()
+ {
+ if (buffer == null)
+ {
+ WritableRaster rst;
+ rst = Raster.createWritableRaster(GtkVolatileImage.createGdkSampleModel(component.awtComponent.getWidth(),
+ component.awtComponent.getHeight()),
+ new Point(0,0));
+
+ buffer = new BufferedImage(GtkVolatileImage.gdkColorModel, rst,
+ GtkVolatileImage.gdkColorModel.isAlphaPremultiplied(),
+ new Hashtable());
+ }
+ else
+ {
+ Graphics2D g2d = ((Graphics2D)buffer.getGraphics());
+
+ g2d.setBackground(new Color(0,0,0,0));
+ g2d.clearRect(0, 0, buffer.getWidth(), buffer.getHeight());
+ }
+
+ if (componentBuffer == null)
+ {
+ WritableRaster rst;
+ rst = Raster.createWritableRaster(GtkVolatileImage.createGdkSampleModel(component.awtComponent.getWidth(),
+ component.awtComponent.getHeight()),
+ new Point(0,0));
+
+ componentBuffer = new BufferedImage(GtkVolatileImage.gdkColorModel, rst,
+ GtkVolatileImage.gdkColorModel.isAlphaPremultiplied(),
+ new Hashtable());
+ }
+ }
+
+ protected ColorModel getNativeCM()
+ {
+ return GtkVolatileImage.gdkColorModel;
+ }
}
diff --git a/gnu/java/awt/peer/gtk/GtkImageConsumer.java b/gnu/java/awt/peer/gtk/GtkImageConsumer.java
index f1a74b8cc..53e97bb1a 100644
--- a/gnu/java/awt/peer/gtk/GtkImageConsumer.java
+++ b/gnu/java/awt/peer/gtk/GtkImageConsumer.java
@@ -42,6 +42,7 @@ import java.awt.image.ColorModel;
import java.awt.image.ImageConsumer;
import java.awt.image.ImageProducer;
import java.awt.image.MemoryImageSource;
+import java.nio.ByteOrder;
import java.util.Hashtable;
/**
@@ -103,7 +104,7 @@ public class GtkImageConsumer implements ImageConsumer
scansize);
}
- public synchronized void setPixels (int x, int y, int width, int height,
+ public synchronized void setPixels (int x, int y, int width, int height,
ColorModel cm, int[] pixels,
int offset, int scansize)
{
@@ -117,18 +118,34 @@ public class GtkImageConsumer implements ImageConsumer
width);
else
{
- for (int i = 0; i < height; i++)
- for (int j = 0; j < width; j++)
- {
- // get in AARRGGBB and convert to AABBGGRR
- int pix = cm.getRGB(pixels[offset + (i * scansize) + x + j]);
- byte b = (byte)(pix & 0xFF);
- byte r = (byte)(((pix & 0x00FF0000) >> 16) & 0xFF);
- pix &= 0xFF00FF00;
- pix |= ((b & 0xFF) << 16);
- pix |= (r & 0xFF);
- pixelCache[(y + i) * this.width + x + j] = pix;
- }
+ if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN)
+ {
+ for (int i = 0; i < height; i++)
+ for (int j = 0; j < width; j++)
+ {
+ // get in RRGGBBAA and convert to AARRGGBB
+ int pix = cm.getRGB(pixels[offset + (i * scansize) + x + j]);
+ int a = ((pix & 0xFF000000) >> 24) & 0xFF;
+ int rgb = (pix & 0x00FFFFFF) << 8;
+ pix = rgb | a;
+ pixelCache[(y + i) * this.width + x + j] = pix;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < height; i++)
+ for (int j = 0; j < width; j++)
+ {
+ // get in AARRGGBB and convert to AABBGGRR
+ int pix = cm.getRGB(pixels[offset + (i * scansize) + x + j]);
+ byte b = (byte)(pix & 0xFF);
+ byte r = (byte)(((pix & 0x00FF0000) >> 16) & 0xFF);
+ pix &= 0xFF00FF00;
+ pix |= ((b & 0xFF) << 16);
+ pix |= (r & 0xFF);
+ pixelCache[(y + i) * this.width + x + j] = pix;
+ }
+ }
}
}
diff --git a/gnu/java/awt/peer/gtk/VolatileImageGraphics.java b/gnu/java/awt/peer/gtk/VolatileImageGraphics.java
index 3a9f9d693..62dbb45d8 100644
--- a/gnu/java/awt/peer/gtk/VolatileImageGraphics.java
+++ b/gnu/java/awt/peer/gtk/VolatileImageGraphics.java
@@ -40,6 +40,7 @@ package gnu.java.awt.peer.gtk;
import java.awt.AlphaComposite;
import java.awt.Color;
+import java.awt.Composite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
@@ -269,10 +270,13 @@ public class VolatileImageGraphics extends ComponentGraphics
// This MUST call directly into the "action" method in CairoGraphics2D,
// not one of the wrappers, to ensure that the composite isn't processed
// more than once!
+ Composite oldComp = comp; // so that ComponentGraphics doesn't
+ comp = null; // process the composite again
boolean rv = super.drawImage(buffer2,
AffineTransform.getTranslateInstance(bounds.getX(),
bounds.getY()),
null, null);
+ comp = oldComp;
return rv;
}
diff --git a/gnu/java/awt/peer/headless/HeadlessGraphicsEnvironment.java b/gnu/java/awt/peer/headless/HeadlessGraphicsEnvironment.java
new file mode 100644
index 000000000..77ec4bf00
--- /dev/null
+++ b/gnu/java/awt/peer/headless/HeadlessGraphicsEnvironment.java
@@ -0,0 +1,88 @@
+/* HeadlessGraphicsEnvironment.java -- A graphics environment for headless mode
+ 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 gnu.java.awt.peer.headless;
+
+import gnu.java.awt.java2d.RasterGraphics;
+
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.HeadlessException;
+import java.awt.image.BufferedImage;
+import java.util.Locale;
+
+public class HeadlessGraphicsEnvironment
+ extends GraphicsEnvironment
+{
+
+ public Graphics2D createGraphics(BufferedImage image)
+ {
+ return new RasterGraphics(image.getRaster(), image.getColorModel());
+ }
+
+ public Font[] getAllFonts()
+ {
+ // FIXME: Implement.
+ return null;
+ }
+
+ public String[] getAvailableFontFamilyNames()
+ {
+ // FIXME: Implement.
+ return null;
+ }
+
+ public String[] getAvailableFontFamilyNames(Locale l)
+ {
+ // FIXME: Implement.
+ return null;
+ }
+
+ public GraphicsDevice getDefaultScreenDevice()
+ {
+ throw new HeadlessException();
+ }
+
+ public GraphicsDevice[] getScreenDevices()
+ {
+ throw new HeadlessException();
+ }
+
+}
diff --git a/gnu/java/awt/peer/headless/HeadlessToolkit.java b/gnu/java/awt/peer/headless/HeadlessToolkit.java
new file mode 100644
index 000000000..96798c9e9
--- /dev/null
+++ b/gnu/java/awt/peer/headless/HeadlessToolkit.java
@@ -0,0 +1,371 @@
+/* HeadlessToolkit.java -- A toolkit for headless mode
+ 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 gnu.java.awt.peer.headless;
+
+import gnu.java.awt.ClasspathToolkit;
+import gnu.java.awt.EmbeddedWindow;
+import gnu.java.awt.peer.ClasspathFontPeer;
+import gnu.java.awt.peer.EmbeddedWindowPeer;
+
+import java.awt.AWTException;
+import java.awt.Button;
+import java.awt.Canvas;
+import java.awt.Checkbox;
+import java.awt.CheckboxMenuItem;
+import java.awt.Choice;
+import java.awt.Dialog;
+import java.awt.Dimension;
+import java.awt.EventQueue;
+import java.awt.FileDialog;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Frame;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.HeadlessException;
+import java.awt.Image;
+import java.awt.Label;
+import java.awt.List;
+import java.awt.Menu;
+import java.awt.MenuBar;
+import java.awt.MenuItem;
+import java.awt.Panel;
+import java.awt.PopupMenu;
+import java.awt.PrintJob;
+import java.awt.ScrollPane;
+import java.awt.Scrollbar;
+import java.awt.TextArea;
+import java.awt.TextField;
+import java.awt.Window;
+import java.awt.datatransfer.Clipboard;
+import java.awt.dnd.DragGestureEvent;
+import java.awt.dnd.peer.DragSourceContextPeer;
+import java.awt.im.InputMethodHighlight;
+import java.awt.image.ColorModel;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.peer.ButtonPeer;
+import java.awt.peer.CanvasPeer;
+import java.awt.peer.CheckboxMenuItemPeer;
+import java.awt.peer.CheckboxPeer;
+import java.awt.peer.ChoicePeer;
+import java.awt.peer.DialogPeer;
+import java.awt.peer.FileDialogPeer;
+import java.awt.peer.FontPeer;
+import java.awt.peer.FramePeer;
+import java.awt.peer.LabelPeer;
+import java.awt.peer.ListPeer;
+import java.awt.peer.MenuBarPeer;
+import java.awt.peer.MenuItemPeer;
+import java.awt.peer.MenuPeer;
+import java.awt.peer.PanelPeer;
+import java.awt.peer.PopupMenuPeer;
+import java.awt.peer.RobotPeer;
+import java.awt.peer.ScrollPanePeer;
+import java.awt.peer.ScrollbarPeer;
+import java.awt.peer.TextAreaPeer;
+import java.awt.peer.TextFieldPeer;
+import java.awt.peer.WindowPeer;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Map;
+import java.util.Properties;
+
+public class HeadlessToolkit
+ extends ClasspathToolkit
+{
+
+ /**
+ * The graphics environment for headless graphics.
+ */
+ private HeadlessGraphicsEnvironment graphicsEnv;
+
+ public void beep()
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public int checkImage(Image image, int width, int height,
+ ImageObserver observer)
+ {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ protected ButtonPeer createButton(Button target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected CanvasPeer createCanvas(Canvas target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected CheckboxPeer createCheckbox(Checkbox target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected ChoicePeer createChoice(Choice target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected DialogPeer createDialog(Dialog target)
+ {
+ throw new HeadlessException();
+ }
+
+ public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent e)
+ {
+ throw new HeadlessException();
+ }
+
+ protected FileDialogPeer createFileDialog(FileDialog target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected FramePeer createFrame(Frame target)
+ {
+ throw new HeadlessException();
+ }
+
+ public Image createImage(String filename)
+ {
+ // FIXME: Implement.
+ return null;
+ }
+
+ public Image createImage(URL url)
+ {
+ // FIXME: Implement.
+ return null;
+ }
+
+ public Image createImage(ImageProducer producer)
+ {
+ // FIXME: Implement.
+ return null;
+ }
+
+ public Image createImage(byte[] data, int offset, int len)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ protected LabelPeer createLabel(Label target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected ListPeer createList(List target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected MenuPeer createMenu(Menu target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected MenuBarPeer createMenuBar(MenuBar target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected MenuItemPeer createMenuItem(MenuItem target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected PanelPeer createPanel(Panel target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected PopupMenuPeer createPopupMenu(PopupMenu target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected ScrollPanePeer createScrollPane(ScrollPane target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected ScrollbarPeer createScrollbar(Scrollbar target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected TextAreaPeer createTextArea(TextArea target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected TextFieldPeer createTextField(TextField target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected WindowPeer createWindow(Window target)
+ {
+ throw new HeadlessException();
+ }
+
+ public ColorModel getColorModel()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public String[] getFontList()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public FontMetrics getFontMetrics(Font name)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ protected FontPeer getFontPeer(String name, int style)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public Image getImage(String name)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public Image getImage(URL url)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public PrintJob getPrintJob(Frame frame, String title, Properties props)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public int getScreenResolution()
+ {
+ throw new HeadlessException();
+ }
+
+ public Dimension getScreenSize()
+ {
+ throw new HeadlessException();
+ }
+
+ public Clipboard getSystemClipboard()
+ {
+ throw new HeadlessException();
+ }
+
+ protected EventQueue getSystemEventQueueImpl()
+ {
+ throw new HeadlessException();
+ }
+
+ public Map mapInputMethodHighlight(InputMethodHighlight highlight)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public boolean prepareImage(Image image, int width, int height,
+ ImageObserver observer)
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public void sync()
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public EmbeddedWindowPeer createEmbeddedWindow(EmbeddedWindow w)
+ {
+ throw new HeadlessException();
+ }
+
+ public Font createFont(int format, InputStream stream)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public RobotPeer createRobot(GraphicsDevice screen) throws AWTException
+ {
+ throw new HeadlessException();
+ }
+
+ public ClasspathFontPeer getClasspathFontPeer(String name, Map attrs)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public GraphicsEnvironment getLocalGraphicsEnvironment()
+ {
+ if (graphicsEnv == null)
+ graphicsEnv = new HeadlessGraphicsEnvironment();
+ return graphicsEnv;
+ }
+
+}
diff --git a/gnu/java/awt/peer/swing/SwingButtonPeer.java b/gnu/java/awt/peer/swing/SwingButtonPeer.java
index 2357fcbfb..531d6f2db 100644
--- a/gnu/java/awt/peer/swing/SwingButtonPeer.java
+++ b/gnu/java/awt/peer/swing/SwingButtonPeer.java
@@ -38,6 +38,7 @@ exception statement from your version. */
package gnu.java.awt.peer.swing;
import java.awt.Button;
+import java.awt.Container;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
@@ -69,6 +70,13 @@ public class SwingButtonPeer
extends JButton
implements SwingComponent
{
+ Button button;
+
+ SwingButton(Button button)
+ {
+ this.button = button;
+ }
+
/**
* Overridden so that this method returns the correct value even without a
* peer.
@@ -90,8 +98,8 @@ public class SwingButtonPeer
public boolean isShowing()
{
boolean retVal = false;
- if (SwingButtonPeer.this.awtComponent != null)
- retVal = SwingButtonPeer.this.awtComponent.isShowing();
+ if (button != null)
+ retVal = button.isShowing();
return retVal;
}
@@ -168,6 +176,14 @@ public class SwingButtonPeer
ev.setSource(this);
processKeyEvent(ev);
}
+
+ public Container getParent()
+ {
+ Container par = null;
+ if (button != null)
+ par = button.getParent();
+ return par;
+ }
}
/**
@@ -205,7 +221,7 @@ public class SwingButtonPeer
*/
public SwingButtonPeer(Button theButton)
{
- SwingButton button = new SwingButton();
+ SwingButton button = new SwingButton(theButton);
button.setText(theButton.getLabel());
button.addActionListener(new SwingButtonListener());
init(theButton, button);
diff --git a/gnu/java/awt/peer/swing/SwingComponent.java b/gnu/java/awt/peer/swing/SwingComponent.java
index a51b758ad..04ca7294f 100644
--- a/gnu/java/awt/peer/swing/SwingComponent.java
+++ b/gnu/java/awt/peer/swing/SwingComponent.java
@@ -62,7 +62,7 @@ public interface SwingComponent
/**
* Handles a mouse event. This is usually forwarded to
- * {@link java.awt.Component#processMouseMotionEvent(MouseEvent)} of the swing
+ * {@link Component#processMouseMotionEvent(MouseEvent)} of the swing
* component.
*
* @param ev the mouse event
@@ -71,7 +71,7 @@ public interface SwingComponent
/**
* Handles a mouse motion event. This is usually forwarded to
- * {@link java.awt.Component#processMouseEvent(MouseEvent)} of the swing
+ * {@link Component#processMouseEvent(MouseEvent)} of the swing
* component.
*
* @param ev the mouse motion event
@@ -80,7 +80,7 @@ public interface SwingComponent
/**
* Handles a key event. This is usually forwarded to
- * {@link java.awt.Component#processKeyEvent(KeyEvent)} of the swing
+ * {@link Component#processKeyEvent(KeyEvent)} of the swing
* component.
*
* @param ev the key event
diff --git a/gnu/java/awt/peer/swing/SwingComponentPeer.java b/gnu/java/awt/peer/swing/SwingComponentPeer.java
index 96ccc00b8..7e1ad86a0 100644
--- a/gnu/java/awt/peer/swing/SwingComponentPeer.java
+++ b/gnu/java/awt/peer/swing/SwingComponentPeer.java
@@ -42,6 +42,7 @@ import java.awt.AWTException;
import java.awt.BufferCapabilities;
import java.awt.Color;
import java.awt.Component;
+import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
@@ -62,6 +63,13 @@ import java.awt.image.ImageProducer;
import java.awt.image.VolatileImage;
import java.awt.peer.ComponentPeer;
import java.awt.peer.ContainerPeer;
+import java.awt.peer.LightweightPeer;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.swing.JComponent;
+import javax.swing.RepaintManager;
/**
* The base class for Swing based component peers. This provides the basic
@@ -75,7 +83,7 @@ import java.awt.peer.ContainerPeer;
* This class also provides the necesary hooks into the Swing painting and
* event handling system. In order to achieve this, it traps paint, mouse and
* key events in {@link #handleEvent(AWTEvent)} and calls some special methods
- * ({@link #peerPaint(Graphics)}, {@link #handleKeyEvent(KeyEvent)},
+ * ({@link #peerPaint(Graphics,boolean)}, {@link #handleKeyEvent(KeyEvent)},
* {@link #handleMouseEvent(MouseEvent)} and
* {@link #handleMouseMotionEvent(MouseEvent)}) that call the corresponding
* Swing methods.
@@ -97,14 +105,30 @@ public class SwingComponentPeer
protected SwingComponent swingComponent;
/**
+ * The font that is set for this peer.
+ */
+ protected Font peerFont;
+
+ /**
+ * The repaint requests that will be handled next. The events queued
+ * up here are in the exact same order as they appear in
+ * {@link #coalescePaintEvent(PaintEvent)}, that is in event queue order.
+ * This is used for coalescing paint events.
+ *
+ * @see #coalescePaintEvent(PaintEvent)
+ */
+ protected List currentPaintEvents;
+
+ /**
* Creates a SwingComponentPeer instance. Subclasses are expected to call
- * this constructor and thereafter call
- * {@link #init(Component,SwingComponent)}
- * in order to setup the AWT and Swing components properly.
+ * this constructor and thereafter call {@link #init(Component,
+ * SwingComponent)}in order to setup the AWT and Swing components properly.
*/
protected SwingComponentPeer()
{
- // Nothing to do here.
+ // Initialize paint event queue.
+ currentPaintEvents = new LinkedList();
+
}
/**
@@ -118,6 +142,38 @@ public class SwingComponentPeer
{
awtComponent = awtComp;
swingComponent = swingComp;
+ if (swingComponent != null)
+ {
+ JComponent c = swingComponent.getJComponent();
+ if (c != null)
+ {
+ c.addNotify();
+ RepaintManager.currentManager(c).setDoubleBufferingEnabled(false);
+ System.setProperty("gnu.awt.swing.doublebuffering", "true");
+ }
+ }
+
+ // Register this heavyweight component with the nearest heavyweight
+ // container, so we get peerPaint() triggered by that container.
+ if (! (this instanceof LightweightPeer))
+ {
+ Component comp = awtComponent;
+ Container parent = comp.getParent();
+ while (parent != null &&
+ ! (parent.getPeer() instanceof SwingContainerPeer))
+ {
+ comp = parent;
+ parent = comp.getParent();
+ }
+
+ // At this point we have the ancestor with a SwingContainerPeer
+ // (or null peer).
+ if (parent != null && parent.getPeer() instanceof SwingContainerPeer)
+ {
+ SwingContainerPeer p = (SwingContainerPeer) parent.getPeer();
+ p.addHeavyweightDescendent(awtComponent);
+ }
+ }
}
/**
@@ -185,6 +241,28 @@ public class SwingComponentPeer
*/
public void dispose()
{
+ // Unregister this heavyweight component from the nearest heavyweight
+ // container.
+ if (! (this instanceof LightweightPeer))
+ {
+ Component comp = awtComponent;
+ Container parent = comp.getParent();
+ while (parent != null &&
+ ! (parent.getPeer() instanceof SwingContainerPeer))
+ {
+ comp = parent;
+ parent = comp.getParent();
+ }
+
+ // At this point we have the ancestor with a SwingContainerPeer
+ // (or null peer).
+ if (parent != null && parent.getPeer() instanceof SwingContainerPeer)
+ {
+ SwingContainerPeer p = (SwingContainerPeer) parent.getPeer();
+ p.removeHeavyweightDescendent(awtComponent);
+ }
+ }
+
awtComponent = null;
swingComponent = null;
}
@@ -244,8 +322,7 @@ public class SwingComponentPeer
public Graphics getGraphics()
{
Component parent = awtComponent.getParent();
- ComponentPeer parentPeer = parent.getPeer();
- Graphics g = parentPeer.getGraphics();
+ Graphics g = parent.getGraphics();
g.translate(awtComponent.getX(), awtComponent.getY());
g.setClip(0, 0, awtComponent.getWidth(), awtComponent.getHeight());
return g;
@@ -331,23 +408,30 @@ public class SwingComponentPeer
{
case PaintEvent.UPDATE:
case PaintEvent.PAINT:
- // This only will work when the component is showing.
- if (awtComponent.isShowing())
+ // Need to synchronize to avoid threading problems on the
+ // paint event list.
+ // We must synchronize on the tree lock first to avoid deadlock,
+ // because Container.paint() will grab it anyway.
+ synchronized (awtComponent.getTreeLock())
{
- Graphics g = getGraphics();
- Rectangle clip = ((PaintEvent)e).getUpdateRect();
- g.clipRect(clip.x, clip.y, clip.width, clip.height);
- //if (this instanceof LightweightPeer)
- // {
- if (e.getID() == PaintEvent.UPDATE)
- awtComponent.update(g);
- else
- awtComponent.paint(g);
- // }
- // We paint the 'heavyweights' at last, so that they appear on top of
- // everything else.
- peerPaint(g);
- g.dispose();
+ synchronized (currentPaintEvents)
+ {
+ if (currentPaintEvents.contains(e))
+ {
+ Graphics g = awtComponent.getGraphics();
+ try
+ {
+ Rectangle clip = ((PaintEvent) e).getUpdateRect();
+ g.clipRect(clip.x, clip.y, clip.width, clip.height);
+ peerPaint(g, e.getID() == PaintEvent.UPDATE);
+ }
+ finally
+ {
+ g.dispose();
+ }
+ currentPaintEvents.remove(e);
+ }
+ }
}
break;
case MouseEvent.MOUSE_PRESSED:
@@ -451,9 +535,15 @@ public class SwingComponentPeer
return retVal;
}
+ /**
+ * Paints the component. This is triggered by
+ * {@link Component#paintAll(Graphics)}.
+ *
+ * @param graphics the graphics to paint with
+ */
public void paint(Graphics graphics)
{
- // FIXME: I don't know what this method is supposed to do.
+ peerPaint(graphics, false);
}
/**
@@ -634,6 +724,7 @@ public class SwingComponentPeer
*/
public void setFont(Font font)
{
+ peerFont = font;
if (swingComponent != null)
swingComponent.getJComponent().setFont(font);
}
@@ -741,7 +832,36 @@ public class SwingComponentPeer
*/
public void coalescePaintEvent(PaintEvent e)
{
- // Nothing to do here yet.
+ synchronized (currentPaintEvents)
+ {
+ Rectangle newRect = e.getUpdateRect();
+ boolean coalesced = false;
+ for (Iterator i = currentPaintEvents.iterator(); i.hasNext() && ! coalesced;)
+ {
+ PaintEvent e2 = (PaintEvent) i.next();
+ if (e.getID() == e2.getID())
+ {
+ Rectangle oldRect = e2.getUpdateRect();
+ if (oldRect.contains(newRect))
+ {
+ // Merge newRect into oldRect. We have to discard the old request
+ // so that the events are still in the correct order.
+ i.remove();
+ newRect.setBounds(oldRect);
+ coalesced = true;
+ }
+ else if (newRect.contains(oldRect))
+ {
+ // Merge oldRect into newRect. We have to discard the old request
+ // so that the events are still in the correct order.
+ i.remove();
+ coalesced = true;
+ }
+ }
+ // TODO: Maybe do something more clever here.
+ }
+ currentPaintEvents.add(e);
+ }
}
/**
@@ -947,9 +1067,33 @@ public class SwingComponentPeer
* paint() on the Swing component.
*
* @param g the graphics context to use for painting
+ * @param update wether we need to call update or paint on the AWT component
+ */
+ protected void peerPaint(Graphics g, boolean update)
+ {
+ peerPaintComponent(g);
+
+ Graphics userGraphics = g.create();
+ try{
+ if (update)
+ awtComponent.update(userGraphics);
+ else
+ awtComponent.paint(userGraphics);
+ } finally {
+ userGraphics.dispose();
+ }
+
+ }
+
+ /**
+ * Paints the actual 'heavyweight' swing component, if there is one
+ * associated to this peer.
+ *
+ * @param g the graphics to paint the component with
*/
- protected void peerPaint(Graphics g)
+ protected void peerPaintComponent(Graphics g)
{
+ // Paint the actual Swing component if this peer has one.
if (swingComponent != null)
swingComponent.getJComponent().paint(g);
}
diff --git a/gnu/java/awt/peer/swing/SwingContainerPeer.java b/gnu/java/awt/peer/swing/SwingContainerPeer.java
index f433e1b5c..c78b644a7 100644
--- a/gnu/java/awt/peer/swing/SwingContainerPeer.java
+++ b/gnu/java/awt/peer/swing/SwingContainerPeer.java
@@ -37,14 +37,20 @@ exception statement from your version. */
package gnu.java.awt.peer.swing;
+import gnu.classpath.SystemProperties;
+
import java.awt.Component;
import java.awt.Container;
import java.awt.Graphics;
+import java.awt.Image;
import java.awt.Insets;
-import java.awt.Shape;
+import java.awt.Rectangle;
+import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.peer.ComponentPeer;
import java.awt.peer.ContainerPeer;
+import java.util.Iterator;
+import java.util.LinkedList;
/**
* A peer for Container to be used with the Swing based AWT peers.
@@ -57,13 +63,53 @@ public class SwingContainerPeer
{
/**
+ * Stores all heavyweight descendents of the container. This is used
+ * in {@link #peerPaintChildren(Graphics)}.
+ */
+ private LinkedList heavyweightDescendents;
+
+ /**
+ * The backbuffer used for painting UPDATE events.
+ */
+ private Image backbuffer;
+
+ /**
* Creates a new SwingContainerPeer.
*
* @param awtCont
*/
- public SwingContainerPeer(Component awtCont)
+ public SwingContainerPeer(Container awtCont)
+ {
+ heavyweightDescendents = new LinkedList();
+ }
+
+ /**
+ * Registers a heavyweight descendent. This is then painted by
+ * {@link #peerPaintChildren(Graphics)}.
+ *
+ * @param comp the descendent to register
+ *
+ * @see #peerPaintChildren(Graphics)
+ * @see #removeHeavyweightDescendent(Component)
+ */
+ synchronized void addHeavyweightDescendent(Component comp)
+ {
+ heavyweightDescendents.add(comp);
+ focusOwner = null;
+ }
+
+ /**
+ * Unregisters a heavyweight descendent.
+ *
+ * @param comp the descendent to unregister
+ *
+ * @see #peerPaintChildren(Graphics)
+ * @see #addHeavyweightDescendent(Component)
+ */
+ synchronized void removeHeavyweightDescendent(Component comp)
{
- init(awtCont, null);
+ heavyweightDescendents.remove(comp);
+ focusOwner = null;
}
/**
@@ -92,12 +138,7 @@ public class SwingContainerPeer
*/
public Insets getInsets()
{
- Insets retVal;
- if (swingComponent != null)
- retVal = swingComponent.getJComponent().getInsets();
- else
- retVal = new Insets(0, 0, 0, 0);
- return retVal;
+ return insets();
}
/**
@@ -171,38 +212,83 @@ public class SwingContainerPeer
}
/**
- * Triggers painting of a component. This calls peerPaint on all the child
- * components of this container.
- *
- * @param g the graphics context to paint to
+ * Performs the super behaviour (call peerPaintComponent() and
+ * awtComponent.paint()), and forwards the paint request to the heavyweight
+ * descendents of the container.
*/
- protected void peerPaint(Graphics g)
+ protected void peerPaint(Graphics g, boolean update)
{
- Container c = (Container) awtComponent;
- Component[] children = c.getComponents();
- for (int i = children.length - 1; i >= 0; --i)
+ if (isDoubleBuffering())
{
- Component child = children[i];
- ComponentPeer peer = child.getPeer();
- boolean translated = false;
- boolean clipped = false;
- Shape oldClip = g.getClip();
+ int width = awtComponent.getWidth();
+ int height = awtComponent.getHeight();
+ if (backbuffer == null
+ || backbuffer.getWidth(awtComponent) < width
+ || backbuffer.getHeight(awtComponent) < height)
+ backbuffer = awtComponent.createImage(width, height);
+ Graphics g2 = backbuffer.getGraphics();
+ Rectangle clip = g.getClipRect();
try
- {
- g.translate(child.getX(), child.getY());
- translated = true;
- g.setClip(0, 0, child.getWidth(), child.getHeight());
- clipped = true;
- if (peer instanceof SwingComponentPeer)
- ((SwingComponentPeer) peer).peerPaint(g);
- }
+ {
+ g2.setClip(clip);
+ super.peerPaint(g2, update);
+ peerPaintChildren(g2);
+ }
finally
- {
- if (translated)
- g.translate(- child.getX(), - child.getY());
- if (clipped)
- g.setClip(oldClip);
- }
+ {
+ g2.dispose();
+ }
+ g.drawImage(backbuffer, 0, 0, awtComponent);
+ }
+ else
+ {
+ super.peerPaint(g, update);
+ peerPaintChildren(g);
+ }
+ }
+
+ /**
+ * Determines if we should do double buffering or not.
+ *
+ * @return if we should do double buffering or not
+ */
+ private boolean isDoubleBuffering()
+ {
+ Object prop =
+ SystemProperties.getProperty("gnu.awt.swing.doublebuffering", "false");
+ return prop.equals("true");
+ }
+
+ /**
+ * Paints any heavyweight child components.
+ *
+ * @param g the graphics to use for painting
+ */
+ protected synchronized void peerPaintChildren(Graphics g)
+ {
+ // TODO: Is this the right painting order?
+ for (Iterator i = heavyweightDescendents.iterator(); i.hasNext();)
+ {
+ Component child = (Component) i.next();
+ ComponentPeer peer = child.getPeer();
+
+ if (peer instanceof SwingComponentPeer && child.isVisible())
+ {
+ // TODO: The translation here doesn't work for deeper
+ // nested children. Fix this!
+ Graphics g2 = g.create(child.getX(), child.getY(),
+ child.getWidth(), child.getHeight());
+ try
+ {
+ // update() is only called for the topmost component if
+ // necessary, all other components only get paint() called.
+ ((SwingComponentPeer) peer).peerPaint(g2, false);
+ }
+ finally
+ {
+ g2.dispose();
+ }
+ }
}
}
@@ -214,17 +300,13 @@ public class SwingContainerPeer
protected void handleMouseEvent(MouseEvent ev)
{
Component comp = awtComponent.getComponentAt(ev.getPoint());
- if(comp == null)
- comp = awtComponent;
- if (comp != null)
+ if(comp == null) comp = awtComponent;
+ ComponentPeer peer = comp.getPeer();
+ if (awtComponent != comp && !comp.isLightweight() && peer instanceof SwingComponentPeer)
{
- ComponentPeer peer = comp.getPeer();
- if (awtComponent != comp && !comp.isLightweight() && peer instanceof SwingComponentPeer)
- {
- ev.translatePoint(comp.getX(), comp.getY());
- ev.setSource(comp);
- ((SwingComponentPeer) peer).handleMouseEvent(ev);
- }
+ ev.translatePoint(comp.getX(), comp.getY());
+ ev.setSource(comp);
+ ((SwingComponentPeer) peer).handleMouseEvent(ev);
}
}
@@ -246,4 +328,39 @@ public class SwingContainerPeer
}
}
}
+
+ /**
+ * Handles key events on the component. This is usually forwarded to the
+ * SwingComponent's processKeyEvent() method.
+ *
+ * @param e the key event
+ */
+ protected void handleKeyEvent(KeyEvent e)
+ {
+ Component owner = getFocusOwner();
+ if(owner != null)
+ owner.dispatchEvent(e);
+ else
+ super.handleKeyEvent(e);
+ }
+
+ private Component focusOwner = null;
+
+ private Component getFocusOwner()
+ {
+ if(focusOwner == null)
+ {
+ for(Iterator iter=heavyweightDescendents.iterator(); iter.hasNext();)
+ {
+ Component child = (Component) iter.next();
+ if(child.isFocusable())
+ {
+ focusOwner = child;
+ break;
+ }
+ }
+ }
+ return focusOwner;
+ }
+
}
diff --git a/gnu/java/awt/peer/swing/SwingFramePeer.java b/gnu/java/awt/peer/swing/SwingFramePeer.java
index 0d5a02d78..56c7417cd 100644
--- a/gnu/java/awt/peer/swing/SwingFramePeer.java
+++ b/gnu/java/awt/peer/swing/SwingFramePeer.java
@@ -43,6 +43,7 @@ import java.awt.Insets;
import java.awt.MenuBar;
import java.awt.Point;
import java.awt.event.MouseEvent;
+import java.awt.peer.ComponentPeer;
import java.awt.peer.FramePeer;
/**
@@ -53,9 +54,9 @@ import java.awt.peer.FramePeer;
* As a minimum, a subclass must implement all the remaining abstract methods
* as well as the following methods:
* <ul>
- * <li>{@link java.awt.peer.ComponentPeer#getLocationOnScreen()}</li>
- * <li>{@link java.awt.peer.ComponentPeer#getGraphics()}</li>
- * <li>{@link java.awt.peer.ComponentPeer#createImage(int, int)}</li>
+ * <li>{@link ComponentPeer#getLocationOnScreen()}</li>
+ * <li>{@link ComponentPeer#getGraphics()}</li>
+ * <li>{@link ComponentPeer#createImage(int, int)}</li>
* </ul>
*
* @author Roman Kennke (kennke@aicas.com)
@@ -97,9 +98,9 @@ public abstract class SwingFramePeer
*
* @param g the graphics context to use for painting
*/
- protected void peerPaint(Graphics g)
+ protected void peerPaintComponent(Graphics g)
{
- super.peerPaint(g);
+ super.peerPaintComponent(g);
if (menuBar != null)
menuBar.peerPaint(g);
}
diff --git a/gnu/java/awt/peer/swing/SwingLabelPeer.java b/gnu/java/awt/peer/swing/SwingLabelPeer.java
index dd86fff2d..349c5a0ab 100644
--- a/gnu/java/awt/peer/swing/SwingLabelPeer.java
+++ b/gnu/java/awt/peer/swing/SwingLabelPeer.java
@@ -37,6 +37,8 @@ exception statement from your version. */
package gnu.java.awt.peer.swing;
+import java.awt.Container;
+import java.awt.Graphics;
import java.awt.Image;
import java.awt.Label;
import java.awt.Point;
@@ -67,7 +69,14 @@ public class SwingLabelPeer
extends JLabel
implements SwingComponent
{
-
+ Label label;
+
+
+ SwingLabel(Label label)
+ {
+ this.label = label;
+ }
+
/**
* Returns this label.
*
@@ -131,8 +140,8 @@ public class SwingLabelPeer
public boolean isShowing()
{
boolean retVal = false;
- if (SwingLabelPeer.this.awtComponent != null)
- retVal = SwingLabelPeer.this.awtComponent.isShowing();
+ if (label != null)
+ retVal = label.isShowing();
return retVal;
}
@@ -149,7 +158,19 @@ public class SwingLabelPeer
{
return SwingLabelPeer.this.createImage(w, h);
}
-
+
+ public Graphics getGraphics()
+ {
+ return SwingLabelPeer.this.getGraphics();
+ }
+
+ public Container getParent()
+ {
+ Container par = null;
+ if (label != null)
+ par = label.getParent();
+ return par;
+ }
}
/**
@@ -160,11 +181,11 @@ public class SwingLabelPeer
public SwingLabelPeer(Label label)
{
super();
- SwingLabel swingLabel = new SwingLabel();
+ SwingLabel swingLabel = new SwingLabel(label);
swingLabel.setText(label.getText());
- swingLabel.setHorizontalAlignment(label.getAlignment());
swingLabel.setOpaque(true);
init(label, swingLabel);
+ setAlignment(label.getAlignment());
}
/**
@@ -190,7 +211,20 @@ public class SwingLabelPeer
*/
public void setAlignment(int alignment)
{
- ((JLabel) swingComponent.getJComponent()).setHorizontalAlignment(alignment);
+ JLabel swingLabel = (JLabel) swingComponent.getJComponent();
+ switch (alignment)
+ {
+ case Label.RIGHT:
+ swingLabel.setHorizontalAlignment(JLabel.RIGHT);
+ break;
+ case Label.CENTER:
+ swingLabel.setHorizontalAlignment(JLabel.CENTER);
+ break;
+ case Label.LEFT:
+ default:
+ swingLabel.setHorizontalAlignment(JLabel.LEFT);
+ break;
+ }
}
}
diff --git a/gnu/java/awt/peer/swing/SwingListPeer.java b/gnu/java/awt/peer/swing/SwingListPeer.java
new file mode 100644
index 000000000..aca207048
--- /dev/null
+++ b/gnu/java/awt/peer/swing/SwingListPeer.java
@@ -0,0 +1,352 @@
+/* SwingListPeer.java -- A Swing based peer for AWT lists
+ 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 gnu.java.awt.peer.swing;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.List;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.peer.ListPeer;
+
+import javax.swing.DefaultListModel;
+import javax.swing.JComponent;
+import javax.swing.JList;
+import javax.swing.JScrollPane;
+import javax.swing.ListSelectionModel;
+
+public class SwingListPeer
+ extends SwingComponentPeer
+ implements ListPeer
+{
+
+ /**
+ * A spezialized Swing scroller used to hold the list.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ private class SwingList
+ extends JScrollPane
+ implements SwingComponent
+ {
+
+ SwingList(Component comp)
+ {
+ super(comp, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
+ JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
+ }
+
+ /**
+ * Returns this label.
+ *
+ * @return <code>this</code>
+ */
+ public JComponent getJComponent()
+ {
+ return this;
+ }
+
+ /**
+ * Handles mouse events by forwarding it to
+ * <code>processMouseEvent()</code>.
+ *
+ * @param ev the mouse event
+ */
+ public void handleMouseEvent(MouseEvent ev)
+ {
+ ev.setSource(this);
+ dispatchEvent(ev);
+ }
+
+ /**
+ * Force lightweight mouse dispatching.
+ */
+ public boolean isLightweight()
+ {
+ return false;
+ }
+
+ /**
+ * Handles mouse motion events by forwarding it to
+ * <code>processMouseMotionEvent()</code>.
+ *
+ * @param ev the mouse motion event
+ */
+ public void handleMouseMotionEvent(MouseEvent ev)
+ {
+ processMouseMotionEvent(ev);
+ }
+
+ /**
+ * Handles key events by forwarding it to <code>processKeyEvent()</code>.
+ *
+ * @param ev the mouse event
+ */
+ public void handleKeyEvent(KeyEvent ev)
+ {
+ processKeyEvent(ev);
+ }
+
+ /**
+ * Overridden so that this method returns the correct value even without a
+ * peer.
+ *
+ * @return the screen location of the button
+ */
+ public Point getLocationOnScreen()
+ {
+ return SwingListPeer.this.getLocationOnScreen();
+ }
+
+ /**
+ * Overridden so that the isShowing method returns the correct value for the
+ * swing button, even if it has no peer on its own.
+ *
+ * @return <code>true</code> if the button is currently showing,
+ * <code>false</code> otherwise
+ */
+ public boolean isShowing()
+ {
+ boolean retVal = false;
+ if (SwingListPeer.this.awtComponent != null)
+ retVal = SwingListPeer.this.awtComponent.isShowing();
+ return retVal;
+ }
+
+ /**
+ * Overridden, so that the Swing button can create an Image without its
+ * own peer.
+ *
+ * @param w the width of the image
+ * @param h the height of the image
+ *
+ * @return an image
+ */
+ public Image createImage(int w, int h)
+ {
+ return SwingListPeer.this.createImage(w, h);
+ }
+
+ public Graphics getGraphics()
+ {
+ return SwingListPeer.this.getGraphics();
+ }
+
+ public Container getParent()
+ {
+ Container par = null;
+ if (SwingListPeer.this.awtComponent != null)
+ par = SwingListPeer.this.awtComponent.getParent();
+ return par;
+ }
+ }
+
+ /**
+ * The actual Swing JList.
+ */
+ private JList jList;
+
+ private DefaultListModel listModel;
+
+ public SwingListPeer(List list)
+ {
+ super();
+ listModel = new DefaultListModel();
+ jList = new JList(listModel);
+ SwingList swingList = new SwingList(jList);
+ init(list, swingList);
+
+ // Pull over the items from the list.
+ String[] items = list.getItems();
+ for (int i = 0 ; i < items.length; i++)
+ addItem(items[i], i);
+ }
+
+ public void add(String item, int index)
+ {
+ if (listModel != null)
+ listModel.add(index, item);
+ }
+
+ public void addItem(String item, int index)
+ {
+ if (listModel != null)
+ listModel.add(index, item);
+ }
+
+ public void clear()
+ {
+ if (listModel != null)
+ listModel.clear();
+ }
+
+ public void delItems(int startIndex, int endIndex)
+ {
+ if (listModel != null)
+ listModel.removeRange(startIndex, endIndex);
+ }
+
+ public void deselect(int index)
+ {
+ if (jList != null)
+ {
+ jList.getSelectionModel().removeSelectionInterval(index, index);
+ }
+ }
+
+ public Dimension getMinimumSize(int s)
+ {
+ Dimension d = null;
+ if (jList != null)
+ {
+ d = jList.getComponent(s).getMinimumSize();
+ }
+ return d;
+ }
+
+ public Dimension getPreferredSize(int s)
+ {
+ Dimension d = null;
+ if (jList != null)
+ {
+ d = jList.getComponent(s).getPreferredSize();
+ }
+ return d;
+ }
+
+ public int[] getSelectedIndexes()
+ {
+ int[] sel = null;
+ if (jList != null)
+ {
+ sel = jList.getSelectedIndices();
+ }
+ return sel;
+ }
+
+ public void makeVisible(int index)
+ {
+ if (jList != null)
+ {
+ Component comp = jList.getComponent(index);
+ jList.scrollRectToVisible(comp.getBounds());
+ }
+ }
+
+ public Dimension minimumSize(int s)
+ {
+ Dimension d = null;
+ if (jList != null)
+ {
+ d = jList.getComponent(s).getMinimumSize();
+ }
+ return d;
+ }
+
+ public Dimension preferredSize(int s)
+ {
+ Dimension d = null;
+ if (jList != null)
+ {
+ d = jList.getComponent(s).getPreferredSize();
+ }
+ return d;
+ }
+
+ public void removeAll()
+ {
+ if (jList != null)
+ {
+ jList.removeAll();
+ }
+ }
+
+ public void select(int index)
+ {
+ if (jList != null)
+ {
+ jList.setSelectedIndex(index);
+ }
+ }
+
+ public void setMultipleMode(boolean multi)
+ {
+ if (jList != null)
+ {
+ jList.setSelectionMode(multi
+ ? ListSelectionModel.MULTIPLE_INTERVAL_SELECTION
+ : ListSelectionModel.SINGLE_SELECTION);
+ }
+ }
+
+ public void setMultipleSelections(boolean multi)
+ {
+ if (jList != null)
+ {
+ jList.setSelectionMode(multi
+ ? ListSelectionModel.MULTIPLE_INTERVAL_SELECTION
+ : ListSelectionModel.SINGLE_SELECTION);
+ }
+ }
+
+ public void reshape(int x, int y, int width, int height)
+ {
+ if (swingComponent != null)
+ {
+ swingComponent.getJComponent().setBounds(x, y, width, height);
+ swingComponent.getJComponent().validate();
+ }
+ }
+
+ protected void peerPaint(Graphics g, boolean update)
+ {
+ super.peerPaint(g, update);
+ jList.doLayout();
+ jList.list();
+
+ Rectangle r = getBounds();
+ g.setColor(Color.RED);
+ g.drawRect(r.x, r.y, r.width, r.height);
+ }
+}
diff --git a/gnu/java/awt/peer/swing/SwingMenuBarPeer.java b/gnu/java/awt/peer/swing/SwingMenuBarPeer.java
index 0033efb02..bd9dcd77a 100644
--- a/gnu/java/awt/peer/swing/SwingMenuBarPeer.java
+++ b/gnu/java/awt/peer/swing/SwingMenuBarPeer.java
@@ -174,7 +174,7 @@ public class SwingMenuBarPeer
/**
* Adds a help menu to the menu bar.
*
- * @param menu the menu to add
+ * @param m the menu to add
*/
public void addHelpMenu(Menu menu)
{
diff --git a/gnu/java/awt/peer/swing/SwingPanelPeer.java b/gnu/java/awt/peer/swing/SwingPanelPeer.java
index 0a0f20fe8..3cea62ac4 100644
--- a/gnu/java/awt/peer/swing/SwingPanelPeer.java
+++ b/gnu/java/awt/peer/swing/SwingPanelPeer.java
@@ -39,7 +39,6 @@ exception statement from your version. */
package gnu.java.awt.peer.swing;
import java.awt.Panel;
-import java.awt.peer.LightweightPeer;
import java.awt.peer.PanelPeer;
/**
@@ -51,7 +50,7 @@ import java.awt.peer.PanelPeer;
// necessary, but might be good for more consistend Look.
public class SwingPanelPeer
extends SwingContainerPeer
- implements PanelPeer, LightweightPeer
+ implements PanelPeer
{
/**
@@ -63,5 +62,6 @@ public class SwingPanelPeer
public SwingPanelPeer(Panel panel)
{
super(panel);
+ init(panel, null);
}
}
diff --git a/gnu/java/awt/peer/swing/SwingTextAreaPeer.java b/gnu/java/awt/peer/swing/SwingTextAreaPeer.java
new file mode 100644
index 000000000..04ac01141
--- /dev/null
+++ b/gnu/java/awt/peer/swing/SwingTextAreaPeer.java
@@ -0,0 +1,317 @@
+/* SwingTextAreaPeer.java -- A Swing based peer for AWT textareas
+ 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 gnu.java.awt.peer.swing;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.TextArea;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.im.InputMethodRequests;
+import java.awt.peer.TextAreaPeer;
+
+import javax.swing.JComponent;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.text.BadLocationException;
+
+public class SwingTextAreaPeer
+ extends SwingComponentPeer
+ implements TextAreaPeer
+{
+
+ /**
+ * A spezialized Swing scroller used to hold the textarea.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ private class SwingTextArea
+ extends JScrollPane
+ implements SwingComponent
+ {
+
+ SwingTextArea(Component comp)
+ {
+ super(comp, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
+ JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
+ }
+
+ /**
+ * Returns this label.
+ *
+ * @return <code>this</code>
+ */
+ public JComponent getJComponent()
+ {
+ return this;
+ }
+
+ /**
+ * Handles mouse events by forwarding it to
+ * <code>processMouseEvent()</code>.
+ *
+ * @param ev the mouse event
+ */
+ public void handleMouseEvent(MouseEvent ev)
+ {
+ ev.setSource(this);
+ dispatchEvent(ev);
+ }
+
+ /**
+ * Force lightweight mouse dispatching.
+ */
+ public boolean isLightweight()
+ {
+ return false;
+ }
+
+ /**
+ * Handles mouse motion events by forwarding it to
+ * <code>processMouseMotionEvent()</code>.
+ *
+ * @param ev the mouse motion event
+ */
+ public void handleMouseMotionEvent(MouseEvent ev)
+ {
+ processMouseMotionEvent(ev);
+ }
+
+ /**
+ * Handles key events by forwarding it to <code>processKeyEvent()</code>.
+ *
+ * @param ev the mouse event
+ */
+ public void handleKeyEvent(KeyEvent ev)
+ {
+ processKeyEvent(ev);
+ }
+
+ /**
+ * Overridden so that this method returns the correct value even without a
+ * peer.
+ *
+ * @return the screen location of the button
+ */
+ public Point getLocationOnScreen()
+ {
+ return SwingTextAreaPeer.this.getLocationOnScreen();
+ }
+
+ /**
+ * Overridden so that the isShowing method returns the correct value for the
+ * swing button, even if it has no peer on its own.
+ *
+ * @return <code>true</code> if the button is currently showing,
+ * <code>false</code> otherwise
+ */
+ public boolean isShowing()
+ {
+ boolean retVal = false;
+ if (SwingTextAreaPeer.this.awtComponent != null)
+ retVal = SwingTextAreaPeer.this.awtComponent.isShowing();
+ return retVal;
+ }
+
+ /**
+ * Overridden, so that the Swing button can create an Image without its
+ * own peer.
+ *
+ * @param w the width of the image
+ * @param h the height of the image
+ *
+ * @return an image
+ */
+ public Image createImage(int w, int h)
+ {
+ return SwingTextAreaPeer.this.createImage(w, h);
+ }
+
+ public Graphics getGraphics()
+ {
+ return SwingTextAreaPeer.this.getGraphics();
+ }
+
+ public Container getParent()
+ {
+ Container par = null;
+ if (SwingTextAreaPeer.this.awtComponent != null)
+ par = SwingTextAreaPeer.this.awtComponent.getParent();
+ return par;
+ }
+ }
+
+ /**
+ * The actual JTextArea.
+ */
+ private JTextArea jTextArea;
+
+ public SwingTextAreaPeer(TextArea textArea)
+ {
+ super();
+ System.err.println("new SwingTextAreaPeer");
+ jTextArea = new JTextArea();
+ SwingTextArea swingArea = new SwingTextArea(jTextArea);
+ init(textArea, swingArea);
+
+ // Pull over the text from the text area.
+ setText(textArea.getText());
+ }
+
+ public Dimension getMinimumSize(int rows, int cols)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public Dimension getPreferredSize(int rows, int cols)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void insert(String text, int pos)
+ {
+ jTextArea.insert(text, pos);
+ }
+
+ public void insertText(String text, int pos)
+ {
+ jTextArea.insert(text, pos);
+ }
+
+ public Dimension minimumSize(int rows, int cols)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public Dimension preferredSize(int rows, int cols)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void replaceRange(String text, int start, int end)
+ {
+ jTextArea.replaceRange(text, start, end);
+ }
+
+ public void replaceText(String text, int start, int end)
+ {
+ jTextArea.replaceRange(text, start, end);
+ }
+
+ public long filterEvents(long filter)
+ {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int getCaretPosition()
+ {
+ return jTextArea.getCaretPosition();
+ }
+
+ public Rectangle getCharacterBounds(int pos)
+ {
+ Rectangle r;
+ try
+ {
+ return jTextArea.modelToView(pos);
+ }
+ catch (BadLocationException ex)
+ {
+ r = null;
+ }
+ return r;
+ }
+
+ public int getIndexAtPoint(int x, int y)
+ {
+ return jTextArea.viewToModel(new Point(x, y));
+ }
+
+ public InputMethodRequests getInputMethodRequests()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public int getSelectionEnd()
+ {
+ return jTextArea.getSelectionEnd();
+ }
+
+ public int getSelectionStart()
+ {
+ return jTextArea.getSelectionStart();
+ }
+
+ public String getText()
+ {
+ return jTextArea.getText();
+ }
+
+ public void select(int start, int end)
+ {
+ jTextArea.select(start, end);
+ }
+
+ public void setCaretPosition(int pos)
+ {
+ jTextArea.setCaretPosition(pos);
+ }
+
+ public void setEditable(boolean editable)
+ {
+ jTextArea.setEditable(editable);
+ }
+
+ public void setText(String text)
+ {
+ System.err.println("setText: " + text);
+ jTextArea.setText(text);
+ }
+
+}
diff --git a/gnu/java/awt/peer/swing/SwingTextFieldPeer.java b/gnu/java/awt/peer/swing/SwingTextFieldPeer.java
index 0c3b4e726..d7d574a0b 100644
--- a/gnu/java/awt/peer/swing/SwingTextFieldPeer.java
+++ b/gnu/java/awt/peer/swing/SwingTextFieldPeer.java
@@ -36,7 +36,10 @@ obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.awt.peer.swing;
+import java.awt.Component;
+import java.awt.Container;
import java.awt.Dimension;
+import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
@@ -69,6 +72,13 @@ public class SwingTextFieldPeer
implements SwingComponent
{
+ TextField textField;
+
+ SwingTextField(TextField textField)
+ {
+ this.textField = textField;
+ }
+
/**
* Overridden to provide normal behaviour even without a real peer
* attached.
@@ -90,8 +100,8 @@ public class SwingTextFieldPeer
public boolean isShowing()
{
boolean retVal = false;
- if (SwingTextFieldPeer.this.awtComponent != null)
- retVal = SwingTextFieldPeer.this.awtComponent.isShowing();
+ if (textField != null)
+ retVal = textField.isShowing();
return retVal;
}
@@ -151,7 +161,19 @@ public class SwingTextFieldPeer
ev.setSource(this);
processKeyEvent(ev);
}
-
+
+ public Container getParent()
+ {
+ Container par = null;
+ if (textField != null)
+ par = textField.getParent();
+ return par;
+ }
+
+ public Graphics getGraphics()
+ {
+ return SwingTextFieldPeer.this.getGraphics();
+ }
}
/**
@@ -162,7 +184,7 @@ public class SwingTextFieldPeer
*/
public SwingTextFieldPeer(TextField textField)
{
- SwingTextField swingTextField = new SwingTextField();
+ SwingTextField swingTextField = new SwingTextField(textField);
swingTextField.setText(textField.getText());
init(textField, swingTextField);
}
@@ -283,7 +305,7 @@ public class SwingTextFieldPeer
* @param startPos the start index of the selection
* @param endPos the start index of the selection
*/
- public void select(int startPos, int endPos)
+ public void select(int start_pos, int endPos)
{
// TODO: Must be implemented.
}
diff --git a/gnu/java/awt/peer/swing/SwingWindowPeer.java b/gnu/java/awt/peer/swing/SwingWindowPeer.java
index 43a509b95..531552d90 100644
--- a/gnu/java/awt/peer/swing/SwingWindowPeer.java
+++ b/gnu/java/awt/peer/swing/SwingWindowPeer.java
@@ -38,6 +38,7 @@ exception statement from your version. */
package gnu.java.awt.peer.swing;
import java.awt.Window;
+import java.awt.peer.ComponentPeer;
import java.awt.peer.WindowPeer;
/**
@@ -48,9 +49,9 @@ import java.awt.peer.WindowPeer;
* As a minimum, a subclass must implement all the remaining abstract methods
* as well as the following methods:
* <ul>
- * <li>{@link java.awt.peer.ComponentPeer#getLocationOnScreen()}</li>
- * <li>{@link java.awt.peer.ComponentPeer#getGraphics()}</li>
- * <li>{@link java.awt.peer.ComponentPeer#createImage(int, int)}</li>
+ * <li>{@link ComponentPeer#getLocationOnScreen()}</li>
+ * <li>{@link ComponentPeer#getGraphics()}</li>
+ * <li>{@link ComponentPeer#createImage(int, int)}</li>
* </ul>
*
* @author Roman Kennke (kennke@aicas.com)
@@ -68,5 +69,6 @@ public abstract class SwingWindowPeer
public SwingWindowPeer(Window window)
{
super(window);
+ init(window, null);
}
}
diff --git a/gnu/java/net/protocol/jar/Handler.java b/gnu/java/net/protocol/jar/Handler.java
index 316d8cb02..7c09766a5 100644
--- a/gnu/java/net/protocol/jar/Handler.java
+++ b/gnu/java/net/protocol/jar/Handler.java
@@ -1,5 +1,5 @@
/* gnu.java.net.protocol.jar.Handler - jar protocol handler for java.net
- Copyright (C) 1999, 2002, 2003, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -45,6 +45,9 @@ import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.StringTokenizer;
/**
* @author Kresten Krab Thorup (krab@gnu.org)
@@ -114,7 +117,7 @@ public class Handler extends URLStreamHandler
file = file.substring(0, idx + 1) + url_string;
}
- setURL (url, "jar", url.getHost(), url.getPort(), file, null);
+ setURL (url, "jar", url.getHost(), url.getPort(), flat(file), null);
return;
}
@@ -149,6 +152,45 @@ public class Handler extends URLStreamHandler
}
/**
+ * Makes the given jar url string 'flat' by removing any . and .. from
+ * jar file path because ZipFile entries can only handle flat paths.
+ * Inside jar files '/' is always the path separator.
+ */
+ private static String flat(String url_string)
+ {
+ int jar_stop = url_string.indexOf("!/");
+ String jar_path = url_string.substring(jar_stop + 1, url_string.length());
+
+ if (jar_path.indexOf("/.") < 0)
+ return url_string;
+
+ ArrayList tokens = new ArrayList();
+ StringTokenizer st = new StringTokenizer(jar_path, "/");
+ while (st.hasMoreTokens())
+ {
+ String token = st.nextToken();
+ if (token.equals("."))
+ continue;
+ else if (token.equals(".."))
+ {
+ if (! tokens.isEmpty())
+ tokens.remove(tokens.size() - 1);
+ }
+ else
+ tokens.add(token);
+ }
+
+ StringBuffer path = new StringBuffer(url_string.length());
+ path.append(url_string.substring(0, jar_stop + 1));
+
+ Iterator it = tokens.iterator();
+ while (it.hasNext())
+ path.append('/').append(it.next());
+
+ return path.toString();
+ }
+
+ /**
* This method converts a Jar URL object into a String.
*
* @param url The URL object to convert
diff --git a/gnu/javax/swing/text/html/parser/HTML_401Swing.java b/gnu/javax/swing/text/html/css/BorderWidth.java
index 9c934f647..b717020e3 100644
--- a/gnu/javax/swing/text/html/parser/HTML_401Swing.java
+++ b/gnu/javax/swing/text/html/css/BorderWidth.java
@@ -1,4 +1,4 @@
-/* HTML_401Swing.java -- The HTML 4.01 DTD, adapted for HTML rendering in Swing
+/* BorderWidth.java -- A CSS metric for border widths
Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -36,56 +36,31 @@ obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
-package gnu.javax.swing.text.html.parser;
-
-import javax.swing.text.html.parser.DTD;
+package gnu.javax.swing.text.html.css;
/**
- * This class is necessary because the current implementation of the GNU
- * Classpath Swing requires always enclose the text into paragraphs.
- *
- * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
+ * A special CSS metric for border widths. It basically understands everything
+ * as Length, and in addition to that provides a mapping for the border-width's
+ * thin, medium and think values.
*/
-public class HTML_401Swing extends HTML_401F
+public class BorderWidth
+ extends Length
{
+
/**
- * The singleton instance;
- */
- final static HTML_401Swing singleton = new HTML_401Swing();
-
- /**
- * Either takes the document (by name) from DTD table, or
- * creates a new instance and registers it in the tabe.
- * The document is registerd under name "-//W3C//DTD HTML 4.01 Frameset//EN".
- * @return The new or existing DTD for parsing HTML 4.01 Frameset.
- */
- public static DTD getInstance()
- {
- return singleton;
- }
-
- /**
- * Get elements that are allowed in the document body, at the zero level.
- * This list disallows the text at this level (the implied P tag will be
- * generated). It also disallows A, B, I, U, CITE and other similar
- * elements that have the plain text inside. They will also be placed
- * inside the generated implied P tags.
+ * Creates a new BorderWidth instance.
+ *
+ * @param val the CSS value to be interpreted
*/
- protected String[] getBodyElements()
+ public BorderWidth(String val)
{
- return new String[] {
- APPLET, BASEFONT,
- BR, BUTTON,
- IFRAME, IMG,
- INPUT, LABEL, MAP, OBJECT,
- SCRIPT, SELECT,
- TEXTAREA,
- BLOCKQUOTE, CENTER, DEL, DIR,
- DIV, DL, FIELDSET, FORM, H1,
- H2, H3, H4, H5, H6,
- HR, INS, ISINDEX, MENU, NOFRAMES,
- NOSCRIPT, OL, P, PRE, TABLE,
- UL
- };
+ super(val);
+ if (val.equals("thin"))
+ floatValue = 1.F;
+ else if (val.equals("medium"))
+ floatValue = 2.F;
+ else if (val.equals("thick"))
+ floatValue = 3.F;
}
+
}
diff --git a/gnu/javax/swing/text/html/css/CSSColor.java b/gnu/javax/swing/text/html/css/CSSColor.java
index 381bcd5ed..57230f12a 100644
--- a/gnu/javax/swing/text/html/css/CSSColor.java
+++ b/gnu/javax/swing/text/html/css/CSSColor.java
@@ -40,6 +40,8 @@ package gnu.javax.swing.text.html.css;
import java.awt.Color;
import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Set;
/**
* Converts CSS color values into AWT Color values.
@@ -131,4 +133,31 @@ public class CSSColor
{
return value;
}
+
+ /**
+ * Returns <code>true</code> if the specified value is a valid color value,
+ * <code>false</code> otherwise.
+ *
+ * @param val the value to check
+ *
+ * @return <code>true</code> if the specified value is a valid color value,
+ * <code>false</code> otherwise
+ */
+ public static boolean isValidColor(String val)
+ {
+ boolean ret = false;
+ if (val.charAt(0) == '#')
+ ret = true;
+ else
+ {
+ Set colors = COLOR_MAP.keySet();
+ for (Iterator i = colors.iterator(); i.hasNext() && ret == false;)
+ {
+ String color = (String) i.next();
+ if (color.equalsIgnoreCase(val))
+ ret = true;
+ }
+ }
+ return ret;
+ }
}
diff --git a/gnu/javax/swing/text/html/css/CSSParser.java b/gnu/javax/swing/text/html/css/CSSParser.java
index 190c93eb4..0d68457a3 100644
--- a/gnu/javax/swing/text/html/css/CSSParser.java
+++ b/gnu/javax/swing/text/html/css/CSSParser.java
@@ -39,6 +39,8 @@ exception statement from your version. */
package gnu.javax.swing.text.html.css;
import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -156,7 +158,7 @@ public class CSSParser
{
StringBuilder selector = new StringBuilder();
parseSelector(selector);
- callback.startStatement(selector.toString());
+ callback.startStatement(new Selector(selector.toString()));
// Read any number of whitespace.
int token;
do
@@ -296,7 +298,9 @@ public class CSSParser
throws IOException
{
// FIXME: Handle block and ATKEYWORD.
- return parseAny(s);
+ boolean success = parseAny(s);
+ while (parseAny(s));
+ return success;
}
/**
@@ -439,13 +443,22 @@ public class CSSParser
{
try
{
- String name = "/javax/swing/text/html/default.css";
- InputStream in = CSSScanner.class.getResourceAsStream(name);
+ InputStream in;
+ if (args.length > 0)
+ {
+ File file = new File(args[0]);
+ in = new FileInputStream(file);
+ }
+ else
+ {
+ String name = "/javax/swing/text/html/default.css";
+ in = CSSScanner.class.getResourceAsStream(name);
+ }
BufferedInputStream bin = new BufferedInputStream(in);
InputStreamReader r = new InputStreamReader(bin);
CSSParserCallback cb = new CSSParserCallback()
{
- public void startStatement(String selector)
+ public void startStatement(Selector selector)
{
System.out.println("startStatement: " + selector);
}
diff --git a/gnu/javax/swing/text/html/css/CSSParserCallback.java b/gnu/javax/swing/text/html/css/CSSParserCallback.java
index 60dc5488a..b62baddfc 100644
--- a/gnu/javax/swing/text/html/css/CSSParserCallback.java
+++ b/gnu/javax/swing/text/html/css/CSSParserCallback.java
@@ -62,7 +62,7 @@ public interface CSSParserCallback
*
* @param selector the selector of the statement.
*/
- void startStatement(String selector);
+ void startStatement(Selector selector);
/**
* Signals the end of a statement.
diff --git a/gnu/javax/swing/text/html/css/CSSScanner.java b/gnu/javax/swing/text/html/css/CSSScanner.java
index a402b9522..9cc6209a5 100644
--- a/gnu/javax/swing/text/html/css/CSSScanner.java
+++ b/gnu/javax/swing/text/html/css/CSSScanner.java
@@ -509,6 +509,7 @@ class CSSScanner
{
parseBuffer[tokenEnd] = (char) ch;
tokenEnd++;
+ ch = read();
}
// Push back last read character since it doesn't belong to the IDENT.
diff --git a/gnu/javax/swing/text/html/css/Length.java b/gnu/javax/swing/text/html/css/Length.java
index 7091fbae7..339e2a2e0 100644
--- a/gnu/javax/swing/text/html/css/Length.java
+++ b/gnu/javax/swing/text/html/css/Length.java
@@ -54,7 +54,12 @@ public class Length
/**
* The converted value.
*/
- private float floatValue;
+ protected float floatValue;
+
+ /**
+ * Indicates when the value is a percentage value.
+ */
+ private boolean isPercentage;
/**
* Creates a new length converter instance.
@@ -65,16 +70,31 @@ public class Length
{
value = val;
int i = value.indexOf("px");
- floatValue = 0.0F;
- if (i != -1)
+ int percent = value.indexOf("%");
+ try
{
- String sub = value.substring(0, i);
- floatValue = Float.parseFloat(sub);
+ floatValue = 0.0F;
+ if (i != -1)
+ {
+ String sub = value.substring(0, i);
+ floatValue = Float.parseFloat(sub);
+ }
+ else if (percent != -1)
+ {
+ isPercentage = true;
+ String sub = value.substring(0, percent);
+ floatValue = Float.parseFloat(sub) / 100;
+ }
+ else
+ {
+ // TODO: Implement other length options.
+ floatValue = Float.parseFloat(value);
+ }
}
- else
+ catch (NumberFormatException ex)
{
- // TODO: Implement other length options.
- floatValue = Float.parseFloat(value);
+ // Don't let such small problems interrupt CSS parsing.
+ System.err.println("couldn't parse: " + val);
}
}
@@ -87,4 +107,32 @@ public class Length
{
return floatValue;
}
+
+ /**
+ * Returns the absolute span for the case when this length value is
+ * a relative value.
+ *
+ * @param available the target span
+ *
+ * @return the absolute span
+ */
+ public float getValue(float available)
+ {
+ float span = floatValue;
+ if (isPercentage)
+ span *= available;
+ return span;
+ }
+
+ /**
+ * Returns <code>true</code> when the length value is a percentage
+ * value, <code>false</code> otherwise.
+ *
+ * @return <code>true</code> when the length value is a percentage
+ * value, <code>false</code> otherwise
+ */
+ public boolean isPercentage()
+ {
+ return isPercentage;
+ }
}
diff --git a/gnu/javax/swing/text/html/css/Selector.java b/gnu/javax/swing/text/html/css/Selector.java
new file mode 100644
index 000000000..75f2d46c6
--- /dev/null
+++ b/gnu/javax/swing/text/html/css/Selector.java
@@ -0,0 +1,233 @@
+/* Selector.java -- A CSS selector
+ 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 gnu.javax.swing.text.html.css;
+
+import java.util.StringTokenizer;
+
+/**
+ * A CSS selector. This provides methods to interpret a selector and
+ * query matches with an actual HTML element tree.
+ */
+public class Selector
+{
+
+ /**
+ * The actual selector. The selector tokens are stored backwards, that
+ * is the last token first. This makes matching easier.
+ */
+ private String[] selector;
+
+ private String[] elements;
+ private String[] ids;
+ private String[] classes;
+
+ /**
+ * The specificity of the selector.
+ */
+ private int specificity;
+
+ /**
+ * An implicit selector has true here. This is the case for CSS rules that
+ * are attached to HTML elements directly via style="<CSS rule>".
+ */
+ private boolean implicit;
+
+ /**
+ * Creates a new Selector instance for the specified selector string.
+ *
+ * @param sel the selector
+ */
+ public Selector(String sel)
+ {
+ StringTokenizer selectorTokens = new StringTokenizer(sel, " ");
+ selector = new String[selectorTokens.countTokens()];
+ for (int i = selector.length - 1; selectorTokens.hasMoreTokens(); i--)
+ {
+ selector[i] = selectorTokens.nextToken();
+ }
+ calculateSpecificity();
+ }
+
+ /**
+ * Determines if this selector matches the element path specified in the
+ * arguments. The arguments hold the element names as well as class
+ * and id attibutes of the HTML element to be queried. The first item
+ * in the array is the deepest element and the last on the highest up (for
+ * instance, the html tag).
+ *
+ * @param tags
+ * @param classes
+ * @param ids
+ *
+ * @return <code>true</code> when this selector matches the element path,
+ * <code>false</code> otherwise
+ */
+ public boolean matches(String[] tags, String[] pathClasses, String[] pathIds)
+ {
+ // TODO: This implements class, id and descendent matching. These are
+ // the most commonly used selector matchers in CSS together with HTML.
+ // However, the CSS spec defines a couple of more sophisticated matches
+ // which should be implemented.
+ // http://www.w3.org/TR/CSS21/selector.html
+
+ // All parts of the selector must match at some point.
+ boolean match = false;
+ int numTags = tags.length;
+ int numSel = selector.length;
+ if (numSel <= numTags)
+ {
+ match = true;
+ int tagIndex = 0;
+ for (int j = 0; j < numSel && match; j++)
+ {
+ boolean tagMatch = false;
+ for (; tagIndex < numTags && tagMatch == false; tagIndex++)
+ {
+ String tag = elements[j];
+ String clazz = classes[j];
+ String id = ids[j];
+ tagMatch = tag.equals("") || tag.equals("*")
+ || tag.equals(tags[tagIndex]);
+ tagMatch = tagMatch && (clazz.equals("*")
+ || clazz.equals(pathClasses[tagIndex]));
+ tagMatch = tagMatch && (id.equals("*")
+ || id.equals(pathIds[tagIndex]));
+ // For the last element in the selector we must not look
+ // further.
+ if (j == 0)
+ break;
+ }
+ // If we don't come out here with a matching tag, then we're
+ // not matching at all.
+ match = tagMatch;
+ }
+ }
+ return match;
+ }
+
+ /**
+ * Returns the specificity of the selector. This is calculated according
+ * to:
+ * http://www.w3.org/TR/CSS21/cascade.html#specificity
+ *
+ * @return the specificity of the selector
+ */
+ public int getSpecificity()
+ {
+ return specificity;
+ }
+
+ /**
+ * Returns a string representation of the selector. This tries to reconstruct
+ * the original selector as closely as possible.
+ *
+ * @return a string representation of the selector
+ */
+ public String toString()
+ {
+ StringBuilder b = new StringBuilder();
+ for (int i = selector.length - 1; i >= 0; i--)
+ {
+ b.append(selector[i]);
+ if (i > 0)
+ b.append(' ');
+ }
+ return b.toString();
+ }
+
+ /**
+ * Calculates the specificity of the selector. This is calculated according
+ * to:
+ * http://www.w3.org/TR/CSS21/cascade.html#specificity
+ */
+ private void calculateSpecificity()
+ {
+ int a = implicit ? 1 : 0;
+ int b = 0;
+ int c = 0;
+ int d = 0;
+ int numSel = selector.length;
+ elements = new String[numSel];
+ ids = new String[numSel];
+ classes = new String[numSel];
+ for (int i = 0; i < numSel; i++)
+ {
+ String sel = selector[i];
+ int clazzIndex = sel.indexOf('.');
+ int idIndex = sel.indexOf('#');
+ String clazz;
+ if (clazzIndex == -1)
+ {
+ clazz = "*";
+ clazzIndex = sel.length();
+ }
+ else
+ {
+ c++;
+ clazz = sel.substring(clazzIndex + 1,
+ idIndex > 0 ? Math.min(idIndex, sel.length())
+ : sel.length());
+ }
+ String id;
+ if (idIndex == -1)
+ {
+ id = "*";
+ idIndex = sel.length();
+ }
+ else
+ {
+ b++;
+ id = sel.substring(idIndex + 1,
+ clazzIndex > 0 ? Math.min(idIndex, sel.length())
+ : sel.length());
+ }
+ String tag = sel.substring(0,
+ Math.min(Math.min(clazzIndex, idIndex),
+ sel.length()));
+ if (! tag.equals("") && ! tag.equals("*"))
+ d++;
+
+ elements[i] = tag;
+ ids[i] = id;
+ classes[i] = clazz;
+ }
+ // An order of 20 should be enough for everybody.
+ specificity = a * 20 ^ 3 + b * 20 ^ 2 + c * 20 + d;
+ }
+}
diff --git a/gnu/javax/swing/text/html/parser/GnuParserDelegator.java b/gnu/javax/swing/text/html/parser/GnuParserDelegator.java
index 841db667e..273461a72 100644
--- a/gnu/javax/swing/text/html/parser/GnuParserDelegator.java
+++ b/gnu/javax/swing/text/html/parser/GnuParserDelegator.java
@@ -43,6 +43,7 @@ import java.io.Reader;
import java.io.Serializable;
import javax.swing.text.BadLocationException;
+import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.HTMLEditorKit.ParserCallback;
import javax.swing.text.html.parser.DTD;
@@ -92,7 +93,7 @@ public class GnuParserDelegator extends ParserDelegator implements Serializable
protected final void handleStartTag(TagElement tag)
{
- htmlAttributeSet attributes = gnu.getAttributes();
+ SimpleAttributeSet attributes = gnu.getAttributes();
if (tag.fictional())
attributes.addAttribute(ParserCallback.IMPLIED, Boolean.TRUE);
diff --git a/gnu/javax/swing/text/html/parser/support/Parser.java b/gnu/javax/swing/text/html/parser/support/Parser.java
index 92f9b27c5..f1f25fad0 100644
--- a/gnu/javax/swing/text/html/parser/support/Parser.java
+++ b/gnu/javax/swing/text/html/parser/support/Parser.java
@@ -56,6 +56,7 @@ import java.util.TreeSet;
import java.util.Vector;
import javax.swing.text.ChangedCharSetException;
+import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.html.HTML;
import javax.swing.text.html.parser.AttributeList;
import javax.swing.text.html.parser.DTD;
@@ -250,9 +251,9 @@ public class Parser
* Get the attributes of the current tag.
* @return The attribute set, representing the attributes of the current tag.
*/
- public htmlAttributeSet getAttributes()
+ public SimpleAttributeSet getAttributes()
{
- return attributes;
+ return new SimpleAttributeSet(attributes);
}
/**
@@ -661,12 +662,16 @@ public class Parser
if (text != null && text.length > 0)
{
TagElement pcdata = new TagElement(dtd.getElement("#pcdata"));
- attributes = htmlAttributeSet.EMPTY_HTML_ATTRIBUTE_SET;
- _handleEmptyTag(pcdata);
+ if ((text.length > 1 && text[0] != ' ')
+ || validator.tagIsValidForContext(pcdata) == Boolean.TRUE)
+ {
+ attributes = htmlAttributeSet.EMPTY_HTML_ATTRIBUTE_SET;
+ _handleEmptyTag(pcdata);
- handleText(text);
- if (titleOpen)
- title.append(text);
+ handleText(text);
+ if (titleOpen)
+ title.append(text);
+ }
}
}
@@ -1418,8 +1423,6 @@ public class Parser
hTag = new Token(start, next);
- attributes.setResolveParent(defaulter.getDefaultParameters(name.getImage()));
-
if (!end)
{
// The tag body contains errors. If additionally the tag
diff --git a/include/gnu_java_net_VMPlainDatagramSocketImpl.h b/include/gnu_java_net_VMPlainDatagramSocketImpl.h
deleted file mode 100644
index 2bd1f4905..000000000
--- a/include/gnu_java_net_VMPlainDatagramSocketImpl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* DO NOT EDIT THIS FILE - it is machine generated */
-
-#ifndef __gnu_java_net_VMPlainDatagramSocketImpl__
-#define __gnu_java_net_VMPlainDatagramSocketImpl__
-
-#include <jni.h>
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-JNIEXPORT void JNICALL Java_gnu_java_net_VMPlainDatagramSocketImpl_bind (JNIEnv *env, jclass, jobject, jint, jobject);
-JNIEXPORT void JNICALL Java_gnu_java_net_VMPlainDatagramSocketImpl_create (JNIEnv *env, jclass, jobject);
-JNIEXPORT void JNICALL Java_gnu_java_net_VMPlainDatagramSocketImpl_connect (JNIEnv *env, jclass, jobject, jobject, jint);
-JNIEXPORT void JNICALL Java_gnu_java_net_VMPlainDatagramSocketImpl_nativeSendTo (JNIEnv *env, jclass, jobject, jobject, jint, jbyteArray, jint, jint);
-JNIEXPORT void JNICALL Java_gnu_java_net_VMPlainDatagramSocketImpl_nativeReceive (JNIEnv *env, jclass, jobject, jbyteArray, jint, jint, jbyteArray, jintArray, jintArray);
-JNIEXPORT void JNICALL Java_gnu_java_net_VMPlainDatagramSocketImpl_setOption (JNIEnv *env, jclass, jobject, jint, jobject);
-JNIEXPORT jobject JNICALL Java_gnu_java_net_VMPlainDatagramSocketImpl_getOption (JNIEnv *env, jclass, jobject, jint);
-JNIEXPORT void JNICALL Java_gnu_java_net_VMPlainDatagramSocketImpl_close (JNIEnv *env, jclass, jobject);
-JNIEXPORT void JNICALL Java_gnu_java_net_VMPlainDatagramSocketImpl_join (JNIEnv *env, jclass, jobject, jobject);
-JNIEXPORT void JNICALL Java_gnu_java_net_VMPlainDatagramSocketImpl_leave (JNIEnv *env, jclass, jobject, jobject);
-#undef gnu_java_net_VMPlainDatagramSocketImpl_IP_TTL
-#define gnu_java_net_VMPlainDatagramSocketImpl_IP_TTL 7777L
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __gnu_java_net_VMPlainDatagramSocketImpl__ */
diff --git a/include/gnu_java_nio_channels_FileChannelImpl.h b/include/gnu_java_nio_channels_FileChannelImpl.h
deleted file mode 100644
index 1e09c09dd..000000000
--- a/include/gnu_java_nio_channels_FileChannelImpl.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* DO NOT EDIT THIS FILE - it is machine generated */
-
-#ifndef __gnu_java_nio_channels_FileChannelImpl__
-#define __gnu_java_nio_channels_FileChannelImpl__
-
-#include <jni.h>
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-JNIEXPORT void JNICALL Java_gnu_java_nio_channels_FileChannelImpl_init (JNIEnv *env, jclass);
-JNIEXPORT jint JNICALL Java_gnu_java_nio_channels_FileChannelImpl_open (JNIEnv *env, jobject, jstring, jint);
-JNIEXPORT jint JNICALL Java_gnu_java_nio_channels_FileChannelImpl_available (JNIEnv *env, jobject);
-JNIEXPORT jlong JNICALL Java_gnu_java_nio_channels_FileChannelImpl_implPosition (JNIEnv *env, jobject);
-JNIEXPORT void JNICALL Java_gnu_java_nio_channels_FileChannelImpl_seek (JNIEnv *env, jobject, jlong);
-JNIEXPORT void JNICALL Java_gnu_java_nio_channels_FileChannelImpl_implTruncate (JNIEnv *env, jobject, jlong);
-JNIEXPORT void JNICALL Java_gnu_java_nio_channels_FileChannelImpl_unlock (JNIEnv *env, jobject, jlong, jlong);
-JNIEXPORT jlong JNICALL Java_gnu_java_nio_channels_FileChannelImpl_size (JNIEnv *env, jobject);
-JNIEXPORT void JNICALL Java_gnu_java_nio_channels_FileChannelImpl_implCloseChannel (JNIEnv *env, jobject);
-JNIEXPORT jint JNICALL Java_gnu_java_nio_channels_FileChannelImpl_read__ (JNIEnv *env, jobject);
-JNIEXPORT jint JNICALL Java_gnu_java_nio_channels_FileChannelImpl_read___3BII (JNIEnv *env, jobject, jbyteArray, jint, jint);
-JNIEXPORT void JNICALL Java_gnu_java_nio_channels_FileChannelImpl_write___3BII (JNIEnv *env, jobject, jbyteArray, jint, jint);
-JNIEXPORT void JNICALL Java_gnu_java_nio_channels_FileChannelImpl_write__I (JNIEnv *env, jobject, jint);
-JNIEXPORT jobject JNICALL Java_gnu_java_nio_channels_FileChannelImpl_mapImpl (JNIEnv *env, jobject, jchar, jlong, jint);
-JNIEXPORT void JNICALL Java_gnu_java_nio_channels_FileChannelImpl_force (JNIEnv *env, jobject);
-JNIEXPORT jboolean JNICALL Java_gnu_java_nio_channels_FileChannelImpl_lock (JNIEnv *env, jobject, jlong, jlong, jboolean, jboolean);
-#undef gnu_java_nio_channels_FileChannelImpl_READ
-#define gnu_java_nio_channels_FileChannelImpl_READ 1L
-#undef gnu_java_nio_channels_FileChannelImpl_WRITE
-#define gnu_java_nio_channels_FileChannelImpl_WRITE 2L
-#undef gnu_java_nio_channels_FileChannelImpl_APPEND
-#define gnu_java_nio_channels_FileChannelImpl_APPEND 4L
-#undef gnu_java_nio_channels_FileChannelImpl_EXCL
-#define gnu_java_nio_channels_FileChannelImpl_EXCL 8L
-#undef gnu_java_nio_channels_FileChannelImpl_SYNC
-#define gnu_java_nio_channels_FileChannelImpl_SYNC 16L
-#undef gnu_java_nio_channels_FileChannelImpl_DSYNC
-#define gnu_java_nio_channels_FileChannelImpl_DSYNC 32L
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __gnu_java_nio_channels_FileChannelImpl__ */
diff --git a/java/awt/FlowLayout.java b/java/awt/FlowLayout.java
index 8c9919528..70c98a29a 100644
--- a/java/awt/FlowLayout.java
+++ b/java/awt/FlowLayout.java
@@ -337,7 +337,10 @@ public class FlowLayout implements LayoutManager, Serializable
Insets ins = parent.getInsets ();
- w += (num + 1) * hgap + ins.left + ins.right;
+ if (num == 0)
+ w += 2 * hgap + ins.left + ins.right;
+ else
+ w += (num + 1) * hgap + ins.left + ins.right;
h += 2 * vgap + ins.top + ins.bottom;
return new Dimension (w, h);
diff --git a/java/awt/TextComponent.java b/java/awt/TextComponent.java
index 4fc62a951..8fdd94139 100644
--- a/java/awt/TextComponent.java
+++ b/java/awt/TextComponent.java
@@ -391,7 +391,9 @@ public class TextComponent extends Component
*/
public synchronized void setSelectionStart(int selectionStart)
{
- select(selectionStart, getSelectionEnd());
+ select(selectionStart,
+ (getSelectionEnd() < selectionStart)
+ ? selectionStart : getSelectionEnd());
}
/**
diff --git a/java/awt/TextField.java b/java/awt/TextField.java
index 2aff0ca64..b1df66f7c 100644
--- a/java/awt/TextField.java
+++ b/java/awt/TextField.java
@@ -264,9 +264,12 @@ public class TextField extends TextComponent
*/
public Dimension minimumSize(int columns)
{
+ if (isMinimumSizeSet())
+ return new Dimension(minSize);
+
TextFieldPeer peer = (TextFieldPeer) getPeer ();
if (peer == null)
- return null; // FIXME: What do we do if there is no peer?
+ return new Dimension(getWidth(), getHeight());
return peer.getMinimumSize (columns);
}
@@ -316,10 +319,13 @@ public class TextField extends TextComponent
*/
public Dimension preferredSize(int columns)
{
+ if (isPreferredSizeSet())
+ return new Dimension(prefSize);
+
TextFieldPeer peer = (TextFieldPeer) getPeer ();
if (peer == null)
- return new Dimension (0, 0);
-
+ return new Dimension (getWidth(), getHeight());
+
return peer.getPreferredSize (columns);
}
diff --git a/java/awt/Toolkit.java b/java/awt/Toolkit.java
index 9eb4da216..5ac9e2766 100644
--- a/java/awt/Toolkit.java
+++ b/java/awt/Toolkit.java
@@ -41,6 +41,7 @@ package java.awt;
import gnu.classpath.SystemProperties;
import gnu.java.awt.peer.GLightweightPeer;
+import gnu.java.awt.peer.headless.HeadlessToolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.dnd.DragGestureEvent;
@@ -554,6 +555,14 @@ public abstract class Toolkit
{
if (toolkit != null)
return toolkit;
+
+ // Check for the headless property.
+ if (GraphicsEnvironment.isHeadless())
+ {
+ toolkit = new HeadlessToolkit();
+ return toolkit;
+ }
+
String toolkit_name = SystemProperties.getProperty("awt.toolkit",
default_toolkit_name);
try
diff --git a/java/beans/SimpleBeanInfo.java b/java/beans/SimpleBeanInfo.java
index cfb960484..56b1f7aa7 100644
--- a/java/beans/SimpleBeanInfo.java
+++ b/java/beans/SimpleBeanInfo.java
@@ -1,5 +1,5 @@
/* java.beans.SimpleBeanInfo
- Copyright (C) 1998 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2006, Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -40,6 +40,7 @@ package java.beans;
import java.awt.Image;
import java.awt.Toolkit;
+import java.net.URL;
/**
** SimpleBeanInfo is a class you may extend to more easily
@@ -130,10 +131,16 @@ public class SimpleBeanInfo implements BeanInfo {
** and its BeanInfo are both loaded by the same
** ClassLoader, generally a reasonable assumption.
** @param location the URL relative
- ** @return the Image in question.
+ ** @return the Image in question (possibly <code>null</code>).
**/
- public Image loadImage(String location) {
- return Toolkit.getDefaultToolkit().getImage(getClass().getResource(location));
+ public Image loadImage(String location)
+ {
+ if (location == null)
+ return null;
+ URL url = getClass().getResource(location);
+ if (url == null)
+ return null;
+ return Toolkit.getDefaultToolkit().getImage(url);
}
}
diff --git a/java/beans/beancontext/BeanContextSupport.java b/java/beans/beancontext/BeanContextSupport.java
index a12c078df..2dc2a4e4a 100644
--- a/java/beans/beancontext/BeanContextSupport.java
+++ b/java/beans/beancontext/BeanContextSupport.java
@@ -144,42 +144,61 @@ public class BeanContextSupport extends BeanContextChildSupport
*/
public BeanContextSupport ()
{
- this (null, null, true, true);
+ this (null, null, false, true);
}
/**
* Construct a BeanContextSupport instance.
+ *
+ * @param peer the bean context peer (<code>null</code> permitted).
*/
- public BeanContextSupport (BeanContext peer)
+ public BeanContextSupport(BeanContext peer)
{
- this (peer, null, true, true);
+ this (peer, null, false, true);
}
/**
* Construct a BeanContextSupport instance.
+ *
+ * @param peer the bean context peer (<code>null</code> permitted).
+ * @param locale the locale (<code>null</code> permitted, equivalent to
+ * the default locale).
*/
- public BeanContextSupport (BeanContext peer, Locale lcle)
+ public BeanContextSupport (BeanContext peer, Locale locale)
{
- this (peer, lcle, true, true);
+ this (peer, locale, false, true);
}
/**
* Construct a BeanContextSupport instance.
+ *
+ * @param peer the bean context peer (<code>null</code> permitted).
+ * @param locale the locale (<code>null</code> permitted, equivalent to
+ * the default locale).
+ * @param dtime a flag indicating whether or not the bean context is in
+ * design time mode.
*/
- public BeanContextSupport (BeanContext peer, Locale lcle, boolean dtime)
+ public BeanContextSupport (BeanContext peer, Locale locale, boolean dtime)
{
- this (peer, lcle, dtime, true);
+ this (peer, locale, dtime, true);
}
/**
* Construct a BeanContextSupport instance.
+ *
+ * @param peer the bean context peer (<code>null</code> permitted).
+ * @param locale the locale (<code>null</code> permitted, equivalent to
+ * the default locale).
+ * @param dtime a flag indicating whether or not the bean context is in
+ * design time mode.
+ * @param visible initial value of the <code>okToUseGui</code> flag.
*/
- public BeanContextSupport (BeanContext peer, Locale lcle, boolean dtime,
+ public BeanContextSupport (BeanContext peer, Locale locale, boolean dtime,
boolean visible)
{
super(peer);
- locale = lcle == null ? Locale.getDefault() : lcle;
+ this.locale = locale == null ? Locale.getDefault() : locale;
designTime = dtime;
okToUseGui = visible;
@@ -447,16 +466,40 @@ public class BeanContextSupport extends BeanContextChildSupport
}
}
- public BeanContext getBeanContextPeer ()
- throws NotImplementedException
+ /**
+ * Returns the bean context peer.
+ *
+ * @return The bean context peer.
+ *
+ * @see BeanContextChildSupport#beanContextChildPeer
+ */
+ public BeanContext getBeanContextPeer()
{
- throw new Error ("Not implemented");
+ return (BeanContext) beanContextChildPeer;
}
- protected static final BeanContextChild getChildBeanContextChild (Object child)
- throws NotImplementedException
- {
- throw new Error ("Not implemented");
+ /**
+ * Returns the {@link BeanContextChild} implementation for the given child.
+ *
+ * @param child the child (<code>null</code> permitted).
+ *
+ * @return The bean context child.
+ *
+ * @throws IllegalArgumentException if <code>child</code> implements both
+ * the {@link BeanContextChild} and {@link BeanContextProxy} interfaces.
+ */
+ protected static final BeanContextChild getChildBeanContextChild(Object child)
+ {
+ if (child == null)
+ return null;
+ if (child instanceof BeanContextChild && child instanceof BeanContextProxy)
+ throw new IllegalArgumentException("Child cannot implement "
+ + "BeanContextChild and BeanContextProxy simultaneously.");
+ if (child instanceof BeanContextChild)
+ return (BeanContextChild) child;
+ if (child instanceof BeanContextProxy)
+ return ((BeanContextProxy) child).getBeanContextProxy();
+ return null;
}
protected static final BeanContextMembershipListener getChildBeanContextMembershipListener (Object child)
diff --git a/java/io/OutputStreamWriter.java b/java/io/OutputStreamWriter.java
index 572683834..26363401f 100644
--- a/java/io/OutputStreamWriter.java
+++ b/java/io/OutputStreamWriter.java
@@ -223,6 +223,7 @@ public class OutputStreamWriter extends Writer
encoder.onMalformedInput(CodingErrorAction.REPLACE);
encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
outputBuffer = CharBuffer.allocate(BUFFER_SIZE);
+ encodingName = EncodingHelper.getOldCanonical(cs.name());
}
/**
@@ -240,6 +241,11 @@ public class OutputStreamWriter extends Writer
this.out = out;
encoder = enc;
outputBuffer = CharBuffer.allocate(BUFFER_SIZE);
+ Charset cs = enc.charset();
+ if (cs == null)
+ encodingName = "US-ASCII";
+ else
+ encodingName = EncodingHelper.getOldCanonical(cs.name());
}
/**
diff --git a/java/util/Collections.java b/java/util/Collections.java
index cd4a6fb40..c15fa092b 100644
--- a/java/util/Collections.java
+++ b/java/util/Collections.java
@@ -2068,10 +2068,11 @@ public class Collections
* sorts the array, and then iterates over the list setting each element from
* the array.
*
- * @param l the List to sort
+ * @param l the List to sort (<code>null</code> not permitted)
* @throws ClassCastException if some items are not mutually comparable
* @throws UnsupportedOperationException if the List is not modifiable
- * @throws NullPointerException if some element is null
+ * @throws NullPointerException if the list is <code>null</code>, or contains
+ * some element that is <code>null</code>.
* @see Arrays#sort(Object[])
*/
public static <T extends Comparable<? super T>> void sort(List<T> l)
@@ -2087,13 +2088,15 @@ public class Collections
* sorts the array, and then iterates over the list setting each element from
* the array.
*
- * @param l the List to sort
+ * @param l the List to sort (<code>null</code> not permitted)
* @param c the Comparator specifying the ordering for the elements, or
- * null for natural ordering
+ * <code>null</code> for natural ordering
* @throws ClassCastException if c will not compare some pair of items
* @throws UnsupportedOperationException if the List is not modifiable
- * @throws NullPointerException if null is compared by natural ordering
- * (only possible when c is null)
+ * @throws NullPointerException if the List is <code>null</code> or
+ * <code>null</code> is compared by natural ordering (only possible
+ * when c is <code>null</code>)
+ *
* @see Arrays#sort(Object[], Comparator)
*/
public static <T> void sort(List<T> l, Comparator<? super T> c)
diff --git a/java/util/regex/Matcher.java b/java/util/regex/Matcher.java
index 3ddd42547..bf833673b 100644
--- a/java/util/regex/Matcher.java
+++ b/java/util/regex/Matcher.java
@@ -278,6 +278,7 @@ public final class Matcher implements MatchResult
public Matcher reset (CharSequence input)
{
this.input = input;
+ this.inputCharIndexed = RE.makeCharIndexed(input, 0);
return reset();
}
diff --git a/javax/swing/JLabel.java b/javax/swing/JLabel.java
index 3e0f28ed7..721287b21 100644
--- a/javax/swing/JLabel.java
+++ b/javax/swing/JLabel.java
@@ -431,11 +431,11 @@ public class JLabel extends JComponent implements Accessible, SwingConstants
* Creates a new vertically and horizontally centered
* JLabel object with no text and the given icon.
*
- * @param image The icon to use with the label.
+ * @param image The icon to use with the label, <code>null</code> permitted.
*/
public JLabel(Icon image)
{
- this("", image, CENTER);
+ this(null, image, CENTER);
}
/**
@@ -443,19 +443,21 @@ public class JLabel extends JComponent implements Accessible, SwingConstants
* given icon and horizontal alignment. By default, the text is TRAILING
* the image.
*
- * @param image The icon to use with the label.
- * @param horizontalAlignment The horizontal alignment of the label.
+ * @param image The icon to use with the label, <code>null</code> premitted.
+ * @param horizontalAlignment The horizontal alignment of the label, must be
+ * either <code>CENTER</code>, <code>LEFT</code>, <code>RIGHT</code>,
+ * <code>LEADING</code> or <code>TRAILING</code>.
*/
public JLabel(Icon image, int horizontalAlignment)
{
- this("", image, horizontalAlignment);
+ this(null, image, horizontalAlignment);
}
/**
* Creates a new horizontally leading and vertically centered JLabel
* object with no icon and the given text.
*
- * @param text The text to use with the label.
+ * @param text The text to use with the label, <code>null</code> permitted.
*/
public JLabel(String text)
{
@@ -466,8 +468,10 @@ public class JLabel extends JComponent implements Accessible, SwingConstants
* Creates a new vertically centered JLabel object with no icon and the
* given text and horizontal alignment.
*
- * @param text The text to use with the label.
- * @param horizontalAlignment The horizontal alignment of the label.
+ * @param text The text to use with the label, <code>null</code> permitted.
+ * @param horizontalAlignment The horizontal alignment of the label, must be
+ * either <code>CENTER</code>, <code>LEFT</code>, <code>RIGHT</code>,
+ * <code>LEADING</code> or <code>TRAILING</code>.
*/
public JLabel(String text, int horizontalAlignment)
{
@@ -478,12 +482,21 @@ public class JLabel extends JComponent implements Accessible, SwingConstants
* Creates a new vertically centered JLabel object with the given text,
* icon, and horizontal alignment.
*
- * @param text The text to use with the label.
- * @param icon The icon to use with the label.
- * @param horizontalAlignment The horizontal alignment of the label.
+ * @param text The text to use with the label, <code>null</code> permitted.
+ * @param icon The icon to use with the label, <code>null</code> premitted.
+ * @param horizontalAlignment The horizontal alignment of the label, must be
+ * either <code>CENTER</code>, <code>LEFT</code>, <code>RIGHT</code>,
+ * <code>LEADING</code> or <code>TRAILING</code>.
*/
public JLabel(String text, Icon icon, int horizontalAlignment)
{
+ if (horizontalAlignment != SwingConstants.LEFT
+ && horizontalAlignment != SwingConstants.RIGHT
+ && horizontalAlignment != SwingConstants.CENTER
+ && horizontalAlignment != SwingConstants.LEADING
+ && horizontalAlignment != SwingConstants.TRAILING)
+ throw new IllegalArgumentException();
+
this.text = text;
this.icon = icon;
this.horizontalAlignment = horizontalAlignment;
diff --git a/javax/swing/JTree.java b/javax/swing/JTree.java
index c6f08b49c..332ec7424 100644
--- a/javax/swing/JTree.java
+++ b/javax/swing/JTree.java
@@ -1230,8 +1230,32 @@ public class JTree extends JComponent implements Scrollable, Accessible
*/
public void treeNodesRemoved(TreeModelEvent ev)
{
- // TODO: The API docs suggest that this method should do something
- // but I cannot really see what has to be done here ...
+ if (ev != null)
+ {
+ TreePath parent = ev.getTreePath();
+ Object[] children = ev.getChildren();
+ TreeSelectionModel sm = getSelectionModel();
+ if (children != null)
+ {
+ TreePath path;
+ Vector toRemove = new Vector();
+ // Collect items that we must remove.
+ for (int i = children.length - 1; i >= 0; i--)
+ {
+ path = parent.pathByAddingChild(children[i]);
+ if (nodeStates.containsKey(path))
+ toRemove.add(path);
+ // Clear selection while we are at it.
+ if (sm != null)
+ removeDescendantSelectedPaths(path, true);
+ }
+ if (toRemove.size() > 0)
+ removeDescendantToggledPaths(toRemove.elements());
+ TreeModel model = getModel();
+ if (model == null || model.isLeaf(parent.getLastPathComponent()))
+ nodeStates.remove(parent);
+ }
+ }
}
/**
@@ -1243,9 +1267,38 @@ public class JTree extends JComponent implements Scrollable, Accessible
*/
public void treeStructureChanged(TreeModelEvent ev)
{
- // Set state of new path.
- TreePath path = ev.getTreePath();
- setExpandedState(path, isExpanded(path));
+ if (ev != null)
+ {
+ TreePath parent = ev.getTreePath();
+ if (parent != null)
+ {
+ if (parent.getPathCount() == 1)
+ {
+ // We have a new root, clear everything.
+ clearToggledPaths();
+ Object root = treeModel.getRoot();
+ if (root != null && treeModel.isLeaf(root))
+ nodeStates.put(parent, Boolean.TRUE);
+ }
+ else if (nodeStates.containsKey(parent))
+ {
+ Vector toRemove = new Vector();
+ boolean expanded = isExpanded(parent);
+ toRemove.add(parent);
+ removeDescendantToggledPaths(toRemove.elements());
+ if (expanded)
+ {
+ TreeModel model = getModel();
+ if (model != null
+ || model.isLeaf(parent.getLastPathComponent()))
+ collapsePath(parent);
+ else
+ nodeStates.put(parent, Boolean.TRUE);
+ }
+ }
+ removeDescendantSelectedPaths(parent, false);
+ }
+ }
}
}
@@ -1399,8 +1452,10 @@ public class JTree extends JComponent implements Scrollable, Accessible
* This contains the state of all nodes in the tree. Al/ entries map the
* TreePath of a note to to its state. Valid states are EXPANDED and
* COLLAPSED. Nodes not in this Hashtable are assumed state COLLAPSED.
+ *
+ * This is package private to avoid accessor methods.
*/
- private Hashtable nodeStates = new Hashtable();
+ Hashtable nodeStates = new Hashtable();
protected transient TreeCellEditor cellEditor;
@@ -2201,20 +2256,35 @@ public class JTree extends JComponent implements Scrollable, Accessible
public void setSelectionPath(TreePath path)
{
+ clearSelectionPathStates();
selectionModel.setSelectionPath(path);
}
public void setSelectionPaths(TreePath[] paths)
{
+ clearSelectionPathStates();
selectionModel.setSelectionPaths(paths);
}
+
+ /**
+ * This method, and all calls to it, should be removed once the
+ * DefaultTreeModel fires events properly. Maintenance of the nodeStates
+ * table should really be done in the TreeModelHandler.
+ */
+ private void clearSelectionPathStates()
+ {
+ TreePath[] oldPaths = selectionModel.getSelectionPaths();
+ if (oldPaths != null)
+ for (int i = 0; i < oldPaths.length; i++)
+ nodeStates.remove(oldPaths[i]);
+ }
public void setSelectionRow(int row)
{
TreePath path = getPathForRow(row);
if (path != null)
- selectionModel.setSelectionPath(path);
+ setSelectionPath(path);
}
public void setSelectionRows(int[] rows)
@@ -2289,11 +2359,13 @@ public class JTree extends JComponent implements Scrollable, Accessible
public void removeSelectionPath(TreePath path)
{
+ clearSelectionPathStates();
selectionModel.removeSelectionPath(path);
}
public void removeSelectionPaths(TreePath[] paths)
{
+ clearSelectionPathStates();
selectionModel.removeSelectionPaths(paths);
}
@@ -2302,7 +2374,7 @@ public class JTree extends JComponent implements Scrollable, Accessible
TreePath path = getPathForRow(row);
if (path != null)
- selectionModel.removeSelectionPath(path);
+ removeSelectionPath(path);
}
public void removeSelectionRows(int[] rows)
diff --git a/javax/swing/text/ComponentView.java b/javax/swing/text/ComponentView.java
index 555120396..8de4de60f 100644
--- a/javax/swing/text/ComponentView.java
+++ b/javax/swing/text/ComponentView.java
@@ -397,7 +397,24 @@ public class ComponentView extends View
{
public void run()
{
- setParentImpl();
+ Document doc = getDocument();
+ try
+ {
+ if (doc instanceof AbstractDocument)
+ ((AbstractDocument) doc).readLock();
+ setParentImpl();
+ Container host = getContainer();
+ if (host != null)
+ {
+ preferenceChanged(null, true, true);
+ host.repaint();
+ }
+ }
+ finally
+ {
+ if (doc instanceof AbstractDocument)
+ ((AbstractDocument) doc).readUnlock();
+ }
}
});
}
diff --git a/javax/swing/text/CompositeView.java b/javax/swing/text/CompositeView.java
index ab587a9e1..d4467f314 100644
--- a/javax/swing/text/CompositeView.java
+++ b/javax/swing/text/CompositeView.java
@@ -134,7 +134,7 @@ public abstract class CompositeView
public void setParent(View parent)
{
super.setParent(parent);
- if (parent != null && ((children == null) || children.length == 0))
+ if (parent != null && numChildren == 0)
loadChildren(getViewFactory());
}
diff --git a/javax/swing/text/FlowView.java b/javax/swing/text/FlowView.java
index cee5bb126..9609f3fc8 100644
--- a/javax/swing/text/FlowView.java
+++ b/javax/swing/text/FlowView.java
@@ -189,7 +189,7 @@ public abstract class FlowView extends BoxView
// Then remove all views from the flow view.
fv.removeAll();
-
+
for (int rowIndex = 0; start < end; rowIndex++)
{
View row = fv.createRow();
@@ -318,8 +318,8 @@ public abstract class FlowView extends BoxView
int rowIndex)
{
View logicalView = getLogicalView(fv);
- // FIXME: Handle the bias thing correctly.
- int index = logicalView.getViewIndex(startOffset, Position.Bias.Forward);
+ int index = logicalView.getViewIndex(startOffset,
+ Position.Bias.Forward);
View retVal = logicalView.getView(index);
if (retVal.getStartOffset() != startOffset)
retVal = retVal.createFragment(startOffset, retVal.getEndOffset());
@@ -603,6 +603,7 @@ public abstract class FlowView extends BoxView
{
super(element, axis);
strategy = sharedStrategy;
+ layoutSpan = Short.MAX_VALUE;
}
/**
@@ -651,7 +652,7 @@ public abstract class FlowView extends BoxView
*/
public int getFlowStart(int index)
{
- return getLeftInset(); // TODO: Is this correct?
+ return 0;
}
/**
@@ -678,8 +679,8 @@ public abstract class FlowView extends BoxView
if (layoutPool == null)
{
layoutPool = new LogicalView(getElement());
- layoutPool.setParent(this);
}
+ layoutPool.setParent(this);
// Initialize the flow strategy.
strategy.insertUpdate(this, null, null);
}
@@ -696,21 +697,17 @@ public abstract class FlowView extends BoxView
protected void layout(int width, int height)
{
int flowAxis = getFlowAxis();
+ int span;
if (flowAxis == X_AXIS)
- {
- if (layoutSpan != width)
- {
- layoutChanged(Y_AXIS);
- layoutSpan = width;
- }
- }
+ span = (int) width;
else
+ span = (int) height;
+
+ if (layoutSpan != span)
{
- if (layoutSpan != height)
- {
- layoutChanged(X_AXIS);
- layoutSpan = height;
- }
+ layoutChanged(flowAxis);
+ layoutChanged(getAxis());
+ layoutSpan = span;
}
if (! isLayoutValid(flowAxis))
diff --git a/javax/swing/text/GlyphView.java b/javax/swing/text/GlyphView.java
index cb7f8f05d..35c8dd5d7 100644
--- a/javax/swing/text/GlyphView.java
+++ b/javax/swing/text/GlyphView.java
@@ -252,6 +252,8 @@ public class GlyphView extends View implements TabableView, Cloneable
*/
static class DefaultGlyphPainter extends GlyphPainter
{
+ FontMetrics fontMetrics;
+
/**
* Returns the full height of the rendered text.
*
@@ -259,9 +261,8 @@ public class GlyphView extends View implements TabableView, Cloneable
*/
public float getHeight(GlyphView view)
{
- Font font = view.getFont();
- FontMetrics metrics = Toolkit.getDefaultToolkit().getFontMetrics(font);
- float height = metrics.getHeight();
+ updateFontMetrics(view);
+ float height = fontMetrics.getHeight();
return height;
}
@@ -341,16 +342,16 @@ public class GlyphView extends View implements TabableView, Cloneable
Shape a)
throws BadLocationException
{
+ updateFontMetrics(view);
Element el = view.getElement();
- Font font = view.getFont();
- FontMetrics fm = view.getContainer().getFontMetrics(font);
Segment txt = view.getText(el.getStartOffset(), pos);
Rectangle bounds = a instanceof Rectangle ? (Rectangle) a
: a.getBounds();
TabExpander expander = view.getTabExpander();
- int width = Utilities.getTabbedTextWidth(txt, fm, bounds.x, expander,
+ int width = Utilities.getTabbedTextWidth(txt, fontMetrics, bounds.x,
+ expander,
view.getStartOffset());
- int height = fm.getHeight();
+ int height = fontMetrics.getHeight();
Rectangle result = new Rectangle(bounds.x + width, bounds.y,
0, height);
return result;
@@ -375,10 +376,10 @@ public class GlyphView extends View implements TabableView, Cloneable
public float getSpan(GlyphView view, int p0, int p1,
TabExpander te, float x)
{
- Font font = view.getFont();
- FontMetrics fm = Toolkit.getDefaultToolkit().getFontMetrics(font);
+ updateFontMetrics(view);
Segment txt = view.getText(p0, p1);
- int span = Utilities.getTabbedTextWidth(txt, fm, (int) x, te, p0);
+ int span = Utilities.getTabbedTextWidth(txt, fontMetrics, (int) x, te,
+ p0);
return span;
}
@@ -395,9 +396,8 @@ public class GlyphView extends View implements TabableView, Cloneable
*/
public float getAscent(GlyphView v)
{
- Font font = v.getFont();
- FontMetrics fm = v.getContainer().getFontMetrics(font);
- return fm.getAscent();
+ updateFontMetrics(v);
+ return fontMetrics.getAscent();
}
/**
@@ -413,9 +413,8 @@ public class GlyphView extends View implements TabableView, Cloneable
*/
public float getDescent(GlyphView v)
{
- Font font = v.getFont();
- FontMetrics fm = v.getContainer().getFontMetrics(font);
- return fm.getDescent();
+ updateFontMetrics(v);
+ return fontMetrics.getDescent();
}
/**
@@ -430,16 +429,10 @@ public class GlyphView extends View implements TabableView, Cloneable
*/
public int getBoundedPosition(GlyphView v, int p0, float x, float len)
{
+ updateFontMetrics(v);
TabExpander te = v.getTabExpander();
Segment txt = v.getText(p0, v.getEndOffset());
- Font font = v.getFont();
- Container c = v.getContainer();
- FontMetrics fm;
- if (c != null)
- fm = c.getFontMetrics(font);
- else
- fm = Toolkit.getDefaultToolkit().getFontMetrics(font);
- int pos = Utilities.getTabbedTextOffset(txt, fm, (int) x,
+ int pos = Utilities.getTabbedTextOffset(txt, fontMetrics, (int) x,
(int) (x + len), te, p0, false);
return pos + p0;
}
@@ -458,9 +451,33 @@ public class GlyphView extends View implements TabableView, Cloneable
public int viewToModel(GlyphView v, float x, float y, Shape a,
Bias[] biasRet)
{
- Rectangle b = a.getBounds();
- int pos = getBoundedPosition(v, v.getStartOffset(), b.x, x - b.x);
- return pos + v.getStartOffset();
+ Rectangle r = a instanceof Rectangle ? (Rectangle) a : a.getBounds();
+ int p0 = v.getStartOffset();
+ int p1 = v.getEndOffset();
+ TabExpander te = v.getTabExpander();
+ Segment s = v.getText(p0, p1);
+ int offset = Utilities.getTabbedTextOffset(s, fontMetrics, r.x, (int) x,
+ te, p0);
+ int ret = p0 + offset;
+ if (ret == p1)
+ ret--;
+ biasRet[0] = Position.Bias.Forward;
+ return ret;
+ }
+
+ private void updateFontMetrics(GlyphView v)
+ {
+ Font font = v.getFont();
+ if (fontMetrics == null || ! font.equals(fontMetrics.getFont()))
+ {
+ Container c = v.getContainer();
+ FontMetrics fm;
+ if (c != null)
+ fm = c.getFontMetrics(font);
+ else
+ fm = Toolkit.getDefaultToolkit().getFontMetrics(font);
+ fontMetrics = fm;
+ }
}
}
diff --git a/javax/swing/text/ParagraphView.java b/javax/swing/text/ParagraphView.java
index 6a13b2a3e..fb4ac65d8 100644
--- a/javax/swing/text/ParagraphView.java
+++ b/javax/swing/text/ParagraphView.java
@@ -38,6 +38,9 @@ exception statement from your version. */
package javax.swing.text;
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Rectangle;
import java.awt.Shape;
import javax.swing.SizeRequirements;
@@ -104,19 +107,6 @@ public class ParagraphView extends FlowView implements TabExpander
}
/**
- * Allows rows to span the whole parent view.
- */
- public float getMaximumSpan(int axis)
- {
- float max;
- if (axis == X_AXIS)
- max = Float.MAX_VALUE;
- else
- max = super.getMaximumSpan(axis);
- return max;
- }
-
- /**
* Overridden because child views are not necessarily laid out in model
* order.
*/
diff --git a/javax/swing/text/View.java b/javax/swing/text/View.java
index aafd76a4f..dc611fe49 100644
--- a/javax/swing/text/View.java
+++ b/javax/swing/text/View.java
@@ -92,7 +92,14 @@ public abstract class View implements SwingConstants
{
int numChildren = getViewCount();
for (int i = 0; i < numChildren; i++)
- getView(i).setParent(null);
+ {
+ View child = getView(i);
+ // It is important that we only reset the parent on views that
+ // actually belong to us. In FlowView the child may already be
+ // reparented.
+ if (child.getParent() == this)
+ child.setParent(null);
+ }
}
this.parent = parent;
@@ -262,7 +269,7 @@ public abstract class View implements SwingConstants
public void removeAll()
{
- replace(0, getViewCount(), new View[0]);
+ replace(0, getViewCount(), null);
}
public void remove(int index)
@@ -618,10 +625,12 @@ public abstract class View implements SwingConstants
DocumentEvent ev, Shape shape)
{
if (ec != null && shape != null)
- preferenceChanged(null, true, true);
- Container c = getContainer();
- if (c != null)
- c.repaint();
+ {
+ preferenceChanged(null, true, true);
+ Container c = getContainer();
+ if (c != null)
+ c.repaint();
+ }
}
/**
diff --git a/javax/swing/text/html/BlockView.java b/javax/swing/text/html/BlockView.java
index 6274e7b17..d7519ef9a 100644
--- a/javax/swing/text/html/BlockView.java
+++ b/javax/swing/text/html/BlockView.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package javax.swing.text.html;
+import gnu.javax.swing.text.html.css.Length;
+
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Shape;
@@ -55,7 +57,24 @@ import javax.swing.text.ViewFactory;
*/
public class BlockView extends BoxView
{
-
+
+ /**
+ * The attributes for this view.
+ */
+ private AttributeSet attributes;
+
+ /**
+ * The box painter for this view.
+ */
+ private StyleSheet.BoxPainter painter;
+
+ /**
+ * The width and height as specified in the stylesheet, null if not
+ * specified. The first value is the X_AXIS, the second the Y_AXIS. You
+ * can index this directly by the X_AXIS and Y_AXIS constants.
+ */
+ private Length[] cssSpans;
+
/**
* Creates a new view that represents an html box.
* This can be used for a number of elements.
@@ -66,8 +85,9 @@ public class BlockView extends BoxView
public BlockView(Element elem, int axis)
{
super(elem, axis);
+ cssSpans = new Length[2];
}
-
+
/**
* Creates the parent view for this. It is called before
* any other methods, if the parent view is working properly.
@@ -99,12 +119,27 @@ public class BlockView extends BoxView
protected SizeRequirements calculateMajorAxisRequirements(int axis,
SizeRequirements r)
{
- SizeRequirements sr = super.calculateMajorAxisRequirements(axis, r);
- // FIXME: adjust it if the CSS width or height attribute is specified
- // and applicable
- return sr;
+ if (r == null)
+ r = new SizeRequirements();
+
+ if (setCSSSpan(r, axis))
+ {
+ // If we have set the span from CSS, then we need to adjust
+ // the margins.
+ SizeRequirements parent = super.calculateMajorAxisRequirements(axis,
+ null);
+ int margin = axis == X_AXIS ? getLeftInset() + getRightInset()
+ : getTopInset() + getBottomInset();
+ r.minimum -= margin;
+ r.preferred -= margin;
+ r.maximum -= margin;
+ constrainSize(axis, r, parent);
+ }
+ else
+ r = super.calculateMajorAxisRequirements(axis, r);
+ return r;
}
-
+
/**
* Calculates the requirements along the minor axis.
* This is implemented to call the superclass and then
@@ -118,12 +153,73 @@ public class BlockView extends BoxView
protected SizeRequirements calculateMinorAxisRequirements(int axis,
SizeRequirements r)
{
- SizeRequirements sr = super.calculateMinorAxisRequirements(axis, r);
- // FIXME: adjust it if the CSS width or height attribute is specified
- // and applicable.
- return sr;
+ if (r == null)
+ r = new SizeRequirements();
+
+ if (setCSSSpan(r, axis))
+ {
+ // If we have set the span from CSS, then we need to adjust
+ // the margins.
+ SizeRequirements parent = super.calculateMinorAxisRequirements(axis,
+ null);
+ int margin = axis == X_AXIS ? getLeftInset() + getRightInset()
+ : getTopInset() + getBottomInset();
+ r.minimum -= margin;
+ r.preferred -= margin;
+ r.maximum -= margin;
+ constrainSize(axis, r, parent);
+ }
+ else
+ r = super.calculateMinorAxisRequirements(axis, r);
+ return r;
}
-
+
+ /**
+ * Sets the span on the SizeRequirements object according to the
+ * according CSS span value, when it is set.
+ *
+ * @param r the size requirements
+ * @param axis the axis
+ *
+ * @return <code>true</code> when the CSS span has been set,
+ * <code>false</code> otherwise
+ */
+ private boolean setCSSSpan(SizeRequirements r, int axis)
+ {
+ boolean ret = false;
+ Length span = cssSpans[axis];
+ // We can't set relative CSS spans here because we don't know
+ // yet about the allocated span. Instead we use the view's
+ // normal requirements.
+ if (span != null && ! span.isPercentage())
+ {
+ r.minimum = (int) span.getValue();
+ r.preferred = (int) span.getValue();
+ r.maximum = (int) span.getValue();
+ ret = true;
+ }
+ return ret;
+ }
+
+ /**
+ * Constrains the <code>r</code> requirements according to
+ * <code>min</code>.
+ *
+ * @param axis the axis
+ * @param r the requirements to constrain
+ * @param min the constraining requirements
+ */
+ private void constrainSize(int axis, SizeRequirements r,
+ SizeRequirements min)
+ {
+ if (min.minimum > r.minimum)
+ {
+ r.minimum = min.minimum;
+ r.preferred = min.minimum;
+ r.maximum = Math.max(r.maximum, min.maximum);
+ }
+ }
+
/**
* Lays out the box along the minor axis (the axis that is
* perpendicular to the axis that it represents). The results
@@ -142,10 +238,40 @@ public class BlockView extends BoxView
protected void layoutMinorAxis(int targetSpan, int axis,
int[] offsets, int[] spans)
{
- // FIXME: Not implemented.
- super.layoutMinorAxis(targetSpan, axis, offsets, spans);
+ int viewCount = getViewCount();
+ CSS.Attribute spanAtt = axis == X_AXIS ? CSS.Attribute.WIDTH
+ : CSS.Attribute.HEIGHT;
+ for (int i = 0; i < viewCount; i++)
+ {
+ View view = getView(i);
+ int min = (int) view.getMinimumSpan(axis);
+ int max;
+ // Handle CSS span value of child.
+ AttributeSet atts = view.getAttributes();
+ Length length = (Length) atts.getAttribute(spanAtt);
+ if (length != null)
+ {
+ min = Math.max((int) length.getValue(targetSpan), min);
+ max = min;
+ }
+ else
+ max = (int) view.getMaximumSpan(axis);
+
+ if (max < targetSpan)
+ {
+ // Align child.
+ float align = view.getAlignment(axis);
+ offsets[i] = (int) ((targetSpan - max) * align);
+ spans[i] = max;
+ }
+ else
+ {
+ offsets[i] = 0;
+ spans[i] = Math.max(min, targetSpan);
+ }
+ }
}
-
+
/**
* Paints using the given graphics configuration and shape.
* This delegates to the css box painter to paint the
@@ -156,11 +282,8 @@ public class BlockView extends BoxView
*/
public void paint(Graphics g, Shape a)
{
- Rectangle rect = (Rectangle) a;
- // FIXME: not fully implemented
- getStyleSheet().getBoxPainter(getAttributes()).paint(g, rect.x, rect.y,
- rect.width,
- rect.height, this);
+ Rectangle rect = a instanceof Rectangle ? (Rectangle) a : a.getBounds();
+ painter.paint(g, rect.x, rect.y, rect.width, rect.height, this);
super.paint(g, a);
}
@@ -171,7 +294,9 @@ public class BlockView extends BoxView
*/
public AttributeSet getAttributes()
{
- return getStyleSheet().getViewAttributes(this);
+ if (attributes == null)
+ attributes = getStyleSheet().getViewAttributes(this);
+ return attributes;
}
/**
@@ -206,8 +331,11 @@ public class BlockView extends BoxView
if (getViewCount() == 0)
return 0.0F;
float prefHeight = getPreferredSpan(Y_AXIS);
- float firstRowHeight = getView(0).getPreferredSpan(Y_AXIS);
- return (firstRowHeight / 2.F) / prefHeight;
+ View first = getView(0);
+ float firstRowHeight = first.getPreferredSpan(Y_AXIS);
+ return prefHeight != 0 ? (firstRowHeight * first.getAlignment(Y_AXIS))
+ / prefHeight
+ : 0;
}
throw new IllegalArgumentException("Invalid Axis");
}
@@ -227,7 +355,8 @@ public class BlockView extends BoxView
// If more elements were added, then need to set the properties for them
int currPos = ev.getOffset();
- if (currPos <= getStartOffset() && (currPos + ev.getLength()) >= getEndOffset())
+ if (currPos <= getStartOffset()
+ && (currPos + ev.getLength()) >= getEndOffset())
setPropertiesFromAttributes();
}
@@ -284,9 +413,27 @@ public class BlockView extends BoxView
*/
protected void setPropertiesFromAttributes()
{
- // FIXME: Not implemented (need to use StyleSheet).
+ // Fetch attributes.
+ StyleSheet ss = getStyleSheet();
+ attributes = ss.getViewAttributes(this);
+
+ // Fetch painter.
+ painter = ss.getBoxPainter(attributes);
+
+ // Update insets.
+ if (attributes != null)
+ {
+ setInsets((short) painter.getInset(TOP, this),
+ (short) painter.getInset(LEFT, this),
+ (short) painter.getInset(BOTTOM, this),
+ (short) painter.getInset(RIGHT, this));
+ }
+
+ // Fetch width and height.
+ cssSpans[X_AXIS] = (Length) attributes.getAttribute(CSS.Attribute.WIDTH);
+ cssSpans[Y_AXIS] = (Length) attributes.getAttribute(CSS.Attribute.HEIGHT);
}
-
+
/**
* Gets the default style sheet.
*
@@ -294,8 +441,7 @@ public class BlockView extends BoxView
*/
protected StyleSheet getStyleSheet()
{
- StyleSheet styleSheet = new StyleSheet();
- styleSheet.importStyleSheet(getClass().getResource(HTMLEditorKit.DEFAULT_CSS));
- return styleSheet;
+ HTMLDocument doc = (HTMLDocument) getDocument();
+ return doc.getStyleSheet();
}
}
diff --git a/javax/swing/text/html/CSS.java b/javax/swing/text/html/CSS.java
index 20a2debbc..6461dca9a 100644
--- a/javax/swing/text/html/CSS.java
+++ b/javax/swing/text/html/CSS.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.swing.text.html;
+import gnu.javax.swing.text.html.css.BorderWidth;
import gnu.javax.swing.text.html.css.CSSColor;
import gnu.javax.swing.text.html.css.FontSize;
import gnu.javax.swing.text.html.css.FontStyle;
@@ -45,6 +46,9 @@ import gnu.javax.swing.text.html.css.Length;
import java.io.Serializable;
import java.util.HashMap;
+import java.util.StringTokenizer;
+
+import javax.swing.text.MutableAttributeSet;
/**
* Provides CSS attributes to be used by the HTML view classes. The constants
@@ -394,6 +398,24 @@ public class CSS implements Serializable
public static final Attribute WORD_SPACING =
new Attribute("word-spacing", true, "normal");
+ // Some GNU Classpath specific extensions.
+ static final Attribute BORDER_TOP_STYLE =
+ new Attribute("border-top-style", false, null);
+ static final Attribute BORDER_BOTTOM_STYLE =
+ new Attribute("border-bottom-style", false, null);
+ static final Attribute BORDER_LEFT_STYLE =
+ new Attribute("border-left-style", false, null);
+ static final Attribute BORDER_RIGHT_STYLE =
+ new Attribute("border-right-style", false, null);
+ static final Attribute BORDER_TOP_COLOR =
+ new Attribute("border-top-color", false, null);
+ static final Attribute BORDER_BOTTOM_COLOR =
+ new Attribute("border-bottom-color", false, null);
+ static final Attribute BORDER_LEFT_COLOR =
+ new Attribute("border-left-color", false, null);
+ static final Attribute BORDER_RIGHT_COLOR =
+ new Attribute("border-right-color", false, null);
+
/**
* The attribute string.
*/
@@ -484,14 +506,44 @@ public class CSS implements Serializable
o = new FontWeight(v);
else if (att == Attribute.FONT_STYLE)
o = new FontStyle(v);
- else if (att == Attribute.COLOR || att == Attribute.BACKGROUND_COLOR)
+ else if (att == Attribute.COLOR || att == Attribute.BACKGROUND_COLOR
+ || att == Attribute.BORDER_COLOR
+ || att == Attribute.BORDER_TOP_COLOR
+ || att == Attribute.BORDER_BOTTOM_COLOR
+ || att == Attribute.BORDER_LEFT_COLOR
+ || att == Attribute.BORDER_RIGHT_COLOR)
o = new CSSColor(v);
else if (att == Attribute.MARGIN || att == Attribute.MARGIN_BOTTOM
|| att == Attribute.MARGIN_LEFT || att == Attribute.MARGIN_RIGHT
- || att == Attribute.MARGIN_TOP)
+ || att == Attribute.MARGIN_TOP || att == Attribute.WIDTH
+ || att == Attribute.HEIGHT)
o = new Length(v);
+ else if (att == Attribute.BORDER_WIDTH || att == Attribute.BORDER_TOP_WIDTH
+ || att == Attribute.BORDER_LEFT_WIDTH
+ || att == Attribute.BORDER_RIGHT_WIDTH
+ || att == Attribute.BORDER_BOTTOM_WIDTH)
+ o = new BorderWidth(v);
else
o = v;
return o;
}
+
+ static void addInternal(MutableAttributeSet atts, Attribute a, String v)
+ {
+ if (a == Attribute.BACKGROUND)
+ parseBackgroundShorthand(atts, v);
+ }
+
+ private static void parseBackgroundShorthand(MutableAttributeSet atts,
+ String v)
+ {
+ StringTokenizer tokens = new StringTokenizer(v, " ");
+ while (tokens.hasMoreElements())
+ {
+ String token = tokens.nextToken();
+ if (CSSColor.isValidColor(token))
+ atts.addAttribute(Attribute.BACKGROUND_COLOR,
+ getValue(Attribute.BACKGROUND_COLOR, token));
+ }
+ }
}
diff --git a/javax/swing/text/html/CSSBorder.java b/javax/swing/text/html/CSSBorder.java
new file mode 100644
index 000000000..540955494
--- /dev/null
+++ b/javax/swing/text/html/CSSBorder.java
@@ -0,0 +1,420 @@
+/* CSSBorder.java -- A border for rendering CSS border styles
+ 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.html;
+
+import gnu.javax.swing.text.html.css.BorderWidth;
+import gnu.javax.swing.text.html.css.CSSColor;
+import gnu.javax.swing.text.html.css.Length;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Insets;
+
+import javax.swing.border.Border;
+import javax.swing.text.AttributeSet;
+
+/**
+ * A border implementation to render CSS border styles.
+ */
+class CSSBorder
+ implements Border
+{
+
+ /**
+ * The CSS border styles.
+ */
+
+ private static final int STYLE_NOT_SET = -1;
+ private static final int STYLE_NONE = 0;
+ private static final int STYLE_HIDDEN = 1;
+ private static final int STYLE_DOTTED = 2;
+ private static final int STYLE_DASHED = 3;
+ private static final int STYLE_SOLID = 4;
+ private static final int STYLE_DOUBLE = 5;
+ private static final int STYLE_GROOVE = 6;
+ private static final int STYLE_RIDGE = 7;
+ private static final int STYLE_INSET = 8;
+ private static final int STYLE_OUTSET = 9;
+
+ /**
+ * The left insets.
+ */
+ private int left;
+
+ /**
+ * The right insets.
+ */
+ private int right;
+
+ /**
+ * The top insets.
+ */
+ private int top;
+
+ /**
+ * The bottom insets.
+ */
+ private int bottom;
+
+ /**
+ * The border style on the left.
+ */
+ private int leftStyle;
+
+ /**
+ * The border style on the right.
+ */
+ private int rightStyle;
+
+ /**
+ * The border style on the top.
+ */
+ private int topStyle;
+
+ /**
+ * The color for the top border.
+ */
+ private Color topColor;
+
+ /**
+ * The color for the bottom border.
+ */
+ private Color bottomColor;
+
+ /**
+ * The color for the left border.
+ */
+ private Color leftColor;
+
+ /**
+ * The color for the right border.
+ */
+ private Color rightColor;
+
+ /**
+ * The border style on the bottom.
+ */
+ private int bottomStyle;
+
+ /**
+ * Creates a new CSS border and fetches its attributes from the specified
+ * attribute set.
+ *
+ * @param atts the attribute set that contains the border spec
+ */
+ CSSBorder(AttributeSet atts)
+ {
+ // Determine the border styles.
+ int style = getBorderStyle(atts, CSS.Attribute.BORDER_STYLE);
+ if (style == STYLE_NOT_SET)
+ style = STYLE_NONE; // Default to none.
+ topStyle = bottomStyle = leftStyle = rightStyle = style;
+ style = getBorderStyle(atts, CSS.Attribute.BORDER_TOP_STYLE);
+ if (style != STYLE_NOT_SET)
+ topStyle = style;
+ style = getBorderStyle(atts, CSS.Attribute.BORDER_BOTTOM_STYLE);
+ if (style != STYLE_NOT_SET)
+ bottomStyle = style;
+ style = getBorderStyle(atts, CSS.Attribute.BORDER_LEFT_STYLE);
+ if (style != STYLE_NOT_SET)
+ leftStyle = style;
+ style = getBorderStyle(atts, CSS.Attribute.BORDER_RIGHT_STYLE);
+ if (style != STYLE_NOT_SET)
+ rightStyle = style;
+
+ // Determine the border colors.
+ Color color = getBorderColor(atts, CSS.Attribute.BORDER_COLOR);
+ if (color == null)
+ color = Color.BLACK;
+ topColor = bottomColor = leftColor = rightColor = color;
+ color = getBorderColor(atts, CSS.Attribute.BORDER_TOP_COLOR);
+ if (color != null)
+ topColor = color;
+ color = getBorderColor(atts, CSS.Attribute.BORDER_BOTTOM_COLOR);
+ if (color != null)
+ bottomColor = color;
+ color = getBorderColor(atts, CSS.Attribute.BORDER_LEFT_COLOR);
+ if (color != null)
+ leftColor = color;
+ color = getBorderColor(atts, CSS.Attribute.BORDER_RIGHT_COLOR);
+ if (color != null)
+ rightColor = color;
+
+ // Determine the border widths.
+ int width = getBorderWidth(atts, CSS.Attribute.BORDER_WIDTH);
+ if (width == -1)
+ width = 0;
+ top = bottom = left = right = width;
+ width = getBorderWidth(atts, CSS.Attribute.BORDER_TOP_WIDTH);
+ if (width >= 0)
+ top = width;
+ width = getBorderWidth(atts, CSS.Attribute.BORDER_BOTTOM_WIDTH);
+ if (width >= 0)
+ bottom = width;
+ width = getBorderWidth(atts, CSS.Attribute.BORDER_LEFT_WIDTH);
+ if (width >= 0)
+ left = width;
+ width = getBorderWidth(atts, CSS.Attribute.BORDER_RIGHT_WIDTH);
+ if (width >= 0)
+ right = width;
+ }
+
+ /**
+ * Determines the border style for a given CSS attribute.
+ *
+ * @param atts the attribute set
+ * @param key the CSS key
+ *
+ * @return the border style according to the constants defined in this class
+ */
+ private int getBorderStyle(AttributeSet atts, CSS.Attribute key)
+ {
+ int style = STYLE_NOT_SET;
+ Object o = atts.getAttribute(key);
+ if (o != null)
+ {
+ String cssStyle = o.toString();
+ if (cssStyle.equals("none"))
+ style = STYLE_NONE;
+ else if (cssStyle.equals("hidden"))
+ style = STYLE_HIDDEN;
+ else if (cssStyle.equals("dotted"))
+ style = STYLE_DOTTED;
+ else if (cssStyle.equals("dashed"))
+ style = STYLE_DASHED;
+ else if (cssStyle.equals("solid"))
+ style = STYLE_SOLID;
+ else if (cssStyle.equals("double"))
+ style = STYLE_DOUBLE;
+ else if (cssStyle.equals("groove"))
+ style = STYLE_GROOVE;
+ else if (cssStyle.equals("ridge"))
+ style = STYLE_RIDGE;
+ else if (cssStyle.equals("inset"))
+ style = STYLE_INSET;
+ else if (cssStyle.equals("outset"))
+ style = STYLE_OUTSET;
+ }
+ return style;
+ }
+
+ /**
+ * Determines the border color for the specified key.
+ *
+ * @param atts the attribute set from which to fetch the color
+ * @param key the CSS key
+ *
+ * @return the border color
+ */
+ private Color getBorderColor(AttributeSet atts, CSS.Attribute key)
+ {
+ Object o = atts.getAttribute(key);
+ Color color = null;
+ if (o instanceof CSSColor)
+ {
+ CSSColor cssColor = (CSSColor) o;
+ color = cssColor.getValue();
+ }
+ return color;
+ }
+
+ /**
+ * Returns the width for the specified key.
+ *
+ * @param atts the attributes to fetch the width from
+ * @param key the CSS key
+ *
+ * @return the width, or -1 of none has been set
+ */
+ private int getBorderWidth(AttributeSet atts, CSS.Attribute key)
+ {
+ int width = -1;
+ Object o = atts.getAttribute(key);
+ if (o instanceof BorderWidth)
+ {
+ width = (int) ((BorderWidth) o).getValue();
+ }
+ return width;
+ }
+
+ /**
+ * Returns the border insets.
+ */
+ public Insets getBorderInsets(Component c)
+ {
+ return new Insets(top, left, bottom, right);
+ }
+
+ /**
+ * CSS borders are generally opaque so return true here.
+ */
+ public boolean isBorderOpaque()
+ {
+ return true;
+ }
+
+ public void paintBorder(Component c, Graphics g, int x, int y, int width,
+ int height)
+ {
+ // Top border.
+ paintBorderLine(g, x, y + top / 2, x + width, y + top / 2, topStyle, top,
+ topColor, false);
+ // Left border.
+ paintBorderLine(g, x + left / 2, y, x + left / 2, y + height, leftStyle,
+ left, leftColor, true);
+ // Bottom border.
+ paintBorderLine(g, x, y + height - bottom / 2, x + width,
+ y + height - bottom / 2, topStyle, bottom, bottomColor,
+ false);
+ // Right border.
+ paintBorderLine(g, x + width - right / 2, y, x + width - right / 2,
+ y + height, topStyle, right, rightColor, true);
+
+ }
+
+ private void paintBorderLine(Graphics g, int x1, int y1, int x2, int y2,
+ int style, int width, Color color,
+ boolean vertical)
+ {
+ switch (style)
+ {
+ case STYLE_DOTTED:
+ paintDottedLine(g, x1, y1, x2, y2, width, color, vertical);
+ break;
+ case STYLE_DASHED:
+ paintDashedLine(g, x1, y1, x2, y2, width, color, vertical);
+ break;
+ case STYLE_SOLID:
+ paintSolidLine(g, x1, y1, x2, y2, width, color, vertical);
+ break;
+ case STYLE_DOUBLE:
+ paintDoubleLine(g, x1, y1, x2, y2, width, color, vertical);
+ break;
+ case STYLE_GROOVE:
+ paintGrooveLine(g, x1, y1, x2, y2, width, color, vertical);
+ break;
+ case STYLE_RIDGE:
+ paintRidgeLine(g, x1, y1, x2, y2, width, color, vertical);
+ break;
+ case STYLE_OUTSET:
+ paintOutsetLine(g, x1, y1, x2, y2, width, color, vertical);
+ break;
+ case STYLE_INSET:
+ paintInsetLine(g, x1, y1, x2, y2, width, color, vertical);
+ break;
+ case STYLE_NONE:
+ case STYLE_HIDDEN:
+ default:
+ // Nothing to do in these cases.
+ }
+ }
+
+ private void paintDottedLine(Graphics g, int x1, int y1, int x2, int y2,
+ int width, Color color, boolean vertical)
+ {
+ // FIXME: Implement this.
+ paintSolidLine(g, x1, y1, x2, y2, width, color, vertical);
+ }
+
+ private void paintDashedLine(Graphics g, int x1, int y1, int x2, int y2,
+ int width, Color color, boolean vertical)
+ {
+ // FIXME: Implement this.
+ paintSolidLine(g, x1, y1, x2, y2, width, color, vertical);
+ }
+
+ private void paintSolidLine(Graphics g, int x1, int y1, int x2, int y2,
+ int width, Color color, boolean vertical)
+ {
+ int x = Math.min(x1, x2);
+ int y = Math.min(y1, y1);
+ int w = Math.abs(x2 - x1);
+ int h = Math.abs(y2 - y1);
+ if (vertical)
+ {
+ w = width;
+ x -= width / 2;
+ }
+ else
+ {
+ h = width;
+ y -= width / 2;
+ }
+ g.setColor(color);
+ g.fillRect(x, y, w, h);
+ }
+
+ private void paintDoubleLine(Graphics g, int x1, int y1, int x2, int y2,
+ int width, Color color, boolean vertical)
+ {
+ // FIXME: Implement this.
+ paintSolidLine(g, x1, y1, x2, y2, width, color, vertical);
+ }
+
+ private void paintGrooveLine(Graphics g, int x1, int y1, int x2, int y2,
+ int width, Color color, boolean vertical)
+ {
+ // FIXME: Implement this.
+ paintSolidLine(g, x1, y1, x2, y2, width, color, vertical);
+ }
+
+ private void paintRidgeLine(Graphics g, int x1, int y1, int x2, int y2,
+ int width, Color color, boolean vertical)
+ {
+ // FIXME: Implement this.
+ paintSolidLine(g, x1, y1, x2, y2, width, color, vertical);
+ }
+
+ private void paintOutsetLine(Graphics g, int x1, int y1, int x2, int y2,
+ int width, Color color, boolean vertical)
+ {
+ // FIXME: Implement this.
+ paintSolidLine(g, x1, y1, x2, y2, width, color, vertical);
+ }
+
+ private void paintInsetLine(Graphics g, int x1, int y1, int x2, int y2,
+ int width, Color color, boolean vertical)
+ {
+ // FIXME: Implement this.
+ paintSolidLine(g, x1, y1, x2, y2, width, color, vertical);
+ }
+
+}
diff --git a/javax/swing/text/html/HTMLDocument.java b/javax/swing/text/html/HTMLDocument.java
index 2e2eb3abc..26e3fb4bc 100644
--- a/javax/swing/text/html/HTMLDocument.java
+++ b/javax/swing/text/html/HTMLDocument.java
@@ -39,10 +39,10 @@ exception statement from your version. */
package javax.swing.text.html;
import gnu.classpath.NotImplementedException;
-import gnu.javax.swing.text.html.parser.htmlAttributeSet;
import java.io.IOException;
import java.io.StringReader;
+import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
@@ -571,6 +571,16 @@ public class HTMLDocument extends DefaultStyledDocument
boolean inPreTag = false;
/**
+ * True when we are inside a paragraph (P, H1-H6, P-IMPLIED).
+ */
+ boolean inParagraph = false;
+
+ /**
+ * True when we are currently inside an implied paragraph.
+ */
+ boolean inImpliedParagraph = false;
+
+ /**
* This is true when we are inside a style tag. This will add text
* content inside this style tag beeing parsed as CSS.
*
@@ -600,12 +610,6 @@ public class HTMLDocument extends DefaultStyledDocument
*/
Document textAreaDocument;
- void print (String line)
- {
- if (debug)
- System.out.println (line);
- }
-
public class TagAction
{
/**
@@ -813,6 +817,7 @@ public class HTMLDocument extends DefaultStyledDocument
public void start(HTML.Tag t, MutableAttributeSet a)
{
blockOpen(t, a);
+ inParagraph = true;
}
/**
@@ -822,6 +827,7 @@ public class HTMLDocument extends DefaultStyledDocument
public void end(HTML.Tag t)
{
blockClose(t);
+ inParagraph = false;
}
}
@@ -882,7 +888,6 @@ public class HTMLDocument extends DefaultStyledDocument
throws NotImplementedException
{
// FIXME: Implement.
- print ("AreaAction.start not implemented");
}
/**
@@ -893,7 +898,6 @@ public class HTMLDocument extends DefaultStyledDocument
throws NotImplementedException
{
// FIXME: Implement.
- print ("AreaAction.end not implemented");
}
}
@@ -942,7 +946,6 @@ public class HTMLDocument extends DefaultStyledDocument
throws NotImplementedException
{
// FIXME: Implement.
- print ("BaseAction.start not implemented");
}
/**
@@ -953,7 +956,6 @@ public class HTMLDocument extends DefaultStyledDocument
throws NotImplementedException
{
// FIXME: Implement.
- print ("BaseAction.end not implemented");
}
}
@@ -967,7 +969,6 @@ public class HTMLDocument extends DefaultStyledDocument
throws NotImplementedException
{
// FIXME: Implement.
- print ("HeadAction.start not implemented: "+t);
super.start(t, a);
}
@@ -992,29 +993,71 @@ public class HTMLDocument extends DefaultStyledDocument
}
}
- class LinkAction extends TagAction
+ class LinkAction extends HiddenAction
{
/**
* This method is called when a start tag is seen for one of the types
* of tags associated with this Action.
*/
public void start(HTML.Tag t, MutableAttributeSet a)
- throws NotImplementedException
{
- // FIXME: Implement.
- print ("LinkAction.start not implemented");
+ super.start(t, a);
+ String type = (String) a.getAttribute(HTML.Attribute.TYPE);
+ if (type == null)
+ type = "text/css";
+ if (type.equals("text/css"))
+ {
+ String rel = (String) a.getAttribute(HTML.Attribute.REL);
+ String media = (String) a.getAttribute(HTML.Attribute.MEDIA);
+ String title = (String) a.getAttribute(HTML.Attribute.TITLE);
+ if (media == null)
+ media = "all";
+ else
+ media = media.toLowerCase();
+ if (rel != null)
+ {
+ rel = rel.toLowerCase();
+ if ((media.indexOf("all") != -1
+ || media.indexOf("screen") != -1)
+ && (rel.equals("stylesheet")))
+ {
+ String href = (String) a.getAttribute(HTML.Attribute.HREF);
+ URL url = null;
+ try
+ {
+ url = new URL(baseURL, href);
+ }
+ catch (MalformedURLException ex)
+ {
+ try
+ {
+ url = new URL(href);
+ }
+ catch (MalformedURLException ex2)
+ {
+ url = null;
+ }
+ }
+ if (url != null)
+ {
+ try
+ {
+ getStyleSheet().importStyleSheet(url);
+ }
+ catch (Exception ex)
+ {
+ // Don't let exceptions and runtime exceptions
+ // in CSS parsing disprupt the HTML parsing
+ // process. But inform the user/developer
+ // on the console about it.
+ ex.printStackTrace();
+ }
+ }
+ }
+ }
+ }
}
- /**
- * Called when an end tag is seen for one of the types of tags associated
- * with this Action.
- */
- public void end(HTML.Tag t)
- throws NotImplementedException
- {
- // FIXME: Implement.
- print ("LinkAction.end not implemented");
- }
}
class MapAction extends TagAction
@@ -1027,7 +1070,6 @@ public class HTMLDocument extends DefaultStyledDocument
throws NotImplementedException
{
// FIXME: Implement.
- print ("MapAction.start not implemented");
}
/**
@@ -1038,7 +1080,6 @@ public class HTMLDocument extends DefaultStyledDocument
throws NotImplementedException
{
// FIXME: Implement.
- print ("MapAction.end not implemented");
}
}
@@ -1052,7 +1093,6 @@ public class HTMLDocument extends DefaultStyledDocument
throws NotImplementedException
{
// FIXME: Implement.
- print ("MetaAction.start not implemented");
}
/**
@@ -1063,7 +1103,6 @@ public class HTMLDocument extends DefaultStyledDocument
throws NotImplementedException
{
// FIXME: Implement.
- print ("MetaAction.end not implemented");
}
}
@@ -1098,7 +1137,6 @@ public class HTMLDocument extends DefaultStyledDocument
throws NotImplementedException
{
// FIXME: Implement.
- print ("TitleAction.start not implemented");
}
/**
@@ -1109,7 +1147,6 @@ public class HTMLDocument extends DefaultStyledDocument
throws NotImplementedException
{
// FIXME: Implement.
- print ("TitleAction.end not implemented");
}
}
@@ -1121,9 +1158,6 @@ public class HTMLDocument extends DefaultStyledDocument
public HTMLReader(int offset, int popDepth, int pushDepth,
HTML.Tag insertTag)
{
- print ("HTMLReader created with pop: "+popDepth
- + " push: "+pushDepth + " offset: "+offset
- + " tag: "+insertTag);
this.insertTag = insertTag;
this.offset = offset;
this.popDepth = popDepth;
@@ -1351,8 +1385,7 @@ public class HTMLDocument extends DefaultStyledDocument
TagAction action = (TagAction) tagToAction.get(HTML.Tag.COMMENT);
if (action != null)
{
- action.start(HTML.Tag.COMMENT,
- htmlAttributeSet.EMPTY_HTML_ATTRIBUTE_SET);
+ action.start(HTML.Tag.COMMENT, new SimpleAttributeSet());
action.end(HTML.Tag.COMMENT);
}
}
@@ -1414,7 +1447,6 @@ public class HTMLDocument extends DefaultStyledDocument
public void handleEndOfLineString(String eol)
{
// FIXME: Implement.
- print ("HTMLReader.handleEndOfLineString not implemented yet");
}
/**
@@ -1475,7 +1507,9 @@ public class HTMLDocument extends DefaultStyledDocument
*/
protected void blockOpen(HTML.Tag t, MutableAttributeSet attr)
{
- printBuffer();
+ if (inImpliedParagraph)
+ blockClose(HTML.Tag.IMPLIED);
+
DefaultStyledDocument.ElementSpec element;
parseStack.push(t);
@@ -1485,7 +1519,6 @@ public class HTMLDocument extends DefaultStyledDocument
element = new DefaultStyledDocument.ElementSpec(copy,
DefaultStyledDocument.ElementSpec.StartTagType);
parseBuffer.addElement(element);
- printBuffer();
}
/**
@@ -1496,9 +1529,16 @@ public class HTMLDocument extends DefaultStyledDocument
*/
protected void blockClose(HTML.Tag t)
{
- printBuffer();
DefaultStyledDocument.ElementSpec element;
+ if (inImpliedParagraph)
+ {
+ inImpliedParagraph = false;
+ inParagraph = false;
+ if (t != HTML.Tag.IMPLIED)
+ blockClose(HTML.Tag.IMPLIED);
+ }
+
// If the previous tag is a start tag then we insert a synthetic
// content tag.
DefaultStyledDocument.ElementSpec prev;
@@ -1519,7 +1559,6 @@ public class HTMLDocument extends DefaultStyledDocument
element = new DefaultStyledDocument.ElementSpec(null,
DefaultStyledDocument.ElementSpec.EndTagType);
parseBuffer.addElement(element);
- printBuffer();
if (parseStack.size() > 0)
parseStack.pop();
}
@@ -1550,6 +1589,13 @@ public class HTMLDocument extends DefaultStyledDocument
protected void addContent(char[] data, int offs, int length,
boolean generateImpliedPIfNecessary)
{
+ if (generateImpliedPIfNecessary && (! inParagraph) && (! inPreTag))
+ {
+ blockOpen(HTML.Tag.IMPLIED, new SimpleAttributeSet());
+ inParagraph = true;
+ inImpliedParagraph = true;
+ }
+
AbstractDocument.AttributeContext ctx = getAttributeContext();
DefaultStyledDocument.ElementSpec element;
AttributeSet attributes = null;
@@ -1566,10 +1612,8 @@ public class HTMLDocument extends DefaultStyledDocument
DefaultStyledDocument.ElementSpec.ContentType,
data, offs, length);
- printBuffer();
// Add the element to the buffer
parseBuffer.addElement(element);
- printBuffer();
if (parseBuffer.size() > HTMLDocument.this.getTokenThreshold())
{
@@ -1592,29 +1636,25 @@ public class HTMLDocument extends DefaultStyledDocument
*/
protected void addSpecialElement(HTML.Tag t, MutableAttributeSet a)
{
+ if (t != HTML.Tag.FRAME && ! inParagraph && ! inImpliedParagraph)
+ {
+ blockOpen(HTML.Tag.IMPLIED, new SimpleAttributeSet());
+ inParagraph = true;
+ inImpliedParagraph = true;
+ }
+
a.addAttribute(StyleConstants.NameAttribute, t);
- // Migrate from the rather htmlAttributeSet to the faster, lighter and
- // unchangeable alternative implementation.
- AttributeSet copy = a.copyAttributes();
-
// The two spaces are required because some special elements like HR
// must be broken. At least two characters are needed to break into the
// two parts.
DefaultStyledDocument.ElementSpec spec =
- new DefaultStyledDocument.ElementSpec(copy,
+ new DefaultStyledDocument.ElementSpec(a.copyAttributes(),
DefaultStyledDocument.ElementSpec.ContentType,
new char[] {' ', ' '}, 0, 2 );
parseBuffer.add(spec);
}
- void printBuffer()
- {
- print ("\n*********BUFFER**********");
- for (int i = 0; i < parseBuffer.size(); i ++)
- print (" "+parseBuffer.get(i));
- print ("***************************");
- }
}
/**
diff --git a/javax/swing/text/html/HTMLEditorKit.java b/javax/swing/text/html/HTMLEditorKit.java
index c541a4d34..85d5221d3 100644
--- a/javax/swing/text/html/HTMLEditorKit.java
+++ b/javax/swing/text/html/HTMLEditorKit.java
@@ -82,7 +82,7 @@ import javax.swing.text.html.parser.ParserDelegator;
/* Move these imports here after javax.swing.text.html to make it compile
with jikes. */
import gnu.javax.swing.text.html.parser.GnuParserDelegator;
-import gnu.javax.swing.text.html.parser.HTML_401Swing;
+import gnu.javax.swing.text.html.parser.HTML_401F;
/**
* @author Lillian Angel (langel at redhat dot com)
@@ -646,15 +646,12 @@ public class HTMLEditorKit
else if (tag.equals(HTML.Tag.IMG))
view = new ImageView(element);
- // FIXME: Uncomment when the views have been implemented
else if (tag.equals(HTML.Tag.CONTENT))
view = new InlineView(element);
else if (tag == HTML.Tag.HEAD)
view = new NullView(element);
else if (tag.equals(HTML.Tag.TABLE))
view = new javax.swing.text.html.TableView(element);
- else if (tag.equals(HTML.Tag.TD))
- view = new ParagraphView(element);
else if (tag.equals(HTML.Tag.HR))
view = new HRuleView(element);
else if (tag.equals(HTML.Tag.BR))
@@ -663,10 +660,11 @@ public class HTMLEditorKit
|| tag.equals(HTML.Tag.TEXTAREA))
view = new FormView(element);
- /*
else if (tag.equals(HTML.Tag.MENU) || tag.equals(HTML.Tag.DIR)
|| tag.equals(HTML.Tag.UL) || tag.equals(HTML.Tag.OL))
view = new ListView(element);
+ // FIXME: Uncomment when the views have been implemented
+ /*
else if (tag.equals(HTML.Tag.OBJECT))
view = new ObjectView(element);
else if (tag.equals(HTML.Tag.FRAMESET))
@@ -973,7 +971,7 @@ public class HTMLEditorKit
{
if (parser == null)
{
- parser = new GnuParserDelegator(HTML_401Swing.getInstance());
+ parser = new GnuParserDelegator(HTML_401F.getInstance());
}
return parser;
}
diff --git a/javax/swing/text/html/HTMLWriter.java b/javax/swing/text/html/HTMLWriter.java
index 16e9a7163..44119c732 100644
--- a/javax/swing/text/html/HTMLWriter.java
+++ b/javax/swing/text/html/HTMLWriter.java
@@ -608,28 +608,8 @@ public class HTMLWriter
closeOutUnwantedEmbeddedTags(attrSet);
- // NOTE: 20061030 - fchoong - GNU CP uses a different implimentation of
- // the IMPLIED tag.
- boolean fg_gnu_cp_implied_tag = false;
-
- if (matchNameAttribute(attrSet, HTML.Tag.P))
- {
- //writeAllAttributes(attrSet);
-
- Enumeration attrNameEnum = attrSet.getAttributeNames();
-
- while (attrNameEnum.hasMoreElements())
- {
- Object key = attrNameEnum.nextElement();
- Object value = attrSet.getAttribute(key);
-
- if (key.equals("_implied_") && value.toString().equals("true"))
- fg_gnu_cp_implied_tag = true;
- } // while(attrNameEnum.hasMoreElements())
- } // if(matchNameAttribute(attrSet, HTML.Tag.P))
-
// handle the tag
- if (synthesizedElement(paramElem) || fg_gnu_cp_implied_tag)
+ if (synthesizedElement(paramElem))
{
if (matchNameAttribute(attrSet, HTML.Tag.CONTENT))
{
@@ -640,8 +620,7 @@ public class HTMLWriter
{
comment(currElem);
} // else if(matchNameAttribute(attrSet, HTML.Tag.COMMENT))
- else if (matchNameAttribute(attrSet, HTML.Tag.IMPLIED)
- || fg_gnu_cp_implied_tag) // NOTE: GNU CP specific
+ else if (matchNameAttribute(attrSet, HTML.Tag.IMPLIED))
{
int child_elem_count = currElem.getElementCount();
@@ -782,28 +761,8 @@ public class HTMLWriter
if (fg_is_fragment_parent_elem || (fg_pass_start_elem
&& fg_pass_end_elem == false) || fg_is_start_and_end_elem)
{
- // NOTE: 20061030 - fchoong - GNU CP uses a different implimentation of
- // the IMPLIED tag.
- boolean fg_gnu_cp_implied_tag = false;
-
- if (matchNameAttribute(attrSet, HTML.Tag.P))
- {
- //writeAllAttributes(attrSet);
-
- Enumeration attrNameEnum = attrSet.getAttributeNames();
-
- while (attrNameEnum.hasMoreElements())
- {
- Object key = attrNameEnum.nextElement();
- Object value = attrSet.getAttribute(key);
-
- if (key.equals("_implied_") && value.toString().equals("true"))
- fg_gnu_cp_implied_tag = true;
- } // while(attrNameEnum.hasMoreElements())
- } // if(matchNameAttribute(attrSet, HTML.Tag.P))
-
// handle the tag
- if (synthesizedElement(paramElem) || fg_gnu_cp_implied_tag)
+ if (synthesizedElement(paramElem))
{
if (matchNameAttribute(attrSet, HTML.Tag.CONTENT))
{
@@ -862,8 +821,7 @@ public class HTMLWriter
{
comment(currElem);
} // else if(matchNameAttribute(attrSet, HTML.Tag.COMMENT))
- else if (matchNameAttribute(attrSet, HTML.Tag.IMPLIED)
- || fg_gnu_cp_implied_tag) // NOTE: GNU CP specific
+ else if (matchNameAttribute(attrSet, HTML.Tag.IMPLIED))
{
int child_elem_count = currElem.getElementCount();
diff --git a/javax/swing/text/html/InlineView.java b/javax/swing/text/html/InlineView.java
index 31eaa129c..6b134ae39 100644
--- a/javax/swing/text/html/InlineView.java
+++ b/javax/swing/text/html/InlineView.java
@@ -38,13 +38,17 @@ exception statement from your version. */
package javax.swing.text.html;
+import java.awt.FontMetrics;
import java.awt.Shape;
+import java.text.BreakIterator;
import javax.swing.event.DocumentEvent;
import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.LabelView;
+import javax.swing.text.Segment;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
@@ -65,6 +69,18 @@ public class InlineView
private AttributeSet attributes;
/**
+ * The span of the longest word in this view.
+ *
+ * @see #getLongestWord()
+ */
+ private float longestWord;
+
+ /**
+ * Indicates if we may wrap or not.
+ */
+ private boolean nowrap;
+
+ /**
* Creates a new <code>InlineView</code> that renders the specified element.
*
* @param element the element for this view
@@ -144,8 +160,13 @@ public class InlineView
public int getBreakWeight(int axis, float pos, float len)
{
- // FIXME: Implement this.
- return super.getBreakWeight(axis, pos, len);
+ int weight;
+ if (nowrap) { if (getText(getStartOffset(), getEndOffset()).toString().contains("Web"))
+ System.err.println("Web NOWRAP");
+ weight = BadBreakWeight;}
+ else
+ weight = super.getBreakWeight(axis, pos, len);
+ return weight;
}
public View breakView(int axis, int offset, float pos, float len)
@@ -190,7 +211,12 @@ public class InlineView
b = true;
setSuperscript(b);
- // TODO: Handle white-space: nowrap property.
+ // Fetch nowrap setting.
+ o = atts.getAttribute(CSS.Attribute.WHITE_SPACE);
+ if (o != null && o.equals("nowrap"))
+ nowrap = true;
+ else
+ nowrap = false;
}
/**
@@ -207,4 +233,74 @@ public class InlineView
styleSheet = ((HTMLDocument) doc).getStyleSheet();
return styleSheet;
}
+
+ /**
+ * Returns the minimum span for the specified axis. This returns the
+ * width of the longest word for the X axis and the super behaviour for
+ * the Y axis. This is a slight deviation from the reference implementation.
+ * IMO this should improve rendering behaviour so that an InlineView never
+ * gets smaller than the longest word in it.
+ */
+ public float getMinimumSpan(int axis)
+ {
+ float min = super.getMinimumSpan(axis);
+ if (axis == X_AXIS)
+ min = Math.max(getLongestWord(), min);
+ return min;
+ }
+
+ /**
+ * Returns the span of the longest word in this view.
+ *
+ * @return the span of the longest word in this view
+ */
+ private float getLongestWord()
+ {
+ if (longestWord == -1)
+ longestWord = calculateLongestWord();
+ return longestWord;
+ }
+
+ /**
+ * Calculates the span of the longest word in this view.
+ *
+ * @return the span of the longest word in this view
+ */
+ private float calculateLongestWord()
+ {
+ float span = 0;
+ try
+ {
+ Document doc = getDocument();
+ int p0 = getStartOffset();
+ int p1 = getEndOffset();
+ Segment s = new Segment();
+ doc.getText(p0, p1 - p0, s);
+ BreakIterator iter = BreakIterator.getWordInstance();
+ iter.setText(s);
+ int wordStart = p0;
+ int wordEnd = p0;
+ int start = iter.first();
+ for (int end = iter.next(); end != BreakIterator.DONE;
+ start = end, end = iter.next())
+ {
+ if ((end - start) > (wordEnd - wordStart))
+ {
+ wordStart = start;
+ wordEnd = end;
+ }
+ }
+ if (wordEnd - wordStart > 0)
+ {
+ FontMetrics fm = getFontMetrics();
+ int offset = s.offset + wordStart - s.getBeginIndex();
+ span = fm.charsWidth(s.array, offset, wordEnd - wordStart);
+ }
+ }
+ catch (BadLocationException ex)
+ {
+ // Return 0.
+ }
+ return span;
+ }
}
diff --git a/javax/swing/text/html/ListView.java b/javax/swing/text/html/ListView.java
index c07d3598c..3e809bbd2 100644
--- a/javax/swing/text/html/ListView.java
+++ b/javax/swing/text/html/ListView.java
@@ -94,9 +94,6 @@ public class ListView
public void paint(Graphics g, Shape allocation)
{
super.paint(g, allocation);
- // FIXME: Why is this overridden? I think that painting would be done
- // by the superclass and the stylesheet... Maybe find out when this
- // stuff is implemented properly.
}
/**
diff --git a/javax/swing/text/html/ParagraphView.java b/javax/swing/text/html/ParagraphView.java
index 951f70b60..e3f2817be 100644
--- a/javax/swing/text/html/ParagraphView.java
+++ b/javax/swing/text/html/ParagraphView.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package javax.swing.text.html;
+import gnu.javax.swing.text.html.css.Length;
+
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Shape;
@@ -71,6 +73,16 @@ public class ParagraphView
private StyleSheet.BoxPainter painter;
/**
+ * The width as specified in the stylesheet or null if not specified.
+ */
+ private Length cssWidth;
+
+ /**
+ * The height as specified in the stylesheet or null if not specified.
+ */
+ private Length cssHeight;
+
+ /**
* Creates a new ParagraphView for the specified element.
*
* @param element the element
@@ -116,29 +128,34 @@ public class ParagraphView
super.setPropertiesFromAttributes();
// Fetch CSS attributes.
- AttributeSet atts = getAttributes();
- Object o = atts.getAttribute(CSS.Attribute.TEXT_ALIGN);
- if (o != null)
+ attributes = getAttributes();
+ if (attributes != null)
{
- String align = o.toString();
- if (align.equals("left"))
- setJustification(StyleConstants.ALIGN_LEFT);
- else if (align.equals("right"))
- setJustification(StyleConstants.ALIGN_RIGHT);
- else if (align.equals("center"))
- setJustification(StyleConstants.ALIGN_CENTER);
- else if (align.equals("justify"))
- setJustification(StyleConstants.ALIGN_JUSTIFIED);
- }
+ super.setPropertiesFromAttributes();
+ Object o = attributes.getAttribute(CSS.Attribute.TEXT_ALIGN);
+ if (o != null)
+ {
+ String align = o.toString();
+ if (align.equals("left"))
+ setJustification(StyleConstants.ALIGN_LEFT);
+ else if (align.equals("right"))
+ setJustification(StyleConstants.ALIGN_RIGHT);
+ else if (align.equals("center"))
+ setJustification(StyleConstants.ALIGN_CENTER);
+ else if (align.equals("justify"))
+ setJustification(StyleConstants.ALIGN_JUSTIFIED);
+ }
- // Fetch StyleSheet's box painter.
- painter = getStyleSheet().getBoxPainter(atts);
- setInsets((short) painter.getInset(TOP, this),
- (short) painter.getInset(LEFT, this),
- (short) painter.getInset(BOTTOM, this),
- (short) painter.getInset(RIGHT, this));
+ // Fetch StyleSheet's box painter.
+ painter = getStyleSheet().getBoxPainter(attributes);
+ setInsets((short) painter.getInset(TOP, this),
+ (short) painter.getInset(LEFT, this),
+ (short) painter.getInset(BOTTOM, this),
+ (short) painter.getInset(RIGHT, this));
- // TODO: Handle CSS width and height attributes somehow.
+ cssWidth = (Length) attributes.getAttribute(CSS.Attribute.WIDTH);
+ cssHeight = (Length) attributes.getAttribute(CSS.Attribute.WIDTH);
+ }
}
/**
@@ -169,8 +186,66 @@ public class ParagraphView
protected SizeRequirements calculateMinorAxisRequirements(int axis,
SizeRequirements r)
{
- // FIXME: Implement the above specified behaviour.
- return super.calculateMinorAxisRequirements(axis, r);
+ r = super.calculateMinorAxisRequirements(axis, r);
+ if (setCSSSpan(r, axis))
+ {
+ // If we have set the span from CSS, then we need to adjust
+ // the margins.
+ SizeRequirements parent = super.calculateMinorAxisRequirements(axis,
+ null);
+ int margin = axis == X_AXIS ? getLeftInset() + getRightInset()
+ : getTopInset() + getBottomInset();
+ r.minimum -= margin;
+ r.preferred -= margin;
+ r.maximum -= margin;
+ }
+ else
+ {
+ float min = 0;
+ int n = getLayoutViewCount();
+ for (int i = 0; i < n; i++)
+ min = Math.max(getLayoutView(i).getMinimumSpan(axis), min);
+ r.minimum = (int) min;
+ r.preferred = Math.max(r.preferred, r.minimum);
+ r.maximum = Math.max(r.maximum, r.preferred);
+ }
+ return r;
+ }
+
+ /**
+ * Sets the span on the SizeRequirements object according to the
+ * according CSS span value, when it is set.
+ *
+ * @param r the size requirements
+ * @param axis the axis
+ *
+ * @return <code>true</code> when the CSS span has been set,
+ * <code>false</code> otherwise
+ */
+ private boolean setCSSSpan(SizeRequirements r, int axis)
+ {
+ boolean ret = false;
+ if (axis == X_AXIS)
+ {
+ if (cssWidth != null && ! cssWidth.isPercentage())
+ {
+ r.minimum = (int) cssWidth.getValue();
+ r.preferred = (int) cssWidth.getValue();
+ r.maximum = (int) cssWidth.getValue();
+ ret = true;
+ }
+ }
+ else
+ {
+ if (cssHeight != null && ! cssWidth.isPercentage())
+ {
+ r.minimum = (int) cssHeight.getValue();
+ r.preferred = (int) cssHeight.getValue();
+ r.maximum = (int) cssHeight.getValue();
+ ret = true;
+ }
+ }
+ return ret;
}
/**
diff --git a/javax/swing/text/html/StyleSheet.java b/javax/swing/text/html/StyleSheet.java
index 703a3864a..add22e01c 100644
--- a/javax/swing/text/html/StyleSheet.java
+++ b/javax/swing/text/html/StyleSheet.java
@@ -45,21 +45,27 @@ import gnu.javax.swing.text.html.css.FontSize;
import gnu.javax.swing.text.html.css.FontStyle;
import gnu.javax.swing.text.html.css.FontWeight;
import gnu.javax.swing.text.html.css.Length;
+import gnu.javax.swing.text.html.css.Selector;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
+import java.io.BufferedReader;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
import java.io.Reader;
import java.io.Serializable;
import java.io.StringReader;
import java.net.URL;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
-import java.util.StringTokenizer;
+import javax.swing.border.Border;
import javax.swing.event.ChangeListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.Element;
@@ -86,7 +92,7 @@ import javax.swing.text.View;
*
* The rules are stored as named styles, and other information is stored to
* translate the context of an element to a rule.
- *
+ *
* @author Lillian Angel (langel@redhat.com)
*/
public class StyleSheet extends StyleContext
@@ -101,21 +107,35 @@ public class StyleSheet extends StyleContext
implements CSSParserCallback
{
/**
- * The selector for which the rules are currently parsed.
+ * The current style.
+ */
+ private CSSStyle style;
+
+ /**
+ * The precedence of the stylesheet to be parsed.
*/
- private String[] selector;
+ private int precedence;
+
+ /**
+ * Creates a new CSS parser. This parser parses a CSS stylesheet with
+ * the specified precedence.
+ *
+ * @param prec the precedence, according to the constants defined in
+ * CSSStyle
+ */
+ CSSStyleSheetParserCallback(int prec)
+ {
+ precedence = prec;
+ }
/**
* Called at the beginning of a statement.
*
* @param sel the selector
*/
- public void startStatement(String sel)
+ public void startStatement(Selector sel)
{
- StringTokenizer tokens = new StringTokenizer(sel);
- selector = new String[tokens.countTokens()];
- for (int index = 0; tokens.hasMoreTokens(); index++)
- selector[index] = tokens.nextToken();
+ style = new CSSStyle(precedence, sel);
}
/**
@@ -123,7 +143,8 @@ public class StyleSheet extends StyleContext
*/
public void endStatement()
{
- selector = null;
+ css.add(style);
+ style = null;
}
/**
@@ -134,23 +155,13 @@ public class StyleSheet extends StyleContext
*/
public void declaration(String property, String value)
{
- for (int i = 0; i < selector.length; i++)
- {
- CSSStyle style = (CSSStyle) css.get(selector[i]);
- if (style == null)
- {
- style = new CSSStyle();
- css.put(selector[i], style);
- }
- CSS.Attribute cssAtt = CSS.getAttribute(property);
- Object val = CSS.getValue(cssAtt, value);
- if (cssAtt != null)
- style.addAttribute(cssAtt, val);
- // else // For debugging only.
- // System.err.println("no mapping for: " + property);
- }
+ CSS.Attribute cssAtt = CSS.getAttribute(property);
+ Object val = CSS.getValue(cssAtt, value);
+ CSS.addInternal(style, cssAtt, value);
+ if (cssAtt != null)
+ style.addAttribute(cssAtt, val);
}
-
+
}
/**
@@ -158,9 +169,33 @@ public class StyleSheet extends StyleContext
*/
private class CSSStyle
extends SimpleAttributeSet
- implements Style
+ implements Style, Comparable
{
+ static final int PREC_UA = 400000;
+ static final int PREC_NORM = 300000;
+ static final int PREC_AUTHOR_NORMAL = 200000;
+ static final int PREC_AUTHOR_IMPORTANT = 100000;
+ static final int PREC_USER_IMPORTANT = 0;
+
+ /**
+ * The priority of this style when matching CSS selectors.
+ */
+ private int precedence;
+
+ /**
+ * The selector for this rule.
+ *
+ * This is package private to avoid accessor methods.
+ */
+ Selector selector;
+
+ CSSStyle(int prec, Selector sel)
+ {
+ precedence = prec;
+ selector = sel;
+ }
+
public String getName()
{
// TODO: Implement this for correctness.
@@ -176,6 +211,17 @@ public class StyleSheet extends StyleContext
{
// TODO: Implement this for correctness.
}
+
+ /**
+ * Sorts the rule according to the style's precedence and the
+ * selectors specificity.
+ */
+ public int compareTo(Object o)
+ {
+ CSSStyle other = (CSSStyle) o;
+ return other.precedence + other.selector.getSpecificity()
+ - precedence - selector.getSpecificity();
+ }
}
@@ -192,7 +238,7 @@ public class StyleSheet extends StyleContext
* Maps element names (selectors) to AttributSet (the corresponding style
* information).
*/
- HashMap css = new HashMap();
+ ArrayList css = new ArrayList();
/**
* Maps selectors to their resolved styles.
@@ -371,14 +417,17 @@ public class StyleSheet extends StyleContext
// the default.css.
int count = tags.length;
ArrayList styles = new ArrayList();
- for (int i = 0; i < count; i++)
+ for (Iterator i = css.iterator(); i.hasNext();)
{
- Style style = (Style) css.get(tags[i]);
- if (style != null)
+ CSSStyle style = (CSSStyle) i.next();
+ if (style.selector.matches(tags, classes, ids))
styles.add(style);
- // FIXME: Handle ID and CLASS attributes.
}
+
+ // Sort selectors.
+ Collections.sort(styles);
Style[] styleArray = new Style[styles.size()];
+ styleArray = (Style[]) styles.toArray(styleArray);
Style resolved = new MultiStyle(selector,
(Style[]) styles.toArray(styleArray));
resolvedStyles.put(selector, resolved);
@@ -395,9 +444,15 @@ public class StyleSheet extends StyleContext
*/
public Style getRule(String selector)
{
- // FIXME: This is a very rudimentary implementation. Should
- // be extended to conform to the CSS spec.
- return (Style) css.get(selector);
+ Selector sel = new Selector(selector);
+ CSSStyle best = null;
+ for (Iterator i = css.iterator(); i.hasNext();)
+ {
+ CSSStyle style = (CSSStyle) i.next();
+ if (style.compareTo(best) < 0)
+ best = style;
+ }
+ return best;
}
/**
@@ -408,7 +463,8 @@ public class StyleSheet extends StyleContext
*/
public void addRule(String rule)
{
- CSSStyleSheetParserCallback cb = new CSSStyleSheetParserCallback();
+ CSSStyleSheetParserCallback cb =
+ new CSSStyleSheetParserCallback(CSSStyle.PREC_AUTHOR_NORMAL);
// FIXME: Handle ref.
StringReader in = new StringReader(rule);
CSSParser parser = new CSSParser(in, cb);
@@ -419,7 +475,7 @@ public class StyleSheet extends StyleContext
catch (IOException ex)
{
// Shouldn't happen. And if, then we
- assert false;
+ System.err.println("IOException while parsing stylesheet: " + ex.getMessage());
}
}
@@ -451,7 +507,8 @@ public class StyleSheet extends StyleContext
public void loadRules(Reader in, URL ref)
throws IOException
{
- CSSStyleSheetParserCallback cb = new CSSStyleSheetParserCallback();
+ CSSStyleSheetParserCallback cb =
+ new CSSStyleSheetParserCallback(CSSStyle.PREC_UA);
// FIXME: Handle ref.
CSSParser parser = new CSSParser(in, cb);
parser.parse();
@@ -543,13 +600,26 @@ public class StyleSheet extends StyleContext
/**
* Imports a style sheet from the url. The rules are directly added to the
- * receiver.
+ * receiver. This is usually called when a <link> tag is resolved in an
+ * HTML document.
*
- * @param url - the URL to import the StyleSheet from.
+ * @param url the URL to import the StyleSheet from
*/
public void importStyleSheet(URL url)
{
- // FIXME: Not implemented
+ try
+ {
+ InputStream in = url.openStream();
+ Reader r = new BufferedReader(new InputStreamReader(in));
+ CSSStyleSheetParserCallback cb =
+ new CSSStyleSheetParserCallback(CSSStyle.PREC_AUTHOR_NORMAL);
+ CSSParser parser = new CSSParser(r, cb);
+ parser.parse();
+ }
+ catch (IOException ex)
+ {
+ // We can't do anything about it I guess.
+ }
}
/**
@@ -585,6 +655,7 @@ public class StyleSheet extends StyleContext
String value)
{
Object val = CSS.getValue(key, value);
+ CSS.addInternal(attr, key, value);
attr.addAttribute(key, val);
}
@@ -615,11 +686,31 @@ public class StyleSheet extends StyleContext
*/
public AttributeSet translateHTMLToCSS(AttributeSet htmlAttrSet)
{
- // FIXME: Really convert HTML to CSS here.
AttributeSet cssAttr = htmlAttrSet.copyAttributes();
- MutableAttributeSet cssStyle = addStyle(null, null);
- cssStyle.addAttributes(cssAttr);
- return cssStyle;
+
+ // The HTML align attribute maps directly to the CSS text-align attribute.
+ Object o = htmlAttrSet.getAttribute(HTML.Attribute.ALIGN);
+ if (o != null)
+ cssAttr = addAttribute(cssAttr, CSS.Attribute.TEXT_ALIGN, o);
+
+ // The HTML width attribute maps directly to CSS width.
+ o = htmlAttrSet.getAttribute(HTML.Attribute.WIDTH);
+ if (o != null)
+ cssAttr = addAttribute(cssAttr, CSS.Attribute.WIDTH,
+ CSS.getValue(CSS.Attribute.WIDTH, o.toString()));
+
+ // The HTML height attribute maps directly to CSS height.
+ o = htmlAttrSet.getAttribute(HTML.Attribute.HEIGHT);
+ if (o != null)
+ cssAttr = addAttribute(cssAttr, CSS.Attribute.HEIGHT,
+ CSS.getValue(CSS.Attribute.HEIGHT, o.toString()));
+
+ o = htmlAttrSet.getAttribute(HTML.Attribute.NOWRAP);
+ if (o != null)
+ cssAttr = addAttribute(cssAttr, CSS.Attribute.WHITE_SPACE, "nowrap");
+
+ // TODO: Add more mappings.
+ return cssAttr;
}
/**
@@ -802,7 +893,7 @@ public class StyleSheet extends StyleContext
*/
public BoxPainter getBoxPainter(AttributeSet a)
{
- return new BoxPainter(a);
+ return new BoxPainter(a, this);
}
/**
@@ -813,7 +904,7 @@ public class StyleSheet extends StyleContext
*/
public ListPainter getListPainter(AttributeSet a)
{
- return new ListPainter(a);
+ return new ListPainter(a, this);
}
/**
@@ -920,17 +1011,42 @@ public class StyleSheet extends StyleContext
public static class BoxPainter extends Object implements Serializable
{
+ /**
+ * The left inset.
+ */
private float leftInset;
+
+ /**
+ * The right inset.
+ */
private float rightInset;
+
+ /**
+ * The top inset.
+ */
private float topInset;
+
+ /**
+ * The bottom inset.
+ */
private float bottomInset;
/**
+ * The border of the box.
+ */
+ private Border border;
+
+ /**
+ * The background color.
+ */
+ private Color background;
+
+ /**
* Package-private constructor.
*
* @param as - AttributeSet for painter
*/
- BoxPainter(AttributeSet as)
+ BoxPainter(AttributeSet as, StyleSheet ss)
{
Length l = (Length) as.getAttribute(CSS.Attribute.MARGIN_LEFT);
if (l != null)
@@ -944,6 +1060,13 @@ public class StyleSheet extends StyleContext
l = (Length) as.getAttribute(CSS.Attribute.MARGIN_BOTTOM);
if (l != null)
bottomInset = l.getValue();
+
+ // Determine border.
+ border = new CSSBorder(as);
+
+ // Determine background.
+ background = ss.getBackground(as);
+
}
@@ -965,15 +1088,23 @@ public class StyleSheet extends StyleContext
{
case View.TOP:
inset = topInset;
+ if (border != null)
+ inset += border.getBorderInsets(null).top;
break;
case View.BOTTOM:
inset = bottomInset;
+ if (border != null)
+ inset += border.getBorderInsets(null).bottom;
break;
case View.LEFT:
inset = leftInset;
+ if (border != null)
+ inset += border.getBorderInsets(null).left;
break;
case View.RIGHT:
inset = rightInset;
+ if (border != null)
+ inset += border.getBorderInsets(null).right;
break;
default:
inset = 0.0F;
@@ -994,7 +1125,16 @@ public class StyleSheet extends StyleContext
*/
public void paint(Graphics g, float x, float y, float w, float h, View v)
{
- // FIXME: Not implemented.
+
+ if (background != null)
+ {
+ g.setColor(background);
+ g.fillRect((int) x, (int) y, (int) w, (int) h);
+ }
+ if (border != null)
+ {
+ border.paintBorder(null, g, (int) x, (int) y, (int) w, (int) h);
+ }
}
}
@@ -1005,24 +1145,36 @@ public class StyleSheet extends StyleContext
*
* @author Lillian Angel (langel@redhat.com)
*/
- public static class ListPainter extends Object implements Serializable
+ public static class ListPainter implements Serializable
{
-
+
/**
* Attribute set for painter
*/
- AttributeSet as;
-
+ private AttributeSet attributes;
+
+ /**
+ * The associated style sheet.
+ */
+ private StyleSheet styleSheet;
+
+ /**
+ * The bullet type.
+ */
+ private String type;
+
/**
* Package-private constructor.
*
* @param as - AttributeSet for painter
*/
- ListPainter(AttributeSet as)
+ ListPainter(AttributeSet as, StyleSheet ss)
{
- this.as = as;
+ attributes = as;
+ styleSheet = ss;
+ type = (String) as.getAttribute(CSS.Attribute.LIST_STYLE_TYPE);
}
-
+
/**
* Paints the CSS list decoration according to the attributes given.
*
@@ -1037,7 +1189,19 @@ public class StyleSheet extends StyleContext
public void paint(Graphics g, float x, float y, float w, float h, View v,
int item)
{
- // FIXME: Not implemented.
+ // FIXME: This is a very simplistic list rendering. We still need
+ // to implement different bullet types (see type field) and custom
+ // bullets via images.
+ View itemView = v.getView(item);
+ AttributeSet viewAtts = itemView.getAttributes();
+ Object tag = viewAtts.getAttribute(StyleConstants.NameAttribute);
+ // Only paint something here when the child view is an LI tag
+ // and the calling view is some of the list tags then).
+ if (tag != null && tag == HTML.Tag.LI)
+ {
+ g.setColor(Color.BLACK);
+ g.fillOval((int) x - 15, (int) (h / 2 - 3 + y), 6, 6);
+ }
}
}
diff --git a/javax/swing/text/html/TableView.java b/javax/swing/text/html/TableView.java
index c2edc8cdd..2bd11ffcf 100644
--- a/javax/swing/text/html/TableView.java
+++ b/javax/swing/text/html/TableView.java
@@ -38,49 +38,185 @@ exception statement from your version. */
package javax.swing.text.html;
-import javax.swing.text.Document;
+import gnu.javax.swing.text.html.css.Length;
+
+import javax.swing.SizeRequirements;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BoxView;
import javax.swing.text.Element;
+import javax.swing.text.StyleConstants;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
/**
- * A conrete implementation of TableView that renders HTML tables.
- *
- * @author Roman Kennke (kennke@aicas.com)
+ * A view implementation that renders HTML tables.
+ *
+ * This is basically a vertical BoxView that contains the rows of the table
+ * and the rows are horizontal BoxViews that contain the actual columns.
*/
class TableView
- extends javax.swing.text.TableView
+ extends BoxView
+ implements ViewFactory
{
+
/**
* Represents a single table row.
*/
- public class RowView extends TableRow
+ class RowView
+ extends BlockView
{
/**
- * Creates a new instance of the <code>RowView</code>.
+ * Creates a new RowView.
*
- * @param el the element for which to create a row view
+ * @param el the element for the row view
+ */
+ RowView(Element el)
+ {
+ super(el, X_AXIS);
+ }
+
+ /**
+ * Overridden to make rows not resizable along the Y axis.
+ */
+ public float getMaximumSpan(int axis)
+ {
+ float span;
+ if (axis == Y_AXIS)
+ span = super.getPreferredSpan(axis);
+ else
+ span = super.getMaximumSpan(axis);
+ return span;
+ }
+
+ /**
+ * Calculates the overall size requirements for the row along the
+ * major axis. This will be the sum of the column requirements.
+ */
+ protected SizeRequirements calculateMajorAxisRequirements(int axis,
+ SizeRequirements r)
+ {
+ if (r == null)
+ r = new SizeRequirements();
+ r.minimum = totalColumnRequirements.minimum;
+ r.preferred = totalColumnRequirements.preferred;
+ r.maximum = totalColumnRequirements.maximum;
+ r.alignment = 0.0F;
+ return r;
+ }
+
+ /**
+ * Lays out the columns in this row.
*/
- public RowView(Element el)
+ protected void layoutMajorAxis(int targetSpan, int axis, int[] offsets,
+ int spans[])
{
- super(el);
+ int numCols = offsets.length;
+ int realColumn = 0;
+ for (int i = 0; i < numCols; i++)
+ {
+ View v = getView(i);
+ if (v instanceof CellView)
+ {
+ CellView cv = (CellView) v;
+ offsets[i] = columnOffsets[realColumn];
+ spans[i] = 0;
+ for (int j = 0; j < cv.colSpan; j++, realColumn++)
+ {
+ spans[i] += columnSpans[realColumn];
+ }
+ }
+ }
}
-
+ }
+
/**
- * Get the associated style sheet from the document.
- *
- * @return the associated style sheet.
+ * A view that renders HTML table cells (TD and TH tags).
*/
- protected StyleSheet getStyleSheet()
+ class CellView
+ extends BlockView
+ {
+
+ /**
+ * The number of columns that this view spans.
+ */
+ int colSpan;
+
+ /**
+ * Creates a new CellView for the specified element.
+ *
+ * @param el the element for which to create the colspan
+ */
+ CellView(Element el)
{
- Document d = getElement().getDocument();
- if (d instanceof HTMLDocument)
- return ((HTMLDocument) d).getStyleSheet();
- else
- return null;
- }
+ super(el, Y_AXIS);
+ }
+
+ /**
+ * Overridden to fetch the columnSpan attibute.
+ */
+ protected void setPropertiesFromAttributes()
+ {
+ super.setPropertiesFromAttributes();
+ colSpan = 1;
+ AttributeSet atts = getAttributes();
+ Object o = atts.getAttribute(HTML.Attribute.COLSPAN);
+ if (o != null)
+ {
+ try
+ {
+ colSpan = Integer.parseInt(o.toString());
+ }
+ catch (NumberFormatException ex)
+ {
+ // Couldn't parse the colspan, assume 1.
+ colSpan = 1;
+ }
+ }
+ }
}
+
+ /**
+ * The attributes of this view.
+ */
+ private AttributeSet attributes;
+
+ /**
+ * The column requirements.
+ */
+ private SizeRequirements[] columnRequirements;
+
+ /**
+ * The overall requirements across all columns.
+ *
+ * Package private to avoid accessor methods.
+ */
+ SizeRequirements totalColumnRequirements;
+
+ /**
+ * The column layout, offsets.
+ *
+ * Package private to avoid accessor methods.
+ */
+ int[] columnOffsets;
+
+ /**
+ * The column layout, spans.
+ *
+ * Package private to avoid accessor methods.
+ */
+ int[] columnSpans;
+
+ /**
+ * The widths of the columns that have been explicitly specified.
+ */
+ Length[] columnWidths;
+
+ /**
+ * Indicates if the grid setup is ok.
+ */
+ private boolean gridValid;
+
/**
* Creates a new HTML table view for the specified element.
*
@@ -88,50 +224,424 @@ class TableView
*/
public TableView(Element el)
{
- super(el);
+ super(el, Y_AXIS);
+ totalColumnRequirements = new SizeRequirements();
}
-
+
/**
- * Get the associated style sheet from the document.
- *
- * @return the associated style sheet.
+ * Implementation of the ViewFactory interface for creating the
+ * child views correctly.
*/
- protected StyleSheet getStyleSheet()
+ public View create(Element elem)
{
- Document d = getElement().getDocument();
- if (d instanceof HTMLDocument)
- return ((HTMLDocument) d).getStyleSheet();
- else
- return null;
- }
-
+ View view = null;
+ AttributeSet atts = elem.getAttributes();
+ Object name = atts.getAttribute(StyleConstants.NameAttribute);
+ if (name instanceof HTML.Tag)
+ {
+ HTML.Tag tag = (HTML.Tag) name;
+ if (tag == HTML.Tag.TR)
+ view = new RowView(elem);
+ else if (tag == HTML.Tag.TD || tag == HTML.Tag.TH)
+ view = new CellView(elem);
+ else if (tag == HTML.Tag.CAPTION)
+ view = new ParagraphView(elem);
+ }
+
+ // If we haven't mapped the element, then fall back to the standard
+ // view factory.
+ if (view == null)
+ {
+ View parent = getParent();
+ if (parent != null)
+ {
+ ViewFactory vf = parent.getViewFactory();
+ if (vf != null)
+ view = vf.create(elem);
+ }
+ }
+ return view;
+ }
+
/**
- * Creates a view for a table row.
- *
- * @param el the element that represents the table row
- * @return a view for rendering the table row
- * (and instance of {@link RowView}).
+ * Returns this object as view factory so that we get our TR, TD, TH
+ * and CAPTION subelements created correctly.
*/
- protected TableRow createTableRow(Element el)
+ public ViewFactory getViewFactory()
{
- return new RowView(el);
- }
-
+ return this;
+ }
+
/**
- * Loads the children of the Table. This completely bypasses the ViewFactory
- * and creates instances of TableRow instead.
+ * Returns the attributes of this view. This is overridden to provide
+ * the attributes merged with the CSS stuff.
+ */
+ public AttributeSet getAttributes()
+ {
+ if (attributes == null)
+ attributes = getStyleSheet().getViewAttributes(this);
+ return attributes;
+ }
+
+ /**
+ * Returns the stylesheet associated with this view.
*
- * @param vf ignored
+ * @return the stylesheet associated with this view
*/
- protected void loadChildren(ViewFactory vf)
+ private StyleSheet getStyleSheet()
{
- Element el = getElement();
- int numChildren = el.getElementCount();
- View[] rows = new View[numChildren];
- for (int i = 0; i < numChildren; ++i)
+ HTMLDocument doc = (HTMLDocument) getDocument();
+ return doc.getStyleSheet();
+ }
+
+ /**
+ * Overridden to calculate the size requirements according to the
+ * columns distribution.
+ */
+ protected SizeRequirements calculateMinorAxisRequirements(int axis,
+ SizeRequirements r)
+ {
+ updateGrid();
+ calculateColumnRequirements();
+
+ // Calculate the horizontal requirements according to the superclass.
+ // This will return the maximum of the row's widths.
+ r = super.calculateMinorAxisRequirements(axis, r);
+
+ // Try to set the CSS width if it fits.
+ AttributeSet atts = getAttributes();
+ Length l = (Length) atts.getAttribute(CSS.Attribute.WIDTH);
+ if (l != null)
+ {
+ int width = (int) l.getValue();
+ if (r.minimum < width)
+ r.minimum = width;
+ }
+
+ // Apply the alignment.
+ Object o = atts.getAttribute(CSS.Attribute.TEXT_ALIGN);
+ r.alignment = 0.0F;
+ if (o != null)
{
- rows[i] = createTableRow(el.getElement(i));
+ String al = o.toString();
+ if (al.equals("left"))
+ r.alignment = 0.0F;
+ else if (al.equals("center"))
+ r.alignment = 0.5F;
+ else if (al.equals("right"))
+ r.alignment = 1.0F;
}
- replace(0, getViewCount(), rows);
+
+ return r;
+ }
+
+ /**
+ * Overridden to perform the table layout before calling the super
+ * implementation.
+ */
+ protected void layoutMinorAxis(int targetSpan, int axis, int[] offsets,
+ int[] spans)
+ {
+ updateGrid();
+ layoutColumns(targetSpan);
+ super.layoutMinorAxis(targetSpan, axis, offsets, spans);
+ }
+
+ /**
+ * Calculates the size requirements for the columns.
+ */
+ private void calculateColumnRequirements()
+ {
+ int numRows = getViewCount();
+ totalColumnRequirements.minimum = 0;
+ totalColumnRequirements.preferred = 0;
+ totalColumnRequirements.maximum = 0;
+
+ // In this first pass we find out a suitable total width to fit in
+ // all columns of all rows.
+ for (int r = 0; r < numRows; r++)
+ {
+ RowView rowView = (RowView) getView(r);
+ int numCols = rowView.getViewCount();
+
+ // We collect the normal (non-relative) column requirements in the
+ // total variable and the relative requirements in the relTotal
+ // variable. In the end we create the maximum of both to get the
+ // real requirements.
+ SizeRequirements total = new SizeRequirements();
+ SizeRequirements relTotal = new SizeRequirements();
+ float totalPercent = 0.F;
+ for (int c = 0; c < numCols; )
+ {
+ View v = rowView.getView(c);
+ if (v instanceof CellView)
+ {
+ CellView cellView = (CellView) v;
+ int colSpan = cellView.colSpan;
+ if (colSpan > 1)
+ {
+ int cellMin = (int) cellView.getMinimumSpan(X_AXIS);
+ int cellPref = (int) cellView.getPreferredSpan(X_AXIS);
+ int cellMax = (int) cellView.getMaximumSpan(X_AXIS);
+ int currentMin = 0;
+ int currentPref = 0;
+ long currentMax = 0;
+ for (int i = 0; i < colSpan; i++)
+ {
+ SizeRequirements req = columnRequirements[c + i];
+ currentMin += req.minimum;
+ currentPref += req.preferred;
+ currentMax += req.maximum;
+ }
+ int deltaMin = cellMin - currentMin;
+ int deltaPref = cellPref - currentPref;
+ int deltaMax = (int) (cellMax - currentMax);
+ // Distribute delta.
+ for (int i = 0; i < colSpan; i++)
+ {
+ SizeRequirements req = columnRequirements[c + i];
+ if (deltaMin > 0)
+ req.minimum += deltaMin / colSpan;
+ if (deltaPref > 0)
+ req.preferred += deltaPref / colSpan;
+ if (deltaMax > 0)
+ req.maximum += deltaMax / colSpan;
+ if (columnWidths[c + i] == null
+ || ! columnWidths[c + i].isPercentage())
+ {
+ total.minimum += req.minimum;
+ total.preferred += req.preferred;
+ total.maximum += req.maximum;
+ }
+ else
+ {
+ relTotal.minimum =
+ Math.max(relTotal.minimum,
+ (int) (req.minimum
+ * columnWidths[c + i].getValue()));
+ relTotal.preferred =
+ Math.max(relTotal.preferred,
+ (int) (req.preferred
+ * columnWidths[c + i].getValue()));
+ relTotal.maximum =
+ Math.max(relTotal.maximum,
+ (int) (req.maximum
+ * columnWidths[c + i].getValue()));
+ totalPercent += columnWidths[c + i].getValue();
+ }
+ }
+ }
+ else
+ {
+ // Shortcut for colSpan == 1.
+ SizeRequirements req = columnRequirements[c];
+ req.minimum = Math.max(req.minimum,
+ (int) cellView.getMinimumSpan(X_AXIS));
+ req.preferred = Math.max(req.preferred,
+ (int) cellView.getPreferredSpan(X_AXIS));
+ req.maximum = Math.max(req.maximum,
+ (int) cellView.getMaximumSpan(X_AXIS));
+ if (columnWidths[c] == null
+ || ! columnWidths[c].isPercentage())
+ {
+ total.minimum += columnRequirements[c].minimum;
+ total.preferred += columnRequirements[c].preferred;
+ total.maximum += columnRequirements[c].maximum;
+ }
+ else
+ {
+ relTotal.minimum =
+ Math.max(relTotal.minimum,
+ (int) (req.minimum
+ / columnWidths[c].getValue()));
+ relTotal.preferred =
+ Math.max(relTotal.preferred,
+ (int) (req.preferred
+ / columnWidths[c].getValue()));
+ relTotal.maximum =
+ Math.max(relTotal.maximum,
+ (int) (req.maximum
+ / columnWidths[c].getValue()));
+ totalPercent += columnWidths[c].getValue();
+ }
+ }
+ c += colSpan;
+ }
+ else
+ c++;
+ }
+
+ // Update the total requirements as follows:
+ // 1. Multiply the absolute requirements with 1 - totalPercent. This
+ // gives the total requirements based on the wishes of the absolute
+ // cells.
+ // 2. Take the maximum of this value and the total relative
+ // requirements. Now we should have enough space for whatever cell
+ // in this column.
+ // 3. Take the maximum of this value and the previous maximum value.
+ total.minimum *= 1.F / (1.F - totalPercent);
+ total.preferred *= 1.F / (1.F - totalPercent);
+ total.maximum *= 1.F / (1.F - totalPercent);
+
+ int rowTotalMin = Math.max(total.minimum, relTotal.minimum);
+ int rowTotalPref = Math.max(total.preferred, relTotal.preferred);
+ int rowTotalMax = Math.max(total.maximum, relTotal.maximum);
+ totalColumnRequirements.minimum =
+ Math.max(totalColumnRequirements.minimum, rowTotalMin);
+ totalColumnRequirements.preferred =
+ Math.max(totalColumnRequirements.preferred, rowTotalPref);
+ totalColumnRequirements.maximum =
+ Math.max(totalColumnRequirements.maximum, rowTotalMax);
+ }
+
+ // Now we know what we want and can fix up the actual relative
+ // column requirements.
+ int numCols = columnRequirements.length;
+ for (int i = 0; i < numCols; i++)
+ {
+ if (columnWidths[i] != null)
+ {
+ columnRequirements[i].minimum = (int)
+ columnWidths[i].getValue(totalColumnRequirements.minimum);
+ columnRequirements[i].preferred = (int)
+ columnWidths[i].getValue(totalColumnRequirements.preferred);
+ columnRequirements[i].maximum = (int)
+ columnWidths[i].getValue(totalColumnRequirements.maximum);
+ }
+ }
+ }
+
+ /**
+ * Lays out the columns.
+ *
+ * @param targetSpan the target span into which the table is laid out
+ */
+ private void layoutColumns(int targetSpan)
+ {
+ // Set the spans to the preferred sizes. Determine the space
+ // that we have to adjust the sizes afterwards.
+ long sumPref = 0;
+ int n = columnRequirements.length;
+ for (int i = 0; i < n; i++)
+ {
+ SizeRequirements col = columnRequirements[i];
+ if (columnWidths[i] != null)
+ columnSpans[i] = (int) columnWidths[i].getValue(targetSpan);
+ else
+ columnSpans[i] = col.preferred;
+ sumPref += columnSpans[i];
+ }
+
+ // Try to adjust the spans so that we fill the targetSpan.
+ long diff = targetSpan - sumPref;
+ float factor = 0.0F;
+ int[] diffs = null;
+ if (diff != 0)
+ {
+ long total = 0;
+ diffs = new int[n];
+ for (int i = 0; i < n; i++)
+ {
+ // Only adjust the width if we haven't set a column width here.
+ if (columnWidths[i] == null)
+ {
+ SizeRequirements col = columnRequirements[i];
+ int span;
+ if (diff < 0)
+ {
+ span = col.minimum;
+ diffs[i] = columnSpans[i] - span;
+ }
+ else
+ {
+ span = col.maximum;
+ diffs[i] = span - columnSpans[i];
+ }
+ total += span;
+ }
+ else
+ total += columnSpans[i];
+ }
+
+ float maxAdjust = Math.abs(total - sumPref);
+ factor = diff / maxAdjust;
+ factor = Math.min(factor, 1.0F);
+ factor = Math.max(factor, -1.0F);
+ }
+
+ // Actually perform adjustments.
+ int totalOffs = 0;
+ for (int i = 0; i < n; i++)
+ {
+ columnOffsets[i] = totalOffs;
+ if (diff != 0)
+ {
+ float adjust = factor * diffs[i];
+ columnSpans[i] += Math.round(adjust);
+ }
+ // Avoid overflow here.
+ totalOffs = (int) Math.min((long) totalOffs + (long) columnSpans[i],
+ Integer.MAX_VALUE);
+ }
+ }
+
+ /**
+ * Updates the arrays that contain the row and column data in response
+ * to a change to the table structure.
+ */
+ private void updateGrid()
+ {
+ if (! gridValid)
+ {
+ int maxColumns = 0;
+ int numRows = getViewCount();
+ for (int r = 0; r < numRows; r++)
+ {
+ RowView rowView = (RowView) getView(r);
+ int numCols = rowView.getViewCount();
+ maxColumns = Math.max(numCols, maxColumns);
+ }
+ columnWidths = new Length[maxColumns];
+ for (int r = 0; r < numRows; r++)
+ {
+ RowView rowView = (RowView) getView(r);
+ int numCols = rowView.getViewCount();
+ int colIndex = 0;
+ for (int c = 0; c < numCols; c++)
+ {
+ View v = rowView.getView(c);
+ if (v instanceof CellView)
+ {
+ CellView cv = (CellView) v;
+ Object o =
+ cv.getAttributes().getAttribute(CSS.Attribute.WIDTH);
+ if (o != null && columnWidths[colIndex] == null
+ && o instanceof Length)
+ columnWidths[colIndex]= (Length) o;
+ colIndex += cv.colSpan;
+ }
+ }
+ }
+ columnRequirements = new SizeRequirements[maxColumns];
+ for (int i = 0; i < maxColumns; i++)
+ columnRequirements[i] = new SizeRequirements();
+ columnOffsets = new int[maxColumns];
+ columnSpans = new int[maxColumns];
+
+ gridValid = true;
+ }
+ }
+
+ /**
+ * Overridden to restrict the table width to the preferred size.
+ */
+ public float getMaximumSpan(int axis)
+ {
+ float span;
+ if (axis == X_AXIS)
+ span = super.getPreferredSpan(axis);
+ else
+ span = super.getMaximumSpan(axis);
+ return span;
}
}
diff --git a/javax/swing/text/html/parser/DocumentParser.java b/javax/swing/text/html/parser/DocumentParser.java
index 062606d17..f717d69cb 100644
--- a/javax/swing/text/html/parser/DocumentParser.java
+++ b/javax/swing/text/html/parser/DocumentParser.java
@@ -38,13 +38,13 @@ exception statement from your version. */
package javax.swing.text.html.parser;
-import gnu.javax.swing.text.html.parser.htmlAttributeSet;
import javax.swing.text.html.parser.Parser;
import java.io.IOException;
import java.io.Reader;
import javax.swing.text.BadLocationException;
+import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.html.HTMLEditorKit;
/**
@@ -117,7 +117,7 @@ public class DocumentParser
protected final void handleStartTag(TagElement tag)
{
parser.handleStartTag(tag);
- htmlAttributeSet attributes = gnu.getAttributes();
+ SimpleAttributeSet attributes = gnu.getAttributes();
if (tag.fictional())
attributes.addAttribute(HTMLEditorKit.ParserCallback.IMPLIED,
diff --git a/javax/swing/text/html/parser/ParserDelegator.java b/javax/swing/text/html/parser/ParserDelegator.java
index 70636d929..cdd339b8f 100644
--- a/javax/swing/text/html/parser/ParserDelegator.java
+++ b/javax/swing/text/html/parser/ParserDelegator.java
@@ -38,13 +38,13 @@ exception statement from your version. */
package javax.swing.text.html.parser;
import gnu.javax.swing.text.html.parser.HTML_401F;
-import gnu.javax.swing.text.html.parser.htmlAttributeSet;
import java.io.IOException;
import java.io.Reader;
import java.io.Serializable;
import javax.swing.text.BadLocationException;
+import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.HTMLEditorKit.ParserCallback;
@@ -93,7 +93,7 @@ public class ParserDelegator
protected final void handleStartTag(TagElement tag)
{
- htmlAttributeSet attributes = gnu.getAttributes();
+ SimpleAttributeSet attributes = gnu.getAttributes();
if (tag.fictional())
attributes.addAttribute(ParserCallback.IMPLIED, Boolean.TRUE);
diff --git a/native/jni/java-net/gnu_java_net_VMPlainDatagramSocketImpl.c b/native/jni/java-net/gnu_java_net_VMPlainDatagramSocketImpl.c
deleted file mode 100644
index 3a451c763..000000000
--- a/native/jni/java-net/gnu_java_net_VMPlainDatagramSocketImpl.c
+++ /dev/null
@@ -1,406 +0,0 @@
-/* VMPlainDatagramSocketImpl.c - Native methods for PlainDatagramSocketImpl
- Copyright (C) 2005, 2006 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-/* do not move; needed here because of some macro definitions */
-#include <config.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <jni.h>
-#include <jcl.h>
-
-#include "cpnative.h"
-#include "cpnet.h"
-
-#include "javanet.h"
-
-#include "gnu_java_net_VMPlainDatagramSocketImpl.h"
-
-/*
- * Note that most of the functions in this module simply redirect to another
- * internal function. Why? Because many of these functions are shared
- * with PlainSocketImpl.
- */
-
-/*************************************************************************/
-
-/*
- * Creates a new datagram socket
- */
-JNIEXPORT void JNICALL
-Java_gnu_java_net_VMPlainDatagramSocketImpl_create(JNIEnv *env,
- jclass klass __attribute__ ((__unused__))
- , jobject obj)
-{
-
-#ifndef WITHOUT_NETWORK
- _javanet_create(env, obj, 0);
-#else /* not WITHOUT_NETWORK */
-#endif /* not WITHOUT_NETWORK */
-}
-
-/*************************************************************************/
-
-/*
- * Close the socket.
- */
-JNIEXPORT void JNICALL
-Java_gnu_java_net_VMPlainDatagramSocketImpl_close(JNIEnv *env,
- jclass klass __attribute__ ((__unused__)),
- jobject obj)
-{
-
-#ifndef WITHOUT_NETWORK
- _javanet_close(env, obj, 0);
-#else /* not WITHOUT_NETWORK */
-#endif /* not WITHOUT_NETWORK */
-}
-
-/*************************************************************************/
-
-/*
- * Connects to the specified destination.
- */
-JNIEXPORT void JNICALL
-Java_gnu_java_net_VMPlainDatagramSocketImpl_connect(JNIEnv *env,
- jclass klass __attribute__ ((__unused__)),
- jobject obj,
- jobject addr, jint port)
-{
-#ifndef WITHOUT_NETWORK
-
- _javanet_connect(env, obj, addr, port, 0);
-#else /* not WITHOUT_NETWORK */
-#endif /* not WITHOUT_NETWORK */
-}
-
-/*************************************************************************/
-
-/*
- * This method binds the specified address to the specified local port.
- * Note that we have to set the local address and local port public instance
- * variables.
- */
-JNIEXPORT void JNICALL
-Java_gnu_java_net_VMPlainDatagramSocketImpl_bind(JNIEnv *env,
- jclass klass __attribute__ ((__unused__)),
- jobject obj,
- jint port, jobject addr)
-{
-
-#ifndef WITHOUT_NETWORK
- _javanet_bind(env, obj, addr, port, 0);
-#else /* not WITHOUT_NETWORK */
-#endif /* not WITHOUT_NETWORK */
-}
-
-/*************************************************************************/
-
-/*
- * This method sets the specified option for a socket
- */
-JNIEXPORT void JNICALL
-Java_gnu_java_net_VMPlainDatagramSocketImpl_setOption(JNIEnv *env,
- jclass klass __attribute__ ((__unused__)),
- jobject obj,
- jint option_id,
- jobject val)
-{
-
-#ifndef WITHOUT_NETWORK
- _javanet_set_option(env, obj, option_id, val);
-#else /* not WITHOUT_NETWORK */
-#endif /* not WITHOUT_NETWORK */
-}
-
-/*************************************************************************/
-
-/*
- * This method sets the specified option for a socket
- */
-JNIEXPORT jobject JNICALL
-Java_gnu_java_net_VMPlainDatagramSocketImpl_getOption(JNIEnv *env,
- jclass klass __attribute__ ((__unused__)),
- jobject obj,
- jint option_id)
-{
-
-#ifndef WITHOUT_NETWORK
- return(_javanet_get_option(env, obj, option_id));
-#else /* not WITHOUT_NETWORK */
- return NULL;
-#endif /* not WITHOUT_NETWORK */
-}
-
-/*************************************************************************/
-
-/*
- * Reads a buffer from a remote host
- */
-JNIEXPORT void JNICALL
-Java_gnu_java_net_VMPlainDatagramSocketImpl_nativeReceive(JNIEnv *env,
- jclass klass __attribute__ ((__unused__)),
- jobject obj,
- jbyteArray arr,
- jint offset,
- jint length,
- jbyteArray receivedFromAddress,
- jintArray receivedFromPort,
- jintArray receivedLength)
-{
-#ifndef WITHOUT_NETWORK
- jint *port, *bytes_read;
- cpnet_address *addr;
- jbyte *addressBytes;
-
- addr = 0;
-
- port = (jint*)(*env)->GetIntArrayElements(env, receivedFromPort, NULL);
- if (port == NULL)
- {
- JCL_ThrowException(env, IO_EXCEPTION, "Internal error: could not access receivedFromPort array");
- return;
- }
-
- bytes_read = (jint*)(*env)->GetIntArrayElements(env, receivedLength, NULL);
- if (bytes_read == NULL)
- {
- (*env)->ReleaseIntArrayElements(env, receivedFromPort, (jint*)port, 0);
- JCL_ThrowException(env, IO_EXCEPTION, "Internal error: could not access receivedLength array");
- return;
- }
-
- /* Receive the packet */
- /* should we try some sort of validation on the length? */
- (*bytes_read) = _javanet_recvfrom(env, obj, arr, offset, length, &addr);
-
- /* Special case the strange situation where the receiver didn't want any
- bytes. */
- if (length == 0 && (*bytes_read) == -1)
- *bytes_read = 0;
-
- if ((*bytes_read) == -1)
- {
- (*env)->ReleaseIntArrayElements(env, receivedFromPort, (jint*)port, 0);
- (*env)->ReleaseIntArrayElements(env, receivedLength, (jint*)bytes_read, 0);
- JCL_ThrowException(env, IO_EXCEPTION, "Internal error: receive");
- return;
- }
-
- if ((*env)->ExceptionOccurred(env))
- return;
-
- *port = cpnet_addressGetPort (addr);
-
- /* Store the address */
- addressBytes = (jbyte*)(*env)->GetPrimitiveArrayCritical(env, receivedFromAddress, NULL);
- cpnet_IPV4AddressToBytes (addr, addressBytes);
- (*env)->ReleasePrimitiveArrayCritical(env, receivedFromAddress, addressBytes, 0);
-
- cpnet_freeAddress (env, addr);
-
- (*env)->ReleaseIntArrayElements(env, receivedFromPort, (jint*)port, 0);
- (*env)->ReleaseIntArrayElements(env, receivedLength, (jint*)bytes_read, 0);
-
- DBG("PlainDatagramSocketImpl.receive(): Received packet\n");
-
-#else /* not WITHOUT_NETWORK */
-#endif /* not WITHOUT_NETWORK */
-}
-
-/*************************************************************************/
-
-/*
- * Writes a buffer to the remote host
- */
-JNIEXPORT void JNICALL
-Java_gnu_java_net_VMPlainDatagramSocketImpl_nativeSendTo(JNIEnv *env,
- jclass klass __attribute__ ((__unused__)),
- jobject obj,
- jobject addr,
- jint port,
- jarray buf,
- jint offset,
- jint len)
-{
-#ifndef WITHOUT_NETWORK
- cpnet_address *netAddress;
-
- /* check if address given, tr 7.3.2005 */
- if (addr != NULL )
- {
- netAddress = _javanet_get_ip_netaddr(env, addr);
- if ((*env)->ExceptionOccurred(env))
- {
- return;
- }
- if (port == 0)
- {
- JCL_ThrowException(env, IO_EXCEPTION,
- "Invalid port number");
- cpnet_freeAddress(env, netAddress);
- return;
- }
- cpnet_addressSetPort (netAddress, port);
- }
- else
- {
- netAddress = NULL;
- }
-
- DBG("PlainDatagramSocketImpl.sendto(): have addr\n");
-
- _javanet_sendto(env, obj, buf, offset, len, netAddress);
- if (netAddress != NULL)
- cpnet_freeAddress(env, netAddress);
- if ((*env)->ExceptionOccurred(env))
- {
- return;
- }
-
- DBG("PlainDatagramSocketImpl.sendto(): finished\n");
-#else /* not WITHOUT_NETWORK */
-#endif /* not WITHOUT_NETWORK */
-}
-
-/*************************************************************************/
-
-/*
- * Joins a multicast group
- */
-JNIEXPORT void JNICALL
-Java_gnu_java_net_VMPlainDatagramSocketImpl_join(JNIEnv *env,
- jclass klass __attribute__ ((__unused__)),
- jobject obj,
- jobject addr)
-{
-#ifndef WITHOUT_NETWORK
- cpnet_address *netAddress;
- int fd;
- int result;
-
- /* check if address given, tr 7.3.2005 */
- if (addr != NULL)
- {
- netAddress = _javanet_get_ip_netaddr(env, addr);
- if ((*env)->ExceptionOccurred(env))
- {
- JCL_ThrowException(env, IO_EXCEPTION, "Internal error");
- return;
- }
- }
- else
- {
- netAddress = NULL;
- }
-
- fd = _javanet_get_int_field(env, obj, "native_fd");
- if ((*env)->ExceptionOccurred(env))
- {
- JCL_ThrowException(env, IO_EXCEPTION, "Internal error");
- return;
- }
-
- DBG("PlainDatagramSocketImpl.join(): have native fd\n");
-
- result = cpnet_addMembership (env, fd, netAddress);
- if (result != CPNATIVE_OK)
- {
- JCL_ThrowException(env, IO_EXCEPTION,
- cpnative_getErrorString (result));
- return;
- }
-
- DBG("PlainDatagramSocketImpl.join(): finished\n");
-#else /* not WITHOUT_NETWORK */
-#endif /* not WITHOUT_NETWORK */
-}
-
-/*************************************************************************/
-
-/*
- * Leaves a multicast group
- */
-JNIEXPORT void JNICALL
-Java_gnu_java_net_VMPlainDatagramSocketImpl_leave(JNIEnv *env,
- jclass klass __attribute__ ((__unused__)),
- jobject obj,
- jobject addr)
-{
-#ifndef WITHOUT_NETWORK
- cpnet_address *netAddress;
- int fd;
- int result;
-
- /* check if address given, tr 7.3.2005 */
- if (addr != NULL)
- {
- netAddress = _javanet_get_ip_netaddr(env, addr);
- if ((*env)->ExceptionOccurred(env))
- {
- JCL_ThrowException(env, IO_EXCEPTION, "Internal error");
- return;
- }
- }
- else
- {
- netAddress = 0;
- }
-
- fd = _javanet_get_int_field(env, obj, "native_fd");
- if ((*env)->ExceptionOccurred(env))
- {
- JCL_ThrowException(env, IO_EXCEPTION, "Internal error");
- return;
- }
-
- DBG("PlainDatagramSocketImpl.leave(): have native fd\n");
-
- result = cpnet_dropMembership (env, fd, netAddress);
- if (result != CPNATIVE_OK)
- {
- JCL_ThrowException(env, IO_EXCEPTION, cpnative_getErrorString (result));
- return;
- }
-
- DBG("PlainDatagramSocketImpl.leave(): finished\n");
-#else /* not WITHOUT_NETWORK */
-#endif /* not WITHOUT_NETWORK */
-}
-
diff --git a/native/jni/java-nio/Makefile.am b/native/jni/java-nio/Makefile.am
index a4b830cd4..9f2db83f2 100644
--- a/native/jni/java-nio/Makefile.am
+++ b/native/jni/java-nio/Makefile.am
@@ -5,7 +5,6 @@ libjavanio_la_SOURCES = gnu_java_nio_VMPipe.c \
gnu_java_nio_VMSelector.c \
gnu_java_nio_charset_iconv_IconvDecoder.c \
gnu_java_nio_charset_iconv_IconvEncoder.c \
- gnu_java_nio_channels_FileChannelImpl.c \
java_nio_MappedByteBufferImpl.c \
java_nio_VMDirectByteBuffer.c \
gnu_java_nio_EpollSelectorImpl.c \
diff --git a/native/jni/java-nio/gnu_java_nio_VMChannel.c b/native/jni/java-nio/gnu_java_nio_VMChannel.c
index 33a4f66de..c49a3184f 100644
--- a/native/jni/java-nio/gnu_java_nio_VMChannel.c
+++ b/native/jni/java-nio/gnu_java_nio_VMChannel.c
@@ -1272,7 +1272,7 @@ Java_gnu_java_nio_VMChannel_getsockname (JNIEnv *env, jclass clazz __attribute__
{
addr6 = (struct sockaddr_in6 *) sockaddr;
memcpy (nameptr, &(addr6->sin6_addr.s6_addr), 16);
- memcpy (nameptr, &(addr6->sin6_port), 2);
+ memcpy (nameptr + 16, &(addr6->sin6_port), 2);
return 16;
}
#endif /* HAVE_INET6 */
@@ -1331,7 +1331,7 @@ Java_gnu_java_nio_VMChannel_getpeername (JNIEnv *env, jclass clazz __attribute__
{
addr6 = (struct sockaddr_in6 *) sockaddr;
memcpy (nameptr, &(addr6->sin6_addr.s6_addr), 16);
- memcpy (nameptr, &(addr6->sin6_port), 2);
+ memcpy (nameptr + 16, &(addr6->sin6_port), 2);
return 16;
}
#endif /* HAVE_INET6 */
diff --git a/native/jni/java-nio/gnu_java_nio_channels_FileChannelImpl.c b/native/jni/java-nio/gnu_java_nio_channels_FileChannelImpl.c
deleted file mode 100644
index 644b334d3..000000000
--- a/native/jni/java-nio/gnu_java_nio_channels_FileChannelImpl.c
+++ /dev/null
@@ -1,773 +0,0 @@
-/* gnu_java_nio_channels_FileChannelImpl.c -
- Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-/* do not move; needed here because of some macro definitions */
-#include <config.h>
-
-#include <stdlib.h>
-#include <errno.h>
-
-#include <jni.h>
-#include <jcl.h>
-
-#include "cpnative.h"
-#include "cpio.h"
-
-#include "gnu_java_nio_channels_FileChannelImpl.h"
-
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif /* HAVE_FCNTL_H */
-
-#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif /* HAVE_SYS_MMAN_H */
-
-#if defined(HAVE_UNISTD_H)
-#include <unistd.h>
-#endif
-
-/* These values must be kept in sync with FileChannelImpl.java. */
-#define FILECHANNELIMPL_READ 1
-#define FILECHANNELIMPL_WRITE 2
-#define FILECHANNELIMPL_APPEND 4
-
-/* These values must be kept in sync with FileChannelImpl.java. */
-/* #define FILECHANNELIMPL_FILESEEK_SET 0 */
-/* #define FILECHANNELIMPL_FILESEEK_CUR 1 */
-/* #define FILECHANNELIMPL_FILESEEK_END 2 */
-
-#define FILECHANNELIMPL_FILEOPEN_FLAG_READ 1
-#define FILECHANNELIMPL_FILEOPEN_FLAG_WRITE 2
-#define FILECHANNELIMPL_FILEOPEN_FLAG_APPEND 4
-#define FILECHANNELIMPL_FILEOPEN_FLAG_EXCL 8
-#define FILECHANNELIMPL_FILEOPEN_FLAG_SYNC 16
-#define FILECHANNELIMPL_FILEOPEN_FLAG_DSYNC 32
-
-#define IO_EXCEPTION "java/io/IOException"
-
-/* Align a value up or down to a multiple of the pagesize. */
-#define ALIGN_DOWN(p,s) ((p) - ((p) % (s)))
-#define ALIGN_UP(p,s) ((p) + ((s) - ((p) % (s))))
-
-/* cached fieldID of gnu.java.nio.channels.FileChannelImpl.fd */
-static jfieldID native_fd_fieldID;
-
-static jint
-get_native_fd (JNIEnv * env, jobject obj)
-{
- return (*env)->GetIntField (env, obj, native_fd_fieldID);
-}
-
-/*
- * Library initialization routine. Called as part of java.io.FileDescriptor
- * static initialization.
- */
-JNIEXPORT void JNICALL
-Java_gnu_java_nio_channels_FileChannelImpl_init (JNIEnv * env,
- jclass clazz
- __attribute__ ((__unused__)))
-{
- jclass clazz_fc;
- jfieldID field;
-
- /* Initialize native_fd_fieldID so we only compute it once! */
- clazz_fc = (*env)->FindClass (env, "gnu/java/nio/channels/FileChannelImpl");
- if (!clazz_fc)
- {
- JCL_ThrowException (env, IO_EXCEPTION, "Internal error");
- return;
- }
-
- field = (*env)->GetFieldID (env, clazz_fc, "fd", "I");
- if (!field)
- {
- JCL_ThrowException (env, IO_EXCEPTION, "Internal error");
- return;
- }
-
- native_fd_fieldID = field;
-}
-
-/*
- * Open the specified file and return a native file descriptor
- */
-JNIEXPORT jint JNICALL
-Java_gnu_java_nio_channels_FileChannelImpl_open (JNIEnv * env,
- jobject obj
- __attribute__ ((__unused__)),
- jstring name, jint mode)
-{
- const char *filename;
- int flags;
- int permissions;
- int native_fd;
- int result;
-
- filename = JCL_jstring_to_cstring (env, name);
- if (filename == NULL)
- return (-1); /* Exception will already have been thrown */
-
- /* get file/permission flags for open() */
- if ((mode & FILECHANNELIMPL_FILEOPEN_FLAG_READ)
- && (mode & FILECHANNELIMPL_FILEOPEN_FLAG_WRITE))
- {
- /* read/write */
- flags = CPFILE_FLAG_CREATE | CPFILE_FLAG_READWRITE;
- permissions = CPFILE_PERMISSION_NORMAL;
- }
- else if ((mode & FILECHANNELIMPL_FILEOPEN_FLAG_READ))
- {
- /* read */
- flags = CPFILE_FLAG_READ;
- permissions = CPFILE_PERMISSION_NORMAL;
- }
- else
- {
- /* write */
- flags = CPFILE_FLAG_CREATE | CPFILE_FLAG_WRITE;
- if ((mode & FILECHANNELIMPL_FILEOPEN_FLAG_APPEND))
- {
- flags |= CPFILE_FLAG_APPEND;
- }
- else
- {
- flags |= CPFILE_FLAG_TRUNCATE;
- }
- permissions = CPFILE_PERMISSION_NORMAL;
- }
-
- if ((mode & FILECHANNELIMPL_FILEOPEN_FLAG_SYNC))
- {
- flags |= CPFILE_FLAG_SYNC;
- }
-
- if ((mode & FILECHANNELIMPL_FILEOPEN_FLAG_DSYNC))
- {
- flags |= CPFILE_FLAG_DSYNC;
- }
- flags |= CPFILE_FLAG_BINARY;
-
- result = cpio_openFile (filename, &native_fd, flags, permissions);
- if (result != CPNATIVE_OK)
- {
- char message[256]; /* Fixed size we don't need to malloc. */
- const char *error_string = cpnative_getErrorString (result);
-
- snprintf(message, 256, "%s: %s", error_string, filename);
- /* We are only allowed to throw FileNotFoundException. */
- JCL_ThrowException (env,
- "java/io/FileNotFoundException",
- message);
- JCL_free_cstring (env, name, filename);
- return -1;
- }
-
- JCL_free_cstring (env, name, filename);
- return native_fd;
-}
-
-/*
- * Closes the specified file descriptor and return status code.
- * Exception on error
- */
-JNIEXPORT void JNICALL
-Java_gnu_java_nio_channels_FileChannelImpl_implCloseChannel (JNIEnv * env,
- jobject obj)
-{
- int native_fd;
- int result;
-
- native_fd = get_native_fd (env, obj);
-
- do
- {
- result = cpio_closeFile (native_fd);
- if (result != CPNATIVE_OK && result != CPNATIVE_EINTR)
- {
- JCL_ThrowException (env, IO_EXCEPTION,
- cpnative_getErrorString (result));
- return;
- }
- }
- while (result != CPNATIVE_OK);
-}
-
-/*
- * Return number of bytes that can be read from the file w/o blocking.
- * Exception on error
- */
-JNIEXPORT jint JNICALL
-Java_gnu_java_nio_channels_FileChannelImpl_available (JNIEnv * env,
- jobject obj)
-{
- int native_fd;
- jlong bytes_available;
- int result;
-
- native_fd = get_native_fd (env, obj);
-
- do
- {
- result = cpio_availableBytes (native_fd, &bytes_available);
- if (result != CPNATIVE_OK && result != CPNATIVE_EINTR)
- {
- JCL_ThrowException (env, IO_EXCEPTION,
- cpnative_getErrorString (result));
- return 0;
- }
- }
- while (result != CPNATIVE_OK);
-
- /* FIXME NYI ??? why only jint and not jlong? */
- return (jint)bytes_available;
-}
-
-JNIEXPORT jlong JNICALL
-Java_gnu_java_nio_channels_FileChannelImpl_size (JNIEnv * env, jobject obj)
-{
- int native_fd;
- jlong file_size;
- int result;
-
- native_fd = get_native_fd (env, obj);
-
- result = cpio_getFileSize (native_fd, &file_size);
- if (result != CPNATIVE_OK)
- {
- JCL_ThrowException (env, IO_EXCEPTION,
- cpnative_getErrorString (result));
- return -1;
- }
-
- return file_size;
-}
-
-/*
- * Return the current position of the file pointer
- * Exception on error
- */
-JNIEXPORT jlong JNICALL
-Java_gnu_java_nio_channels_FileChannelImpl_implPosition (JNIEnv * env,
- jobject obj)
-{
- int native_fd;
- jlong current_offset;
- int result;
-
- native_fd = get_native_fd (env, obj);
-
- result = cpio_getFilePosition (native_fd, &current_offset);
- if (result != CPNATIVE_OK)
- {
- JCL_ThrowException (env, IO_EXCEPTION,
- cpnative_getErrorString (result));
- return -1;
- }
-
- return current_offset;
-}
-
-/*
- * Wrapper around lseek call. Return new file position
- * Exception on error
- */
-JNIEXPORT void JNICALL
-Java_gnu_java_nio_channels_FileChannelImpl_seek (JNIEnv * env, jobject obj,
- jlong offset)
-{
- int native_fd;
- int result;
-
- native_fd = get_native_fd (env, obj);
-
-#if 0
- /* Should there be such an exception? All native layer macros should
- be accepting 64bit-values if needed. It some target is not able
- to handle such values it should simply operate with 32bit-values
- and convert 64bit-values appriopated. In this case I assume
- problems should not occurre: if some specific target is not able
- to handle 64bit-values the system is limited to 32bit at all, thus
- the application can not do a seek() or something else beyond the
- 32bit limit. It this true?
- */
-
- /* FIXME: What do we do if offset > the max value of off_t on this 32bit
- * system? How do we detect that and what do we do? */
- if (CONVERT_OFF_T_TO_JLONG (native_offset) != offset)
- {
- JCL_ThrowException (env, IO_EXCEPTION,
- "Cannot represent position correctly on this system");
- }
-#endif /* 0 */
-
- result = cpio_setFilePosition (native_fd, offset);
- if (result != CPNATIVE_OK)
- {
- JCL_ThrowException (env, IO_EXCEPTION,
- cpnative_getErrorString (result));
- }
-}
-
-/*
- * Set the length of the file
- * Exception on error
- */
-JNIEXPORT void JNICALL
-Java_gnu_java_nio_channels_FileChannelImpl_implTruncate (JNIEnv * env,
- jobject obj,
- jlong len)
-{
- int native_fd;
- int result;
-
- native_fd = get_native_fd (env, obj);
-
-#if 0
- /* Should there be such an exception? All native layer macros should
- be accepting 64bit-values if needed. It some target is not able
- to handle such values it should simply operate with 32bit-values
- and convert 64bit-values appriopated. In this case I assume
- problems should not occurre: if some specific target is not able
- to handle 64bit-values the system is limited to 32bit at all, thus
- the application can not do a seek() or something else beyond the
- 32bit limit. It this true?
- */
-
- /* FIXME: What do we do if len > the max value of off_t on this 32bit
- * system? How do we detect that and what do we do? */
- if (CONVERT_OFF_T_TO_JLONG (native_len) != len)
- {
- JCL_ThrowException (env, IO_EXCEPTION,
- "Cannot represent position correctly on this system");
- return;
- }
-#endif /* 0 */
-
- result = cpio_setFileSize (native_fd, len);
- if (result != CPNATIVE_OK)
- {
- JCL_ThrowException (env, IO_EXCEPTION,
- cpnative_getErrorString (result));
- }
-}
-
-JNIEXPORT jobject JNICALL
-Java_gnu_java_nio_channels_FileChannelImpl_mapImpl (JNIEnv *env, jobject obj,
- jchar mode, jlong position, jint size)
-{
-#ifdef HAVE_MMAP
- jclass MappedByteBufferImpl_class;
- jmethodID MappedByteBufferImpl_init = NULL;
- jobject Pointer_instance;
- volatile jobject buffer;
- long pagesize;
- int prot, flags;
- int fd;
- void *p;
- void *address;
-
- /* FIXME: should we just assume we're on an OS modern enough to
- have 'sysconf'? And not check for 'getpagesize'? */
-#if defined(HAVE_GETPAGESIZE)
- pagesize = getpagesize ();
-#elif defined(HAVE_SYSCONF)
- pagesize = sysconf (_SC_PAGESIZE);
-#else
- JCL_ThrowException (env, IO_EXCEPTION,
- "can't determine memory page size");
- return NULL;
-#endif /* HAVE_GETPAGESIZE/HAVE_SYSCONF */
-
- if ((*env)->ExceptionOccurred (env))
- {
- return NULL;
- }
-
- fd = get_native_fd (env, obj);
-
- prot = PROT_READ;
- if (mode == '+' || mode == 'c')
- {
- /* When writing we need to make sure the file is big enough,
- otherwise the result of mmap is undefined. */
- jlong filesize;
- filesize = Java_gnu_java_nio_channels_FileChannelImpl_size(env, obj);
- if (filesize == -1)
- return NULL;
- if (position + size > filesize)
- if (ftruncate(fd, position + size) == -1)
- {
- JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
- return NULL;
- }
- prot |= PROT_WRITE;
- }
-
- flags = (mode == 'c' ? MAP_PRIVATE : MAP_SHARED);
- p = mmap (NULL, (size_t) ALIGN_UP (size, pagesize), prot, flags,
- fd, ALIGN_DOWN (position, pagesize));
- if (p == MAP_FAILED)
- {
- JCL_ThrowException (env, IO_EXCEPTION, cpnative_getErrorString (errno));
- return NULL;
- }
-
- /* Unalign the mapped value back up, since we aligned offset
- down to a multiple of the page size. */
- address = (void *) ((char *) p + (position % pagesize));
-
- Pointer_instance = JCL_NewRawDataObject(env, address);
-
- MappedByteBufferImpl_class = (*env)->FindClass (env,
- "java/nio/MappedByteBufferImpl");
- if (MappedByteBufferImpl_class != NULL)
- {
- MappedByteBufferImpl_init =
- (*env)->GetMethodID (env, MappedByteBufferImpl_class,
- "<init>", "(Lgnu/classpath/Pointer;IZ)V");
- }
-
- if ((*env)->ExceptionOccurred (env))
- {
- munmap (p, ALIGN_UP (size, pagesize));
- return NULL;
- }
- if (MappedByteBufferImpl_init == NULL)
- {
- JCL_ThrowException (env, "java/lang/InternalError",
- "could not get MappedByteBufferImpl constructor");
- munmap (p, ALIGN_UP (size, pagesize));
- return NULL;
- }
-
- buffer = (*env)->NewObject (env, MappedByteBufferImpl_class,
- MappedByteBufferImpl_init, Pointer_instance,
- (jint) size, mode == 'r');
- return buffer;
-#else
- (void) obj;
- (void) mode;
- (void) position;
- (void) size;
- JCL_ThrowException (env, IO_EXCEPTION,
- "memory-mapped files not implemented");
- return 0;
-#endif /* HAVE_MMAP */
-}
-
-/*
- * Read a single byte from the file descriptor
- * Return byte read or -1 on eof, exception on error
- */
-JNIEXPORT jint JNICALL
-Java_gnu_java_nio_channels_FileChannelImpl_read__ (JNIEnv * env, jobject obj)
-{
- int native_fd;
- char data;
- jint bytes_read;
- int result;
-
- native_fd = get_native_fd (env, obj);
-
- bytes_read = 0;
- do
- {
- result = cpio_read (native_fd, &data, 1, &bytes_read);
- if ((result == CPNATIVE_OK) && (bytes_read == 0))
- return -1;
-
- if ((result != CPNATIVE_OK) && (result != CPNATIVE_EINTR))
- {
- JCL_ThrowException (env, IO_EXCEPTION,
- cpnative_getErrorString (result));
- return -1;
- }
- }
- while (result != CPNATIVE_OK);
-
- return ((jint) (data & 0xFF));
-}
-
-/*
- * Reads to a byte buffer from the specified file descriptor
- * Return number of bytes read or -1 on eof, exception on error
- */
-JNIEXPORT jint JNICALL
-Java_gnu_java_nio_channels_FileChannelImpl_read___3BII (JNIEnv * env,
- jobject obj,
- jbyteArray buffer,
- jint offset,
- jint length)
-{
- int native_fd;
- jbyte *bufptr;
- jint bytes_read;
- jint n;
- int result;
-
- native_fd = get_native_fd (env, obj);
-
- /* Must return 0 if an attempt is made to read 0 bytes. */
- if (length == 0)
- return 0;
-
- if (offset < 0)
- {
- JCL_ThrowException (env, IO_EXCEPTION, "negative offset");
- return -1;
- }
-
- bufptr = (*env)->GetByteArrayElements (env, buffer, 0);
- if (!bufptr)
- {
- JCL_ThrowException (env, IO_EXCEPTION, "Unexpected JNI error");
- return (-1);
- }
-
- if (length + offset > (*env)->GetArrayLength (env, buffer))
- {
- JCL_ThrowException (env, IO_EXCEPTION,
- "length + offset > buffer.length");
- return -1;
- }
-
- bytes_read = 0;
- do
- {
- result = cpio_read (native_fd, (bufptr + offset + bytes_read),
- (length - bytes_read), &n);
- if ((result == CPNATIVE_OK) && (n == 0))
- {
- (*env)->ReleaseByteArrayElements (env, buffer, bufptr, 0);
- if (bytes_read == 0)
- return -1; /* Signal end of file to Java */
- else
- return bytes_read;
- }
- if ((result != CPNATIVE_OK) && (result != CPNATIVE_EINTR))
- {
- JCL_ThrowException (env, IO_EXCEPTION,
- cpnative_getErrorString (result));
- (*env)->ReleaseByteArrayElements (env, buffer, bufptr, 0);
- return -1;
- }
- if (result == CPNATIVE_OK)
- bytes_read += n;
- }
- while (bytes_read < 1);
-
- (*env)->ReleaseByteArrayElements (env, buffer, bufptr, 0);
- return bytes_read;
-}
-
-/*
- * Writes a single byte to the specified file descriptor
- * Return status code, exception on error
- */
-JNIEXPORT void JNICALL
-Java_gnu_java_nio_channels_FileChannelImpl_write__I (JNIEnv * env,
- jobject obj, jint b)
-{
- int native_fd;
- char native_data;
- jint bytes_written;
- int result;
-
- native_fd = get_native_fd (env, obj);
- native_data = (char) (b & 0xFF);
-
- do
- {
- result = cpio_write (native_fd, &native_data, 1, &bytes_written);
- if ((result != CPNATIVE_OK) && (result != CPNATIVE_EINTR))
- {
- JCL_ThrowException (env, IO_EXCEPTION,
- cpnative_getErrorString (result));
- return;
- }
- }
- while (result != CPNATIVE_OK);
-}
-
-/*
- * Copies all parts of a file to disk.
- */
-JNIEXPORT void JNICALL
-Java_gnu_java_nio_channels_FileChannelImpl_force (JNIEnv * env,
- jobject obj)
-{
- int native_fd;
- int result;
- native_fd = get_native_fd (env, obj);
-
- result = cpio_fsync (native_fd);
- if (result != CPNATIVE_OK)
- JCL_ThrowException (env, IO_EXCEPTION,
- cpnative_getErrorString (result));
-}
-
-/*
- * Writes a byte buffer to the specified file descriptor
- * Return status code, exception on error
- */
-JNIEXPORT void JNICALL
-Java_gnu_java_nio_channels_FileChannelImpl_write___3BII (JNIEnv * env,
- jobject obj,
- jbyteArray buffer,
- jint offset,
- jint length)
-{
- int native_fd;
- jbyte *bufptr;
- jint bytes_written;
- jint n;
- int result;
-
- native_fd = get_native_fd (env, obj);
-
- /* Just return if an attempt is made to write 0 bytes. */
- if (length == 0)
- return;
-
- bufptr = (*env)->GetByteArrayElements (env, buffer, 0);
- if (!bufptr)
- {
- JCL_ThrowException (env, IO_EXCEPTION, "Unexpected JNI error");
- return;
- }
-
- bytes_written = 0;
- while (bytes_written < length)
- {
- result = cpio_write (native_fd, (bufptr + offset + bytes_written),
- (length - bytes_written), &n);
- if ((result != CPNATIVE_OK) && (result != CPNATIVE_EINTR))
- {
- JCL_ThrowException (env, IO_EXCEPTION,
- cpnative_getErrorString (result));
- (*env)->ReleaseByteArrayElements (env, buffer, bufptr, 0);
- return;
- }
- if (result == CPNATIVE_OK)
- bytes_written += n;
- }
-
- (*env)->ReleaseByteArrayElements (env, buffer, bufptr, 0);
-}
-
-JNIEXPORT jboolean JNICALL
-Java_gnu_java_nio_channels_FileChannelImpl_lock (JNIEnv *env, jobject obj,
- jlong position, jlong size,
- jboolean shared, jboolean wait)
-{
-#ifdef HAVE_FCNTL
- int fd = get_native_fd (env, obj);
- int cmd = wait ? F_SETLKW : F_SETLK;
- struct flock flock;
- int ret;
-
- flock.l_type = shared ? F_RDLCK : F_WRLCK;
- flock.l_whence = SEEK_SET;
- flock.l_start = (off_t) position;
- /* Long.MAX_VALUE means lock everything possible starting at pos. */
- if (size == 9223372036854775807LL)
- flock.l_len = 0;
- else
- flock.l_len = (off_t) size;
-
- ret = fcntl (fd, cmd, &flock);
- /* fprintf(stderr, "fd %d, wait %d, shared %d, ret %d, position %lld, size %lld, l_start %ld, l_len %ld\n", fd, wait, shared,ret, position, size, (long) flock.l_start, (long) flock.l_len); */
- if (ret)
- {
- /* Linux man pages for fcntl state that errno might be either
- EACCES or EAGAIN if we try F_SETLK, and another process has
- an overlapping lock. We should not get an unexpected errno. */
- if (errno != EACCES && errno != EAGAIN)
- {
- JCL_ThrowException (env, "java/lang/InternalError",
- cpnative_getErrorString (errno));
- }
- return JNI_FALSE;
- }
- return JNI_TRUE;
-#else
- (void) obj;
- (void) position;
- (void) size;
- (void) shared;
- (void) wait;
- JCL_ThrowException (env, "java/lang/UnsupportedOperationException",
- "file locks not implemented on this platform");
- return JNI_FALSE;
-#endif /* HAVE_FCNTL */
-}
-
-JNIEXPORT void JNICALL
-Java_gnu_java_nio_channels_FileChannelImpl_unlock (JNIEnv *env,
- jobject obj,
- jlong position,
- jlong length)
-{
-#ifdef HAVE_FCNTL
- int fd = get_native_fd (env, obj);
- struct flock flock;
- int ret;
-
- flock.l_type = F_UNLCK;
- flock.l_whence = SEEK_SET;
- flock.l_start = (off_t) position;
- /* Long.MAX_VALUE means unlock everything possible starting at pos. */
- if (length == 9223372036854775807LL)
- flock.l_len = 0;
- else
- flock.l_len = (off_t) length;
-
- ret = fcntl (fd, F_SETLK, &flock);
- if (ret)
- {
- JCL_ThrowException (env, "java/lang/InternalError",
- cpnative_getErrorString (errno));
- }
-#else
- (void) obj;
- (void) position;
- (void) length;
- JCL_ThrowException (env, "java/lang/UnsupportedOperationException",
- "file locks not implemented on this platform");
-#endif /* HAVE_FCNTL */
-}