public void visit(LinkModel link) {
   try {
     // make sure to reload
     editorPane.getDocument().putProperty(Document.StreamDescriptionProperty, null);
     // JW: editorPane defaults to asynchronous loading
     // no need to explicitly start a thread - really?
     editorPane.setPage(link.getURL());
     link.setVisited(true);
   } catch (IOException e1) {
     editorPane.setText("<html>Error 404: couldn't show " + link.getURL() + " </html>");
   }
 }
  /**
   * The aggregate components which compise the combo box are unregistered and uninitialized. This
   * method is called as part of the UI uninstallation process.
   */
  protected void uninstallComponents() {
    iconLabel = null;
    errorMessage = null;
    closeButton = null;
    reportButton = null;

    detailButton.removeActionListener(detailListener);
    detailButton = null;

    details.setTransferHandler(null);
    details = null;

    detailsScrollPane.removeAll();
    detailsScrollPane = null;

    detailsPanel.setLayout(null);
    detailsPanel.removeAll();
    detailsPanel = null;

    copyToClipboardButton.removeActionListener(copyToClipboardListener);
    copyToClipboardButton = null;

    pane.removeAll();
    pane.setLayout(null);
    pane.setBorder(null);
  }
 public EditorPaneLinkVisitor(JXEditorPane pane) {
   if (pane == null) {
     pane = createDefaultEditorPane();
   }
   this.editorPane = pane;
   pane.addHyperlinkListener(getHyperlinkListener());
 }
  /**
   * Set the details section to be either visible or invisible. Set the text of the Details button
   * accordingly.
   *
   * @param b if true details section will be visible
   */
  private void setDetailsVisible(boolean b) {
    if (b) {
      collapsedHeight = pane.getHeight();
      pane.setSize(
          pane.getWidth(),
          expandedHeight == 0 ? collapsedHeight + getDetailsHeight() : expandedHeight);
      detailsPanel.setVisible(true);
      configureDetailsButton(true);
      detailsPanel.applyComponentOrientation(detailButton.getComponentOrientation());

      // workaround for bidi bug, if the text is not set "again" and the component orientation has
      // changed
      // then the text won't be aligned correctly. To reproduce this (in JDK 1.5) show two dialogs
      // in one
      // use LTOR orientation and in the second use RTOL orientation and press "details" in both.
      // Text in the text box should be aligned to right/left respectively, without this line this
      // doesn't
      // occure I assume because bidi properties are tested when the text is set and are not updated
      // later
      // on when setComponentOrientation is invoked.
      details.setText(details.getText());
      details.setCaretPosition(0);
    } else if (collapsedHeight != 0) { // only collapse if the dialog has been expanded
      expandedHeight = pane.getHeight();
      detailsPanel.setVisible(false);
      configureDetailsButton(false);
      // Trick to force errorMessage JTextArea to resize according
      // to its columns property.
      errorMessage.setSize(0, 0);
      errorMessage.setSize(errorMessage.getPreferredSize());
      pane.setSize(pane.getWidth(), collapsedHeight);
    } else {
      detailsPanel.setVisible(false);
    }

    pane.doLayout();
  }
  /**
   * Creates and initializes the components which make up the aggregate combo box. This method is
   * called as part of the UI installation process.
   */
  protected void installComponents() {
    iconLabel = new JLabel(pane.getIcon());

    errorMessage = new JEditorPane();
    errorMessage.setEditable(false);
    errorMessage.setContentType("text/html");
    errorMessage.setEditorKitForContentType("text/plain", new StyledEditorKit());
    errorMessage.setEditorKitForContentType("text/html", new HTMLEditorKit());

    errorMessage.setOpaque(false);
    errorMessage.putClientProperty(JXEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE);

    closeButton =
        new JButton(
            UIManagerExt.getString(CLASS_NAME + ".ok_button_text", errorMessage.getLocale()));

    reportButton = new EqualSizeJButton(pane.getActionMap().get(JXErrorPane.REPORT_ACTION_KEY));

    detailButton =
        new EqualSizeJButton(
            UIManagerExt.getString(CLASS_NAME + ".details_expand_text", errorMessage.getLocale()));

    details = new JXEditorPane();
    details.setContentType("text/html");
    details.putClientProperty(JXEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE);
    details.setTransferHandler(createDetailsTransferHandler(details));
    detailsScrollPane = new JScrollPane(details);
    detailsScrollPane.setPreferredSize(new Dimension(10, 250));
    details.setEditable(false);
    detailsPanel = new JPanel();
    detailsPanel.setVisible(false);
    copyToClipboardButton =
        new JButton(
            UIManagerExt.getString(
                CLASS_NAME + ".copy_to_clipboard_button_text", errorMessage.getLocale()));
    copyToClipboardListener =
        new ActionListener() {
          public void actionPerformed(ActionEvent ae) {
            details.copy();
          }
        };
    copyToClipboardButton.addActionListener(copyToClipboardListener);

    detailsPanel.setLayout(createDetailPanelLayout());
    detailsPanel.add(detailsScrollPane);
    detailsPanel.add(copyToClipboardButton);

    // Create error scroll pane. Make sure this happens before call to createErrorPaneLayout() in
    // case any extending
    // class wants to manipulate the component there.
    errorScrollPane = new JScrollPane(errorMessage);
    errorScrollPane.setBorder(new EmptyBorder(0, 0, 5, 0));
    errorScrollPane.setOpaque(false);
    errorScrollPane.getViewport().setOpaque(false);

    // initialize the gui. Most of this code is similar between Mac and PC, but
    // where they differ protected methods have been written allowing the
    // mac implementation to alter the layout of the dialog.
    pane.setLayout(createErrorPaneLayout());

    // An empty border which constitutes the padding from the edge of the
    // dialog to the content. All content that butts against this border should
    // not be padded.
    Insets borderInsets = new Insets(16, 24, 16, 17);
    pane.setBorder(
        BorderFactory.createEmptyBorder(
            borderInsets.top, borderInsets.left, borderInsets.bottom, borderInsets.right));

    // add the JLabel responsible for displaying the icon.
    // TODO: in the future, replace this usage of a JLabel with a JXImagePane,
    // which may add additional "coolness" such as allowing the user to drag
    // the image off the dialog onto the desktop. This kind of coolness is common
    // in the mac world.
    pane.add(iconLabel);
    pane.add(errorScrollPane);
    pane.add(closeButton);
    pane.add(reportButton);
    reportButton.setVisible(false); // not visible by default
    pane.add(detailButton);
    pane.add(detailsPanel);

    // make the buttons the same size
    EqualSizeJButton[] buttons =
        new EqualSizeJButton[] {(EqualSizeJButton) detailButton, (EqualSizeJButton) reportButton};
    ((EqualSizeJButton) reportButton).setGroup(buttons);
    ((EqualSizeJButton) detailButton).setGroup(buttons);

    reportButton.setMinimumSize(reportButton.getPreferredSize());
    detailButton.setMinimumSize(detailButton.getPreferredSize());

    // set the event handling
    detailListener = new DetailsClickEvent();
    detailButton.addActionListener(detailListener);
  }
 protected JXEditorPane createDefaultEditorPane() {
   final JXEditorPane editorPane = new JXEditorPane();
   editorPane.setEditable(false);
   editorPane.setContentType("text/html");
   return editorPane;
 }