/*
 * File    : TextActivityEditorTextPanel.java
 * Created : 10-jun-2002 09:59
 * By      : fbusquets
 *
 * JClic - Authoring and playing system for educational activities
 *
 * Copyright (C) 2000 - 2018 Francesc Busquets & Departament
 * d'Educacio de la Generalitat de Catalunya
 *
 * This program 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 of the License, or
 * (at your option) any later version.
 *
 * This program 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 (see the LICENSE file).
 */

package edu.xtec.jclic.activities.text;

import edu.xtec.jclic.*;
import edu.xtec.jclic.beans.ColorButton;
import edu.xtec.jclic.beans.SmallIntEditor;
import edu.xtec.jclic.boxes.*;
import edu.xtec.util.FontCheck;
import edu.xtec.util.Messages;
import edu.xtec.util.Resizer;
import edu.xtec.util.ResizerPanel;
import edu.xtec.util.ResourceManager;
import edu.xtec.util.SmallButtonBorder;
import java.awt.*;
import java.util.EventObject;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;

/**
 * @author Francesc Busquets (fbusquets@xtec.cat)
 * @version 1.0
 */
public class TextActivityEditorTextPanel extends ActivityEditorInternalPanel implements Resizer.ResizerListener {

  // protected boolean loading;
  protected Resizer resizer;
  protected boolean skipUpdate;
  protected String fontName;
  protected int fontSize;
  protected boolean changeCombos = true;

  /** Creates new form MenuEditorPanel */
  public TextActivityEditorTextPanel(ActivityEditorPanel parent) {
    super(parent);
    initComponents();
    textScroll.setBorder(BorderFactory.createEmptyBorder());
    textScroll.getVerticalScrollBar().setBorder(BorderFactory.createLineBorder(Color.darkGray, 1));
    textPane.addCaretListener(caretListener);
    resizer = new Resizer(previewPanel, null, false, this);
  }

  CaretListener caretListener = new CaretListener() {
    public void caretUpdate(CaretEvent e) {
      showAttributes(e.getDot());
    }
  };

  /**
   * This method is called from within the constructor to initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is always
   * regenerated by the Form Editor.
   */
  // <editor-fold defaultstate="collapsed" desc="Generated
  // Code">//GEN-BEGIN:initComponents
  private void initComponents() {
    java.awt.GridBagConstraints gridBagConstraints;

    alignGrp = new javax.swing.ButtonGroup();
    mainScroll = new javax.swing.JScrollPane();
    previewPanel = new PreviewPanel();
    textScroll = new javax.swing.JScrollPane();
    textPane = new javax.swing.JTextPane();
    javax.swing.JTabbedPane ctrlPanel = new javax.swing.JTabbedPane();
    javax.swing.JPanel actPanel = new javax.swing.JPanel();
    targetBtn = new javax.swing.JToggleButton();
    editTargetBtn = new javax.swing.JButton();
    insertBoxBtn = new javax.swing.JButton();
    prevScreenBtn = new javax.swing.JButton();
    optionsBtn = new javax.swing.JButton();
    typeBtn = new javax.swing.JButton();
    javax.swing.JLabel widthLb = new javax.swing.JLabel();
    widthEdit = new edu.xtec.jclic.beans.SmallIntEditor();
    javax.swing.JLabel heightLb = new javax.swing.JLabel();
    heightEdit = new edu.xtec.jclic.beans.SmallIntEditor();
    javax.swing.JPanel stylePanel = new javax.swing.JPanel();
    styleBtn = new javax.swing.JButton();
    clearStylesBtn = new javax.swing.JButton();
    fontFaceCombo = new JComboBox<Object>(FontCheck.getFontList(false));
    fontSizeCombo = new JComboBox<Object>(FontCheck.fontSizes);
    boldBtn = new javax.swing.JToggleButton();
    italicBtn = new javax.swing.JToggleButton();
    underlineBtn = new javax.swing.JToggleButton();
    alLeftBtn = new javax.swing.JToggleButton();
    alCenterBtn = new javax.swing.JToggleButton();
    alRightBtn = new javax.swing.JToggleButton();
    javax.swing.JLabel textColorLb = new javax.swing.JLabel();
    textColorBtn = new edu.xtec.jclic.beans.ColorButton();
    textColorBtn.setOptions(options);
    javax.swing.JLabel bgColorLb = new javax.swing.JLabel();
    bgColorBtn = new edu.xtec.jclic.beans.ColorButton();
    bgColorBtn.setOptions(options);

    setLayout(new java.awt.BorderLayout());

    previewPanel.setPreferredSize(new java.awt.Dimension(780, 580));

    textPane.setPreferredSize(new java.awt.Dimension(Activity.DEFAULT_WIDTH, Activity.DEFAULT_HEIGHT));
    textScroll.setViewportView(textPane);

    previewPanel.add(textScroll);

    mainScroll.setViewportView(previewPanel);

    add(mainScroll, java.awt.BorderLayout.CENTER);

    actPanel.setLayout(new java.awt.GridBagLayout());

    targetBtn.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/xtec/resources/icons/text_target.gif"))); // NOI18N
    targetBtn.setToolTipText(options.getMsg("edit_text_act_target_toggle"));
    targetBtn.setBorder(new SmallButtonBorder(targetBtn, true));
    targetBtn.addActionListener(this);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
    gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
    actPanel.add(targetBtn, gridBagConstraints);

    editTargetBtn
        .setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/xtec/resources/icons/text_target_edit.gif"))); // NOI18N
    editTargetBtn.setToolTipText(options.getMsg("edit_text_act_edit_target"));
    editTargetBtn.setBorder(new SmallButtonBorder(editTargetBtn, true));
    editTargetBtn.setEnabled(false);
    editTargetBtn.addActionListener(this);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
    gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 8);
    actPanel.add(editTargetBtn, gridBagConstraints);

    insertBoxBtn.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/xtec/resources/icons/insert_box.gif"))); // NOI18N
    insertBoxBtn.setToolTipText(options.getMsg("edit_text_act_insertCell"));
    insertBoxBtn.setBorder(new SmallButtonBorder(prevScreenBtn, true));
    insertBoxBtn.addActionListener(this);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.insets = new java.awt.Insets(2, 8, 2, 8);
    actPanel.add(insertBoxBtn, gridBagConstraints);

    prevScreenBtn
        .setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/xtec/resources/icons/prev_screen.gif"))); // NOI18N
    prevScreenBtn.setToolTipText(options.getMsg("edit_text_act_prevScreen_title"));
    prevScreenBtn.setBorder(new SmallButtonBorder(prevScreenBtn, true));
    prevScreenBtn.addActionListener(this);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.insets = new java.awt.Insets(2, 8, 2, 8);
    actPanel.add(prevScreenBtn, gridBagConstraints);

    optionsBtn.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/xtec/resources/icons/check.gif"))); // NOI18N
    optionsBtn.setToolTipText(options.getMsg("edit_text_act_check_bt"));
    optionsBtn.setBorder(new SmallButtonBorder(optionsBtn, true));
    optionsBtn.addActionListener(this);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.insets = new java.awt.Insets(2, 8, 2, 8);
    actPanel.add(optionsBtn, gridBagConstraints);

    typeBtn.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/xtec/resources/icons/type.gif"))); // NOI18N
    typeBtn.setToolTipText(options.getMsg("edit_text_act_typeBtn"));
    typeBtn.setBorder(new SmallButtonBorder(typeBtn, true));
    typeBtn.addActionListener(this);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.insets = new java.awt.Insets(2, 8, 2, 8);
    actPanel.add(typeBtn, gridBagConstraints);

    widthLb.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/xtec/resources/icons/adjust_width.gif"))); // NOI18N
    widthLb.setLabelFor(widthEdit);
    widthLb.setText(":");
    widthLb.setIconTextGap(0);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
    gridBagConstraints.insets = new java.awt.Insets(2, 8, 2, 2);
    actPanel.add(widthLb, gridBagConstraints);

    widthEdit.setToolTipText(options.getMsg("edit_act_width_tooltip"));
    widthEdit.setMax(999);
    widthEdit.setMin(50);
    widthEdit.addPropertyChangeListener(SmallIntEditor.PROP_VALUE, this);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
    gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 8);
    actPanel.add(widthEdit, gridBagConstraints);

    heightLb.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/xtec/resources/icons/adjust_height.gif"))); // NOI18N
    heightLb.setLabelFor(heightEdit);
    heightLb.setText(":");
    heightLb.setIconTextGap(0);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
    gridBagConstraints.insets = new java.awt.Insets(2, 8, 2, 2);
    actPanel.add(heightLb, gridBagConstraints);

    heightEdit.setToolTipText(options.getMsg("edit_act_height_tooltip"));
    heightEdit.setMax(999);
    heightEdit.setMin(50);
    heightEdit.addPropertyChangeListener(SmallIntEditor.PROP_VALUE, this);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
    gridBagConstraints.weightx = 1.0;
    gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 8);
    actPanel.add(heightEdit, gridBagConstraints);

    ctrlPanel.addTab(options.getMsg("edit_text_act_content"),
        new javax.swing.ImageIcon(getClass().getResource("/edu/xtec/resources/icons/content.gif")), actPanel); // NOI18N

    stylePanel.setLayout(new java.awt.GridBagLayout());

    styleBtn.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/xtec/resources/icons/doc_styles.gif"))); // NOI18N
    styleBtn.setToolTipText(options.getMsg("edit_text_act_editStylesBtn"));
    styleBtn.setBorder(new SmallButtonBorder(styleBtn, true));
    styleBtn.addActionListener(this);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
    stylePanel.add(styleBtn, gridBagConstraints);

    clearStylesBtn
        .setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/xtec/resources/icons/doc_styles_clear.gif"))); // NOI18N
    clearStylesBtn.setToolTipText(options.getMsg("edit_text_act_clearStylesBtn"));
    clearStylesBtn.setBorder(new SmallButtonBorder(styleBtn, true));
    clearStylesBtn.addActionListener(this);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 8);
    stylePanel.add(clearStylesBtn, gridBagConstraints);

    fontFaceCombo.setEditable(true);
    fontFaceCombo.setPreferredSize(new java.awt.Dimension(120, fontFaceCombo.getPreferredSize().height));
    fontFaceCombo.addActionListener(this);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.insets = new java.awt.Insets(2, 8, 2, 2);
    stylePanel.add(fontFaceCombo, gridBagConstraints);

    fontSizeCombo.setEditable(true);
    fontSizeCombo.setPreferredSize(new java.awt.Dimension(50, fontSizeCombo.getPreferredSize().height));
    fontSizeCombo.addActionListener(this);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 8);
    stylePanel.add(fontSizeCombo, gridBagConstraints);

    boldBtn.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/xtec/resources/icons/font_bold.gif"))); // NOI18N
    boldBtn.setToolTipText(options.getMsg("edit_font_bold"));
    boldBtn.setBorder(new SmallButtonBorder(boldBtn, true));
    boldBtn.addActionListener(this);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.insets = new java.awt.Insets(2, 8, 2, 2);
    stylePanel.add(boldBtn, gridBagConstraints);

    italicBtn.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/xtec/resources/icons/font_italic.gif"))); // NOI18N
    italicBtn.setToolTipText(options.getMsg("edit_font_italic"));
    italicBtn.setBorder(new SmallButtonBorder(italicBtn, true));
    italicBtn.addActionListener(this);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
    stylePanel.add(italicBtn, gridBagConstraints);

    underlineBtn
        .setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/xtec/resources/icons/font_underline.gif"))); // NOI18N
    underlineBtn.setToolTipText(options.getMsg("edit_font_underline"));
    underlineBtn.setBorder(new SmallButtonBorder(underlineBtn, true));
    underlineBtn.addActionListener(this);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 8);
    stylePanel.add(underlineBtn, gridBagConstraints);

    alignGrp.add(alLeftBtn);
    alLeftBtn.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/xtec/resources/icons/al_left.gif"))); // NOI18N
    alLeftBtn.setToolTipText(options.getMsg("edit_text_align_left"));
    alLeftBtn.setBorder(new SmallButtonBorder(alLeftBtn, true));
    alLeftBtn.addActionListener(this);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.insets = new java.awt.Insets(2, 8, 2, 2);
    stylePanel.add(alLeftBtn, gridBagConstraints);

    alignGrp.add(alCenterBtn);
    alCenterBtn.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/xtec/resources/icons/al_center.gif"))); // NOI18N
    alCenterBtn.setToolTipText(options.getMsg("edit_text_align_center"));
    alCenterBtn.setBorder(new SmallButtonBorder(alCenterBtn, true));
    alCenterBtn.addActionListener(this);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
    stylePanel.add(alCenterBtn, gridBagConstraints);

    alignGrp.add(alRightBtn);
    alRightBtn.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/xtec/resources/icons/al_right.gif"))); // NOI18N
    alRightBtn.setToolTipText(options.getMsg("edit_text_align_right"));
    alRightBtn.setBorder(new SmallButtonBorder(alRightBtn, true));
    alRightBtn.addActionListener(this);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 8);
    stylePanel.add(alRightBtn, gridBagConstraints);

    textColorLb.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/xtec/resources/icons/fg.gif"))); // NOI18N
    textColorLb.setText(":");
    textColorLb.setIconTextGap(0);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
    gridBagConstraints.insets = new java.awt.Insets(2, 8, 2, 2);
    stylePanel.add(textColorLb, gridBagConstraints);

    textColorBtn.setToolTipText(options.getMsg("edit_act_textColor_tooltip"));
    textColorBtn.addPropertyChangeListener(ColorButton.PROP_COLOR, this);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
    gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 6);
    stylePanel.add(textColorBtn, gridBagConstraints);

    bgColorLb.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edu/xtec/resources/icons/bg.gif"))); // NOI18N
    bgColorLb.setText(":");
    bgColorLb.setIconTextGap(0);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
    gridBagConstraints.insets = new java.awt.Insets(2, 6, 2, 2);
    stylePanel.add(bgColorLb, gridBagConstraints);

    bgColorBtn.setToolTipText(options.getMsg("edit_act_bgColor_tooltip"));
    bgColorBtn.addPropertyChangeListener(ColorButton.PROP_COLOR, this);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
    gridBagConstraints.weightx = 1.0;
    gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
    stylePanel.add(bgColorBtn, gridBagConstraints);

    ctrlPanel.addTab(options.getMsg("edit_text_act_style"),
        new javax.swing.ImageIcon(getClass().getResource("/edu/xtec/resources/icons/styles.gif")), stylePanel); // NOI18N

    add(ctrlPanel, java.awt.BorderLayout.NORTH);
  } // </editor-fold>//GEN-END:initComponents

  protected TextActivityBase getTextActivity() {
    return (TextActivityBase) getActivity();
  }

  protected TextActivityBaseEditor getTextActivityEditor() {
    return (TextActivityBaseEditor) getActivityEditor();
  }

  @Override
  public void setEnabled(boolean enabled) {

    super.setEnabled(enabled);
    textPane.setEnabled(enabled);
    widthEdit.setEnabled(enabled);
    heightEdit.setEnabled(enabled);
    fontFaceCombo.setEnabled(enabled);
    fontSizeCombo.setEnabled(enabled);
    boldBtn.setEnabled(enabled);
    italicBtn.setEnabled(enabled);
    underlineBtn.setEnabled(enabled);
    textColorBtn.setEnabled(enabled);
    bgColorBtn.setEnabled(enabled);
    targetBtn.setEnabled(enabled);
    alCenterBtn.setEnabled(enabled);
    alRightBtn.setEnabled(enabled);
    alLeftBtn.setEnabled(enabled);
    resizer.setEnabled(enabled);
    if (!enabled) {
      editTargetBtn.setEnabled(false);
      typeBtn.setEnabled(false);
    }
  }

  private static final Dimension DEFAULT_SIZE = new Dimension(TextActivityBase.DEFAULT_WIDTH,
      TextActivityBase.DEFAULT_HEIGHT);

  public void fillData() {
    TextActivityBaseEditor tabe = getTextActivityEditor();
    TextActivityBase act = tabe == null ? null : tabe.getTextActivity();
    typeBtn.setEnabled(tabe != null && tabe.hasType());
    DefaultStyledDocument doc = act == null ? new DefaultStyledDocument() : act.tad;

    // Workaround for JRE 1.4+, part 1: Save a clean copy of the default style
    // attributes
    Style defaultStyle = doc.getStyle(StyleContext.DEFAULT_STYLE);
    AttributeSet as = defaultStyle.copyAttributes();
    //
    textPane.setStyledDocument(doc);
    //
    // Workaround for JRE 1.4+, part 2: Restore lost attributes
    defaultStyle.addAttributes(as);

    doc.addDocumentListener(this);
    Dimension d = act == null ? DEFAULT_SIZE : act.getWindowSize();
    if (act == null || act.tad.getLength() == 0)
      textPane.setBounds(0, 0, d.width, d.height);
    widthEdit.setValue(d.width);
    heightEdit.setValue(d.height);
    textPane.setBackground(
        act == null ? Color.white : StyleConstants.getBackground(textPane.getStyle(StyleContext.DEFAULT_STYLE)));
    textScroll.setBounds(0, 0, d.width, d.height);
    resizer.setRect(textScroll.getBounds());
    resizer.setEnabled(act != null);
    if (act != null) {
      JPanelActiveBox[] boxes = act.tad.getPanelBoxes();
      for (int i = 0; i < boxes.length; i++) {
        boxes[i].catchMouseEvents = false;
        Resizer rs = new Resizer(boxes[i], null, true, this);
      }
      javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
          textPane.revalidate();
        }
      });
    }
  }

  public void resizeObjectTo(Rectangle r, JComponent jc) {
    if (jc == previewPanel) {
      TextActivityBase act = getTextActivity();
      if (act != null) {
        textScroll.setBounds(r.x, r.y, r.width, r.height);
        act.setWindowSize(textScroll.getSize());
        widthEdit.setValue(r.width);
        heightEdit.setValue(r.height);
        textScroll.revalidate();
        repaint();
        setModified(true);
      }
    } else if (jc instanceof JPanelActiveBox) {
      JPanelActiveBox jpab = (JPanelActiveBox) jc;
      jpab.setBounds(r.x, r.y, r.width, r.height);
      Dimension d = new Dimension(r.width, r.height);
      jpab.getActiveBoxContent().setDimension(d);
      jpab.setPreferredSize(d);
      jpab.setMaximumSize(d);
      setModified(true);
    }
  }

  public void editObject(Rectangle r, JComponent jc, Point pt) {
    if (jc instanceof JPanelActiveBox) {
      JPanelActiveBox jpab = (JPanelActiveBox) jc;
      if (jpab.ab != null) {
        ActiveBoxContent abc = ActiveBoxContentEditor.getActiveBoxContent(jpab.ab.getContent(), jpab, options,
            getActivityEditor().getMediaBagEditor(), jpab.ab);
        if (abc != null) {
          jpab.setActiveBoxContent(abc);
          Dimension d = abc.getDimension();
          if (d != null)
            resizeObjectTo(new Rectangle(jpab.getX(), jpab.getY(), d.width, d.height), jpab);
          setModified(true);
        }
      }
    }
  }

  public void saveData() {
    TextActivityBase act = getTextActivity();
    if (act != null) {
      // ???
    }
  }

  protected javax.swing.Icon getIcon() {
    return ResourceManager.getImageIcon("icons/text_edit.gif");
  }

  protected String getTitle() {
    return options.getMsg("edit_act_panels_text");
  }

  protected String getTooltip() {
    return options.getMsg("edit_act_panels_text_tooltip");
  }

  @Override
  public boolean documentChangePerformed(DocumentEvent ev) {
    if (ev != null && ev.getType() == DocumentEvent.EventType.REMOVE && getTextActivity() != null)
      getTextActivity().tad.tmb.removeUnattachedElements();
    return ev != null;
  }

  @Override
  public boolean eventPerformed(EventObject ev) {
    boolean result = false;
    TextActivityBaseEditor tabe = getTextActivityEditor();
    if (tabe != null && !skipUpdate) {
      TextActivityBase ta = tabe.getTextActivity();
      MutableAttributeSet attr = new SimpleAttributeSet();
      boolean paragraphAttr = false;
      boolean charAttr = false;
      boolean replace = false;
      Object src = (ev == null ? null : ev.getSource());
      int xStart = textPane.getSelectionStart();
      int xFinish = textPane.getSelectionEnd();
      int len = 0;
      if (xStart != xFinish) {
        if (xFinish < xStart) {
          int s = xStart;
          xStart = xFinish;
          xFinish = s;
        }
        len = xFinish - xStart;
      }

      if (src != null && src.equals(fontFaceCombo)) {
        fontName = fontFaceCombo.getSelectedItem().toString();
        StyleConstants.setFontFamily(attr, fontName);
        charAttr = true;
      } else if (src != null && src.equals(fontSizeCombo)) {
        int fs;
        try {
          fs = Integer.parseInt(fontSizeCombo.getSelectedItem().toString());
        } catch (NumberFormatException ex) {
          return false;
        }
        if (fs >= 1) {
          fontSize = fs;
          StyleConstants.setFontSize(attr, fontSize);
          charAttr = true;
        }
      } else if (src == boldBtn) {
        StyleConstants.setBold(attr, boldBtn.isSelected());
        charAttr = true;
      } else if (src == italicBtn) {
        StyleConstants.setItalic(attr, italicBtn.isSelected());
        charAttr = true;
      } else if (src == underlineBtn) {
        StyleConstants.setUnderline(attr, underlineBtn.isSelected());
        charAttr = true;
      } else if (src == textColorBtn) {
        StyleConstants.setForeground(attr, textColorBtn.getColor());
        charAttr = true;
      } else if (src == targetBtn) {
        boolean b = targetBtn.isSelected();
        TargetMarker tm = b ? createNewTarget() : ta.tad.tmb.getElementByOffset(xFinish, true);
        if (tm == null)
          return false;
        if (!b && !deleteTarget(tm))
          return true;
        textPane.setCaretPosition(xStart);
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            showAttributes(-1);
          }
        });
      } else if (tabe.canEditTarget() && src == editTargetBtn) {
        tabe.editTarget(xFinish, options, this);
      } else if (src == insertBoxBtn) {
        JPanelActiveBox jpab = tabe.createNewBox(xStart, options, this);
        if (jpab != null) {
          jpab.catchMouseEvents = false;
          Resizer rs = new Resizer(jpab, null, true, this);
        }
      } else if (src == optionsBtn) {
        tabe.editCheckOptions(options, this);
      } else if (src == typeBtn && tabe.hasType()) {
        tabe.editType(options, this);
      } else if (src == bgColorBtn) {
        if (len == 0) {

        } else {
          StyleConstants.setBackground(attr, bgColorBtn.getColor());
          charAttr = true;
        }
      } else if (src == alLeftBtn || src == alCenterBtn || src == alRightBtn) {
        int align = src == alCenterBtn ? StyleConstants.ALIGN_CENTER
            : src == alRightBtn ? StyleConstants.ALIGN_RIGHT : StyleConstants.ALIGN_LEFT;
        StyleConstants.setAlignment(attr, align);
        paragraphAttr = true;
      } else if (src == styleBtn) {
        StyleContext sc = TextStyleEditorPanel.editStyleContext(options, ta.tad.styleContext, this);
        if (sc != null) {
          try {
            ta.setStyleContext(sc);
            setInitializing(true);
            fillData();
            setInitializing(false);
          } catch (Exception ex) {
            System.err.println("error applying styles:\n" + ex);
          }
        }
      } else if (src == clearStylesBtn) {
        int d = options.getMessages().showQuestionDlg(this, "edit_text_act_clearStylesPrompt", null, "yn");
        if (d == Messages.YES)
          try {
            ta.setTextActivityDocument(ta.tad.getJDomElementWithoutStyles());
            setInitializing(true);
            fillData();
            setInitializing(false);
          } catch (Exception ex) {
            System.err.println("Error cleaning styles:\n" + ex);
          }
      } else if (src == prevScreenBtn) {
        if (TextPrevScreenEditorPanel.editPrevScreen(options, (TextActivityBaseEditor) getActivityEditor(), this))
          setModified(true);
      } else if (src == widthEdit || src == heightEdit) {
        ta.setWindowSize(new Dimension(widthEdit.getValue(), heightEdit.getValue()));
        previewPanel.revalidate();
      }

      changeCombos = false;

      if (paragraphAttr)
        ta.tad.setParagraphAttributes(xStart, len, attr, replace);
      if (charAttr) {
        if (len > 0)
          ta.tad.setCharacterAttributes(xStart, len, attr, replace);
        else {
          MutableAttributeSet inputAttributes = textPane.getInputAttributes();
          inputAttributes.addAttributes(attr);
        }
      }

      textPane.grabFocus();
      changeCombos = true;
      result = true;
    }
    return result;
  }

  protected TargetMarker createNewTarget() {
    TargetMarker result = null;
    TextActivityBaseEditor tabe = getTextActivityEditor();
    if (tabe != null) {
      int from = textPane.getSelectionStart();
      int to = textPane.getSelectionEnd();
      result = tabe.createNewTarget(from, to, options, this);
    }
    return result;
  }

  protected boolean deleteTarget(TargetMarker tm) {
    boolean result = false;
    TextActivityBaseEditor tabe = getTextActivityEditor();
    if (tabe != null)
      result = tabe.deleteTarget(tm, options, this);
    return result;
  }

  protected void showAttributes(int p) {
    TextActivityBaseEditor tabe = getTextActivityEditor();
    if (tabe != null) {
      TextActivityBase ta = tabe.getTextActivity();
      skipUpdate = true;
      if (p < 0)
        p = Math.max(0, textPane.getCaretPosition());
      AttributeSet a = ta.tad.getCharacterElement(p).getAttributes();
      String name = StyleConstants.getFontFamily(a);
      if (!name.equals(fontName) && changeCombos) {
        fontName = name;
        fontFaceCombo.setSelectedItem(name);
      }
      int size = StyleConstants.getFontSize(a);
      if (fontSize != size && changeCombos) {
        fontSize = size;
        fontSizeCombo.setSelectedItem(Integer.toString(fontSize));
      }
      boldBtn.setSelected(StyleConstants.isBold(a));
      italicBtn.setSelected(StyleConstants.isItalic(a));
      underlineBtn.setSelected(StyleConstants.isUnderline(a));

      Color c = StyleConstants.getForeground(a);
      if (!c.equals(textColorBtn.getColor()))
        textColorBtn.setColor(c);

      c = StyleConstants.getBackground(a);
      if (!c.equals(bgColorBtn.getColor()))
        bgColorBtn.setColor(c);

      targetBtn.setSelected(a.isDefined(TextActivityDocument.TARGET));
      editTargetBtn.setEnabled(tabe.canEditTarget() && a.isDefined(TextActivityDocument.TARGET));

      int alignment = StyleConstants.getAlignment(a);
      alCenterBtn.setSelected(alignment == StyleConstants.ALIGN_CENTER);
      alRightBtn.setSelected(alignment == StyleConstants.ALIGN_RIGHT);
      alLeftBtn.setSelected(alignment != StyleConstants.ALIGN_RIGHT && alignment != StyleConstants.ALIGN_CENTER);

      skipUpdate = false;
    }
  }

  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JToggleButton alCenterBtn;
  private javax.swing.JToggleButton alLeftBtn;
  private javax.swing.JToggleButton alRightBtn;
  private javax.swing.ButtonGroup alignGrp;
  private edu.xtec.jclic.beans.ColorButton bgColorBtn;
  private javax.swing.JToggleButton boldBtn;
  private javax.swing.JButton clearStylesBtn;
  private javax.swing.JButton editTargetBtn;
  private javax.swing.JComboBox<Object> fontFaceCombo;
  private javax.swing.JComboBox<Object> fontSizeCombo;
  private edu.xtec.jclic.beans.SmallIntEditor heightEdit;
  private javax.swing.JButton insertBoxBtn;
  private javax.swing.JToggleButton italicBtn;
  private javax.swing.JScrollPane mainScroll;
  private javax.swing.JButton optionsBtn;
  private javax.swing.JButton prevScreenBtn;
  private javax.swing.JPanel previewPanel;
  private javax.swing.JButton styleBtn;
  private javax.swing.JToggleButton targetBtn;
  private edu.xtec.jclic.beans.ColorButton textColorBtn;
  private javax.swing.JTextPane textPane;
  private javax.swing.JScrollPane textScroll;
  private javax.swing.JButton typeBtn;
  private javax.swing.JToggleButton underlineBtn;
  private edu.xtec.jclic.beans.SmallIntEditor widthEdit;
  // End of variables declaration//GEN-END:variables

  protected class PreviewPanel extends ResizerPanel {
    @Override
    public void doLayout() {
      if (textScroll != null) {
        TextActivityBase act = getTextActivity();
        Dimension d = (act != null ? act.getWindowSize()
            : new Dimension(Activity.DEFAULT_WIDTH, Activity.DEFAULT_HEIGHT));
        textScroll.setBounds(0, 0, d.width, d.height);
      }
    }
  }
}
