0N/A/*
2362N/A * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/Apackage javax.swing.text.html;
0N/A
0N/Aimport java.awt.*;
0N/Aimport java.util.*;
0N/Aimport java.net.*;
0N/Aimport java.io.*;
0N/Aimport javax.swing.*;
0N/Aimport javax.swing.text.*;
0N/Aimport javax.swing.event.*;
0N/A
0N/Aimport sun.swing.text.html.FrameEditorPaneTag;
0N/A
0N/A/**
0N/A * Implements a FrameView, intended to support the HTML
0N/A * <FRAME> tag. Supports the frameborder, scrolling,
0N/A * marginwidth and marginheight attributes.
0N/A *
0N/A * @author Sunita Mani
0N/A */
0N/A
0N/Aclass FrameView extends ComponentView implements HyperlinkListener {
0N/A
0N/A
0N/A JEditorPane htmlPane;
0N/A JScrollPane scroller;
0N/A boolean editable;
0N/A float width;
0N/A float height;
0N/A URL src;
0N/A /** Set to true when the component has been created. */
0N/A private boolean createdComponent;
0N/A
0N/A /**
0N/A * Creates a new Frame.
0N/A *
0N/A * @param elem the element to represent.
0N/A */
0N/A public FrameView(Element elem) {
0N/A super(elem);
0N/A }
0N/A
0N/A protected Component createComponent() {
0N/A
0N/A Element elem = getElement();
0N/A AttributeSet attributes = elem.getAttributes();
0N/A String srcAtt = (String)attributes.getAttribute(HTML.Attribute.SRC);
0N/A
0N/A if ((srcAtt != null) && (!srcAtt.equals(""))) {
0N/A try {
0N/A URL base = ((HTMLDocument)elem.getDocument()).getBase();
0N/A src = new URL(base, srcAtt);
0N/A htmlPane = new FrameEditorPane();
0N/A htmlPane.addHyperlinkListener(this);
0N/A JEditorPane host = getHostPane();
0N/A boolean isAutoFormSubmission = true;
0N/A if (host != null) {
0N/A htmlPane.setEditable(host.isEditable());
0N/A String charset = (String) host.getClientProperty("charset");
0N/A if (charset != null) {
0N/A htmlPane.putClientProperty("charset", charset);
0N/A }
0N/A HTMLEditorKit hostKit = (HTMLEditorKit)host.getEditorKit();
0N/A if (hostKit != null) {
0N/A isAutoFormSubmission = hostKit.isAutoFormSubmission();
0N/A }
0N/A }
0N/A htmlPane.setPage(src);
0N/A HTMLEditorKit kit = (HTMLEditorKit)htmlPane.getEditorKit();
0N/A if (kit != null) {
0N/A kit.setAutoFormSubmission(isAutoFormSubmission);
0N/A }
0N/A
0N/A Document doc = htmlPane.getDocument();
0N/A if (doc instanceof HTMLDocument) {
0N/A ((HTMLDocument)doc).setFrameDocumentState(true);
0N/A }
0N/A setMargin();
0N/A createScrollPane();
0N/A setBorder();
0N/A } catch (MalformedURLException e) {
0N/A e.printStackTrace();
0N/A } catch (IOException e1) {
0N/A e1.printStackTrace();
0N/A }
0N/A }
0N/A createdComponent = true;
0N/A return scroller;
0N/A }
0N/A
0N/A JEditorPane getHostPane() {
0N/A Container c = getContainer();
0N/A while ((c != null) && ! (c instanceof JEditorPane)) {
0N/A c = c.getParent();
0N/A }
0N/A return (JEditorPane) c;
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Sets the parent view for the FrameView.
0N/A * Also determines if the FrameView should be editable
0N/A * or not based on whether the JTextComponent that
0N/A * contains it is editable.
0N/A *
0N/A * @param parent View
0N/A */
0N/A public void setParent(View parent) {
0N/A if (parent != null) {
0N/A JTextComponent t = (JTextComponent)parent.getContainer();
0N/A editable = t.isEditable();
0N/A }
0N/A super.setParent(parent);
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Also determines if the FrameView should be editable
0N/A * or not based on whether the JTextComponent that
0N/A * contains it is editable. And then proceeds to call
0N/A * the superclass to do the paint().
0N/A *
0N/A * @param parent View
0N/A * @see text.ComponentView#paint
0N/A */
0N/A public void paint(Graphics g, Shape allocation) {
0N/A
0N/A Container host = getContainer();
0N/A if (host != null && htmlPane != null &&
0N/A htmlPane.isEditable() != ((JTextComponent)host).isEditable()) {
0N/A editable = ((JTextComponent)host).isEditable();
0N/A htmlPane.setEditable(editable);
0N/A }
0N/A super.paint(g, allocation);
0N/A }
0N/A
0N/A
0N/A /**
0N/A * If the marginwidth or marginheight attributes have been specified,
0N/A * then the JEditorPane's margin's are set to the new values.
0N/A */
0N/A private void setMargin() {
0N/A int margin = 0;
0N/A Insets in = htmlPane.getMargin();
0N/A Insets newInsets;
0N/A boolean modified = false;
0N/A AttributeSet attributes = getElement().getAttributes();
0N/A String marginStr = (String)attributes.getAttribute(HTML.Attribute.MARGINWIDTH);
0N/A if ( in != null) {
0N/A newInsets = new Insets(in.top, in.left, in.right, in.bottom);
0N/A } else {
0N/A newInsets = new Insets(0,0,0,0);
0N/A }
0N/A if (marginStr != null) {
0N/A margin = Integer.parseInt(marginStr);
0N/A if (margin > 0) {
0N/A newInsets.left = margin;
0N/A newInsets.right = margin;
0N/A modified = true;
0N/A }
0N/A }
0N/A marginStr = (String)attributes.getAttribute(HTML.Attribute.MARGINHEIGHT);
0N/A if (marginStr != null) {
0N/A margin = Integer.parseInt(marginStr);
0N/A if (margin > 0) {
0N/A newInsets.top = margin;
0N/A newInsets.bottom = margin;
0N/A modified = true;
0N/A }
0N/A }
0N/A if (modified) {
0N/A htmlPane.setMargin(newInsets);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * If the frameborder attribute has been specified, either in the frame,
0N/A * or by the frames enclosing frameset, the JScrollPane's setBorder()
0N/A * method is invoked to achieve the desired look.
0N/A */
0N/A private void setBorder() {
0N/A
0N/A AttributeSet attributes = getElement().getAttributes();
0N/A String frameBorder = (String)attributes.getAttribute(HTML.Attribute.FRAMEBORDER);
0N/A if ((frameBorder != null) &&
0N/A (frameBorder.equals("no") || frameBorder.equals("0"))) {
0N/A // make invisible borders.
0N/A scroller.setBorder(null);
0N/A }
0N/A }
0N/A
0N/A
0N/A /**
0N/A * This method creates the JScrollPane. The scrollbar policy is determined by
0N/A * the scrolling attribute. If not defined, the default is "auto" which
0N/A * maps to the scrollbar's being displayed as needed.
0N/A */
0N/A private void createScrollPane() {
0N/A AttributeSet attributes = getElement().getAttributes();
0N/A String scrolling = (String)attributes.getAttribute(HTML.Attribute.SCROLLING);
0N/A if (scrolling == null) {
0N/A scrolling = "auto";
0N/A }
0N/A
0N/A if (!scrolling.equals("no")) {
0N/A if (scrolling.equals("yes")) {
0N/A scroller = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
0N/A JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
0N/A } else {
0N/A // scrollbars will be displayed if needed
0N/A //
0N/A scroller = new JScrollPane();
0N/A }
0N/A } else {
0N/A scroller = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_NEVER,
0N/A JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
0N/A }
0N/A
0N/A JViewport vp = scroller.getViewport();
0N/A vp.add(htmlPane);
0N/A vp.setBackingStoreEnabled(true);
0N/A scroller.setMinimumSize(new Dimension(5,5));
0N/A scroller.setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Finds the outermost FrameSetView. It then
0N/A * returns that FrameSetView's container.
0N/A */
0N/A JEditorPane getOutermostJEditorPane() {
0N/A
0N/A View parent = getParent();
0N/A FrameSetView frameSetView = null;
0N/A while (parent != null) {
0N/A if (parent instanceof FrameSetView) {
0N/A frameSetView = (FrameSetView)parent;
0N/A }
0N/A parent = parent.getParent();
0N/A }
0N/A if (frameSetView != null) {
0N/A return (JEditorPane)frameSetView.getContainer();
0N/A }
0N/A return null;
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Returns true if this frame is contained within
0N/A * a nested frameset.
0N/A */
0N/A private boolean inNestedFrameSet() {
0N/A FrameSetView parent = (FrameSetView)getParent();
0N/A return (parent.getParent() instanceof FrameSetView);
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Notification of a change relative to a
0N/A * hyperlink. This method searches for the outermost
0N/A * JEditorPane, and then fires an HTMLFrameHyperlinkEvent
0N/A * to that frame. In addition, if the target is _parent,
0N/A * and there is not nested framesets then the target is
0N/A * reset to _top. If the target is _top, in addition to
0N/A * firing the event to the outermost JEditorPane, this
0N/A * method also invokes the setPage() method and explicitly
0N/A * replaces the current document with the destination url.
0N/A *
0N/A * @param HyperlinkEvent
0N/A */
0N/A public void hyperlinkUpdate(HyperlinkEvent evt) {
0N/A
0N/A JEditorPane c = getOutermostJEditorPane();
0N/A if (c == null) {
0N/A return;
0N/A }
0N/A
0N/A if (!(evt instanceof HTMLFrameHyperlinkEvent)) {
0N/A c.fireHyperlinkUpdate(evt);
0N/A return;
0N/A }
0N/A
0N/A HTMLFrameHyperlinkEvent e = (HTMLFrameHyperlinkEvent)evt;
0N/A
0N/A if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
0N/A String target = e.getTarget();
0N/A String postTarget = target;
0N/A
0N/A if (target.equals("_parent") && !inNestedFrameSet()){
0N/A target = "_top";
0N/A }
0N/A
0N/A if (evt instanceof FormSubmitEvent) {
0N/A HTMLEditorKit kit = (HTMLEditorKit)c.getEditorKit();
0N/A if (kit != null && kit.isAutoFormSubmission()) {
0N/A if (target.equals("_top")) {
0N/A try {
0N/A movePostData(c, postTarget);
0N/A c.setPage(e.getURL());
0N/A } catch (IOException ex) {
0N/A // Need a way to handle exceptions
0N/A }
0N/A } else {
0N/A HTMLDocument doc = (HTMLDocument)c.getDocument();
0N/A doc.processHTMLFrameHyperlinkEvent(e);
0N/A }
0N/A } else {
0N/A c.fireHyperlinkUpdate(evt);
0N/A }
0N/A return;
0N/A }
0N/A
0N/A if (target.equals("_top")) {
0N/A try {
0N/A c.setPage(e.getURL());
0N/A } catch (IOException ex) {
0N/A // Need a way to handle exceptions
0N/A // ex.printStackTrace();
0N/A }
0N/A }
0N/A if (!c.isEditable()) {
0N/A c.fireHyperlinkUpdate(new HTMLFrameHyperlinkEvent(c,
0N/A e.getEventType(),
0N/A e.getURL(),
0N/A e.getDescription(),
0N/A getElement(),
0N/A e.getInputEvent(),
0N/A target));
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Gives notification from the document that attributes were changed
0N/A * in a location that this view is responsible for. Currently this view
0N/A * handles changes to its SRC attribute.
0N/A *
0N/A * @param e the change information from the associated document
0N/A * @param a the current allocation of the view
0N/A * @param f the factory to use to rebuild if the view has children
0N/A *
0N/A */
0N/A public void changedUpdate(DocumentEvent e, Shape a, ViewFactory f) {
0N/A
0N/A Element elem = getElement();
0N/A AttributeSet attributes = elem.getAttributes();
0N/A
0N/A URL oldPage = src;
0N/A
0N/A String srcAtt = (String)attributes.getAttribute(HTML.Attribute.SRC);
0N/A URL base = ((HTMLDocument)elem.getDocument()).getBase();
0N/A try {
0N/A if (!createdComponent) {
0N/A return;
0N/A }
0N/A
0N/A Object postData = movePostData(htmlPane, null);
0N/A src = new URL(base, srcAtt);
0N/A if (oldPage.equals(src) && (src.getRef() == null) && (postData == null)) {
0N/A return;
0N/A }
0N/A
0N/A htmlPane.setPage(src);
0N/A Document newDoc = htmlPane.getDocument();
0N/A if (newDoc instanceof HTMLDocument) {
0N/A ((HTMLDocument)newDoc).setFrameDocumentState(true);
0N/A }
0N/A } catch (MalformedURLException e1) {
0N/A // Need a way to handle exceptions
0N/A //e1.printStackTrace();
0N/A } catch (IOException e2) {
0N/A // Need a way to handle exceptions
0N/A //e2.printStackTrace();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Move POST data from temporary storage into the target document property.
0N/A *
0N/A * @return the POST data or null if no data found
0N/A */
0N/A private Object movePostData(JEditorPane targetPane, String frameName) {
0N/A Object postData = null;
0N/A JEditorPane p = getOutermostJEditorPane();
0N/A if (p != null) {
0N/A if (frameName == null) {
0N/A frameName = (String) getElement().getAttributes().getAttribute(
0N/A HTML.Attribute.NAME);
0N/A }
0N/A if (frameName != null) {
0N/A String propName = FormView.PostDataProperty + "." + frameName;
0N/A Document d = p.getDocument();
0N/A postData = d.getProperty(propName);
0N/A if (postData != null) {
0N/A targetPane.getDocument().putProperty(
0N/A FormView.PostDataProperty, postData);
0N/A d.putProperty(propName, null);
0N/A }
0N/A }
0N/A }
0N/A
0N/A return postData;
0N/A }
0N/A
0N/A /**
0N/A * Determines the minimum span for this view along an
0N/A * axis.
0N/A *
0N/A * @param axis may be either <code>View.X_AXIS</code> or
0N/A * <code>View.Y_AXIS</code>
0N/A * @return the preferred span; given that we do not
0N/A * support resizing of frames, the minimum span returned
0N/A * is the same as the preferred span
0N/A *
0N/A */
0N/A public float getMinimumSpan(int axis) {
0N/A return 5;
0N/A }
0N/A
0N/A /**
0N/A * Determines the maximum span for this view along an
0N/A * axis.
0N/A *
0N/A * @param axis may be either <code>View.X_AXIS</code> or
0N/A * <code>View.Y_AXIS</code>
0N/A * @return the preferred span; given that we do not
0N/A * support resizing of frames, the maximum span returned
0N/A * is the same as the preferred span
0N/A *
0N/A */
0N/A public float getMaximumSpan(int axis) {
0N/A return Integer.MAX_VALUE;
0N/A }
0N/A
0N/A /** Editor pane rendering frame of HTML document
0N/A * It uses the same editor kits classes as outermost JEditorPane
0N/A */
0N/A class FrameEditorPane extends JEditorPane implements FrameEditorPaneTag {
0N/A public EditorKit getEditorKitForContentType(String type) {
0N/A EditorKit editorKit = super.getEditorKitForContentType(type);
0N/A JEditorPane outerMostJEditorPane = null;
0N/A if ((outerMostJEditorPane = getOutermostJEditorPane()) != null) {
0N/A EditorKit inheritedEditorKit = outerMostJEditorPane.getEditorKitForContentType(type);
0N/A if (! editorKit.getClass().equals(inheritedEditorKit.getClass())) {
0N/A editorKit = (EditorKit) inheritedEditorKit.clone();
0N/A setEditorKitForContentType(type, editorKit);
0N/A }
0N/A }
0N/A return editorKit;
0N/A }
0N/A
0N/A FrameView getFrameView() {
0N/A return FrameView.this;
0N/A }
0N/A }
0N/A}