public void propertyChange(PropertyChangeEvent evt) {
    String prop = evt.getPropertyName();
    Object newValue = evt.getNewValue();
    Object oldValue = evt.getOldValue();

    if ("focusOwner".equals(prop) && oldValue instanceof JTextArea) {
      JTextArea freeText = (JTextArea) oldValue;
      if (freeText.equals(freeTextPane)) {
        freeText.setEditable(false);
        if (contentTextChange) {
          contentTextChange = false;
          resetAppearanceShapes();
        }
        if (freeText instanceof FreeTextArea) {
          ((FreeTextArea) freeText).setActive(false);
        }
      }
    } else if ("focusOwner".equals(prop) && newValue instanceof JTextArea) {
      JTextArea freeText = (JTextArea) newValue;
      if (freeText.equals(freeTextPane) && !annotation.getFlagReadOnly()) {
        freeText.setEditable(true);
        if (freeText instanceof FreeTextArea) {
          ((FreeTextArea) freeText).setActive(true);
        }
      }
    }
  }
  public FreeTextAnnotationComponent(
      Annotation annotation,
      DocumentViewController documentViewController,
      final AbstractPageViewComponent pageViewComponent,
      final DocumentViewModel documentViewModel) {
    super(annotation, documentViewController, pageViewComponent, documentViewModel);
    isRollover = false;
    isShowInvisibleBorder = false;

    freeTextAnnotation = (FreeTextAnnotation) annotation;

    // update the shapes array pruning any text glyphs as well as
    // extra any useful font information for the editing of this annotation.
    if (annotation.getShapes() != null) {
      ArrayList<DrawCmd> shapes = annotation.getShapes().getShapes();
      DrawCmd cmd;
      for (int i = 0; i < shapes.size(); i++) {
        cmd = shapes.get(i);
        if (cmd instanceof TextSpriteDrawCmd) {
          // grab the font reference
          TextSprite tmp = ((TextSpriteDrawCmd) cmd).getTextSprite();
          FontFile font = tmp.getFont();
          freeTextAnnotation.setFontSize((int) font.getSize());
          freeTextAnnotation.setFontColor(tmp.getStrokeColor());
          // remove all text.
          shapes.remove(i);
        }
      }
      ((FreeTextAnnotation) annotation).clearShapes();
    }
    // create the textArea to display the text.
    freeTextPane =
        new FreeTextArea(
            new FreeTextArea.ZoomProvider() {
              private DocumentViewModel model;

              {
                this.model = documentViewModel;
              }

              public float getZoom() {
                return this.model.getViewZoom();
              }
            });
    // line wrap false to force users to add line breaks.
    freeTextPane.setLineWrap(false);
    freeTextPane.setBackground(new Color(0, 0, 0, 0));
    freeTextPane.setMargin(new Insets(0, 0, 0, 0));
    // lock the field until the correct tool selects it.
    freeTextPane.setEditable(false);
    // clean up the contents make sure we have \n instead of \r
    String contents = freeTextAnnotation.getContents();
    if (contents != null) {
      contents = contents.replace('\r', '\n');
      freeTextPane.setText(contents);
    }

    // setup change listener so we now when to set the annotations AP stream
    freeTextPane
        .getDocument()
        .addDocumentListener(
            new DocumentListener() {
              public void insertUpdate(DocumentEvent e) {
                contentTextChange = true;
              }

              public void removeUpdate(DocumentEvent e) {
                contentTextChange = true;
              }

              public void changedUpdate(DocumentEvent e) {
                contentTextChange = true;
              }
            });

    GridLayout grid = new GridLayout(1, 1, 0, 0);
    this.setLayout(grid);
    this.add(freeTextPane);

    // add a focus management listener.
    KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
    focusManager.addPropertyChangeListener(this);

    // set the default size hen building from external file
    if (annotation.getBbox() != null) {
      setBounds(annotation.getBbox().getBounds());
    }

    resetAppearanceShapes();
    revalidate();
  }
  public void setAppearanceStream() {
    // copy over annotation properties from the free text annotation.
    if (fontFile == null || freeTextAnnotation.isFontPropertyChanged()) {
      fontFile =
          FontManager.getInstance()
              .getType1AWTFont(freeTextAnnotation.getFontName(), freeTextAnnotation.getFontSize());
    }
    freeTextPane.setFont(fontFile);
    freeTextPane.setForeground(freeTextAnnotation.getFontColor());

    if (freeTextAnnotation.isFillType()) {
      freeTextPane.setOpaque(true);
      freeTextPane.setBackground(freeTextAnnotation.getFillColor());
    } else {
      freeTextPane.setOpaque(false);
    }
    if (freeTextAnnotation.isStrokeType()) {
      if (freeTextAnnotation.getBorderStyle().isStyleSolid()) {
        freeTextPane.setBorder(
            BorderFactory.createLineBorder(
                freeTextAnnotation.getColor(),
                (int) freeTextAnnotation.getBorderStyle().getStrokeWidth()));
      } else if (freeTextAnnotation.getBorderStyle().isStyleDashed()) {
        freeTextPane.setBorder(
            new DashedBorder(freeTextAnnotation.getBorderStyle(), freeTextAnnotation.getColor()));
      }
    } else {
      freeTextPane.setBorder(BorderFactory.createEmptyBorder());
    }

    String content = null;
    try {
      content = freeTextPane.getDocument().getText(0, freeTextPane.getDocument().getLength());
    } catch (BadLocationException e) {
      logger.warning("Error getting rich text.");
    }
    Rectangle tBbox = convertToPageSpace(getBounds());

    // generate the shapes
    freeTextAnnotation.setBBox(tBbox);
    freeTextAnnotation.setContents(content);
    freeTextAnnotation.setRichText(freeTextPane.getText());
    freeTextPane.revalidate();
  }