Package org.freeplane.view.swing.map.mindmapmode

Source Code of org.freeplane.view.swing.map.mindmapmode.EditNodeTextField$MapViewChangeListener

/*
*  Freeplane - mind map editor
*  Copyright (C) 2008 Joerg Mueller, Daniel Polansky, Christian Foltin, Dimitry Polivaev
*
*  This file is modified by Dimitry Polivaev in 2008.
*
*  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.
*
*  You should have received a copy of the GNU General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.freeplane.view.swing.map.mindmapmode;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.event.ActionEvent;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.InputMethodEvent;
import java.awt.event.InputMethodListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import java.io.Writer;
import java.net.URI;
import java.text.AttributedCharacterIterator;

import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.Icon;
import javax.swing.InputMap;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JPopupMenu;
import javax.swing.KeyStroke;
import javax.swing.RootPaneContainer;
import javax.swing.SwingUtilities;
import javax.swing.border.MatteBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultEditorKit;
import javax.swing.text.DefaultEditorKit.PasteAction;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import javax.swing.text.NavigationFilter;
import javax.swing.text.Position.Bias;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledEditorKit;
import javax.swing.text.StyledEditorKit.BoldAction;
import javax.swing.text.StyledEditorKit.ForegroundAction;
import javax.swing.text.StyledEditorKit.ItalicAction;
import javax.swing.text.StyledEditorKit.StyledTextAction;
import javax.swing.text.StyledEditorKit.UnderlineAction;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.HTMLWriter;
import javax.swing.text.html.StyleSheet;

import org.freeplane.core.resources.ResourceController;
import org.freeplane.core.ui.components.UITools;
import org.freeplane.core.ui.components.html.ScaledEditorKit;
import org.freeplane.core.util.ColorUtils;
import org.freeplane.core.util.HtmlUtils;
import org.freeplane.core.util.LogUtils;
import org.freeplane.core.util.TextUtils;
import org.freeplane.features.map.NodeModel;
import org.freeplane.features.mode.Controller;
import org.freeplane.features.mode.ModeController;
import org.freeplane.features.nodestyle.NodeStyleController;
import org.freeplane.features.spellchecker.mindmapmode.SpellCheckerController;
import org.freeplane.features.text.TextController;
import org.freeplane.features.text.mindmapmode.EditNodeBase;
import org.freeplane.features.text.mindmapmode.EventBuffer;
import org.freeplane.features.text.mindmapmode.MTextController;
import org.freeplane.features.ui.IMapViewChangeListener;
import org.freeplane.features.ui.IMapViewManager;
import org.freeplane.features.url.UrlManager;
import org.freeplane.view.swing.map.MainView;
import org.freeplane.view.swing.map.MapView;
import org.freeplane.view.swing.map.NodeView;
import org.freeplane.view.swing.map.ZoomableLabel;
import org.freeplane.view.swing.map.ZoomableLabelUI;

import com.lightdev.app.shtm.SHTMLWriter;


/**
* @author foltin
*/
public class EditNodeTextField extends EditNodeBase {
    private class MyNavigationFilter extends NavigationFilter {
      private final JEditorPane textfield;
        public MyNavigationFilter(JEditorPane textfield) {
          this.textfield = textfield;
        }

    /* (non-Javadoc)
         * @see javax.swing.text.NavigationFilter#moveDot(javax.swing.text.NavigationFilter.FilterBypass, int, javax.swing.text.Position.Bias)
         */
        public void moveDot(final FilterBypass fb, int dot, final Bias bias) {
            dot = getValidPosition(dot);
            super.moveDot(fb, dot, bias);
        }

        /* (non-Javadoc)
         * @see javax.swing.text.NavigationFilter#setDot(javax.swing.text.NavigationFilter.FilterBypass, int, javax.swing.text.Position.Bias)
         */
        public void setDot(final FilterBypass fb, int dot, final Bias bias) {
            dot = getValidPosition(dot);
            super.setDot(fb, dot, bias);
        }

        private int getValidPosition(int position) {
          final HTMLDocument doc = (HTMLDocument) textfield.getDocument();
          if (doc.getDefaultRootElement().getElementCount() > 1) {
            final int startPos = doc.getDefaultRootElement().getElement(1).getStartOffset();
            final int validPosition = Math.max(position, startPos);
            return validPosition;
          }
          return position;
        }
    }
   
  private static class InputMethodInUseListener implements InputMethodListener {
    private boolean imeInUse = false;

    public void inputMethodTextChanged(InputMethodEvent event) {
      updateImeInUseState(event);
    }

    public void caretPositionChanged(InputMethodEvent event) {
      updateImeInUseState(event);
    }

    public boolean isIMEInUse(){
      return imeInUse;
    }
   
    private void updateImeInUseState(InputMethodEvent event) {
          AttributedCharacterIterator aci = event.getText();
      if(aci != null) {
        int inputLen = aci.getEndIndex() - aci.getBeginIndex();
        int committedLen = event.getCommittedCharacterCount();
        imeInUse = inputLen > 0 && inputLen != committedLen;
      }
            else
              imeInUse = false;
        }

  }
 
  private int extraWidth;
  final private boolean layoutMapOnTextChange;

  private final class MyDocumentListener implements DocumentListener {
    private boolean updateRunning = false;
    public void changedUpdate(final DocumentEvent e) {
      onUpdate();
    }

    private void onUpdate() {
      if(updateRunning){
        return;
      }
      EventQueue.invokeLater(new Runnable() {
        public void run() {
          updateRunning = true;
          layout();
          updateRunning = false;
        }
      });
    }

    public void insertUpdate(final DocumentEvent e) {
      onUpdate();
    }

    public void removeUpdate(final DocumentEvent e) {
      onUpdate();
    }
  }

  private void layout() {
    if (textfield == null) {
      return;
    }
    final int lastWidth = textfield.getWidth();
    final int lastHeight = textfield.getHeight();
    final boolean lineWrap = lastWidth == maxWidth;
    Dimension preferredSize = textfield.getPreferredSize();
    if (!lineWrap) {
      preferredSize.width ++;
      if (preferredSize.width > maxWidth) {
        setLineWrap();
        preferredSize = textfield.getPreferredSize();
      }
      else {
        if (preferredSize.width < lastWidth) {
          preferredSize.width = lastWidth;
        }
        else {
          preferredSize.width = Math.min(preferredSize.width + extraWidth, maxWidth);
          if (preferredSize.width == maxWidth) {
            setLineWrap();
          }
        }
      }
    }
    else {
      preferredSize.width = Math.max(maxWidth, preferredSize.width);
    }
    if(preferredSize.width != lastWidth){
      preferredSize.height = lastHeight;
      SwingUtilities.invokeLater(new Runnable() {
        public void run() {
          layout();
        }
      });
    }
    else{
      preferredSize.height = Math.max(preferredSize.height, lastHeight);
    }
    if (preferredSize.width == lastWidth && preferredSize.height == lastHeight) {
      textfield.repaint();
      return;
    }
    textfield.setSize(preferredSize);
    if(layoutMapOnTextChange)
      parent.setPreferredSize(new Dimension(preferredSize.width + horizontalSpace , preferredSize.height + verticalSpace));
    textfield.revalidate();
    final NodeView nodeView = (NodeView) SwingUtilities.getAncestorOfClass(NodeView.class, parent);
    final MapView mapView = (MapView) SwingUtilities.getAncestorOfClass(MapView.class, nodeView);
    if(mapView == null)
      return;
    if(layoutMapOnTextChange)
      mapView.scrollNodeToVisible(nodeView);
    else
      mapView.scrollRectToVisible(textfield.getBounds());
  }

  private void setLineWrap() {
    if(null != textfield.getClientProperty("EditNodeTextField.linewrap") || inputMethodInUseListener.isIMEInUse()){
      return;
    }
   
      final HTMLDocument document = (HTMLDocument) textfield.getDocument();
      document.getStyleSheet().addRule("body { width: " + (maxWidth - 1) + "}");
      // bad hack: call "setEditable" only to update view
      textfield.setEditable(false);
      textfield.setEditable(true);
      textfield.putClientProperty("EditNodeTextField.linewrap", true);
    }

  private static final int SPLIT_KEY_CODE;
  static {
    String rawLabel = TextUtils.getRawText("split");
    final int mnemoSignIndex = rawLabel.indexOf('&');
    if (mnemoSignIndex >= 0 && mnemoSignIndex + 1 < rawLabel.length()) {
      final char charAfterMnemoSign = rawLabel.charAt(mnemoSignIndex + 1);
      if (charAfterMnemoSign != ' ') {
        SPLIT_KEY_CODE = charAfterMnemoSign;
      }
      else SPLIT_KEY_CODE = -1;
    }
    else SPLIT_KEY_CODE = -1;
  }
  private class TextFieldListener implements KeyListener, FocusListener, MouseListener {
    final int CANCEL = 2;
    final int EDIT = 1;
    Integer eventSource = EDIT;
    private boolean popupShown;

    public TextFieldListener() {
    }

    private void conditionallyShowPopup(final MouseEvent e) {
      if (e.isPopupTrigger()) {
        final Component component = e.getComponent();
        final JPopupMenu popupMenu = createPopupMenu(component);
        popupShown = true;
        popupMenu.show(component, e.getX(), e.getY());
        e.consume();
      }
    }
   
   

    public void focusGained(final FocusEvent e) {
      popupShown = false;
    }

    public void focusLost(final FocusEvent e) {
      if (textfield == null || !textfield.isVisible() || eventSource == CANCEL || popupShown) {
        return;
      }
      if (e == null) {
        submitText();
        hideMe();
        eventSource = CANCEL;
        return;
      }
      if (e.isTemporary() && e.getOppositeComponent() == null) {
        return;
      }
      submitText();
      hideMe();
    }

    private void submitText() {
          submitText(getNewText());
        }

    private void submitText(final String output) {
      getEditControl().ok(output);
        }

    public void keyPressed(final KeyEvent e) {
      if (e.isControlDown() || e.isMetaDown() || eventSource == CANCEL||textfield==null) {
        return;
      }
      final int keyCode = e.getKeyCode();
      switch (keyCode) {
        case KeyEvent.VK_ESCAPE:
          eventSource = CANCEL;
          hideMe();
          getEditControl().cancel();
          nodeView.requestFocusInWindow();
          e.consume();
          break;
        case KeyEvent.VK_ENTER: {
          final boolean enterConfirms = ResourceController.getResourceController().getBooleanProperty("el__enter_confirms_by_default");
          if (enterConfirms == e.isAltDown() || e.isShiftDown()) {
            e.consume();
            final Component component = e.getComponent();
            final KeyEvent keyEvent = new KeyEvent(component, e.getID(), e.getWhen(), 0, keyCode, e
                .getKeyChar(), e.getKeyLocation());
            SwingUtilities.processKeyBindings(keyEvent);
            break;
          }
          final String output = getNewText();
          e.consume();
          eventSource = CANCEL;
          hideMe();
          submitText(output);
          nodeView.requestFocusInWindow();
        }
        break;
        case KeyEvent.VK_TAB:
          textfield.replaceSelection("    ");
        case KeyEvent.VK_SPACE:
          e.consume();
          break;
        default:
          if(keyCode == SPLIT_KEY_CODE && keyCode != -1 && e.isAltDown() && getEditControl().canSplit()){
            eventSource = CANCEL;
            final String output = getNewText();
            final int caretPosition = textfield.getCaretPosition();
            hideMe();
            getEditControl().split(output, caretPosition);
            nodeView.requestFocusInWindow();
            e.consume();
          }
          break;
      }
    }

    public void keyReleased(final KeyEvent e) {
    }

    public void keyTyped(final KeyEvent e) {
    }

    public void mouseClicked(final MouseEvent ev) {
      if (textfield != null && (ev.getModifiers() & MouseEvent.CTRL_MASK) != 0) {
        final String linkURL = HtmlUtils.getURLOfExistingLink((HTMLDocument) textfield.getDocument(), textfield.viewToModel(ev.getPoint()));
        if (linkURL != null) {
          try {
            UrlManager.getController().loadURL(new URI(linkURL));
          } catch (Exception e) {
            LogUtils.warn(e);
          }
        }
      }
    }

    public void mouseEntered(final MouseEvent e) {
    }

    public void mouseExited(final MouseEvent e) {
    }

    public void mousePressed(final MouseEvent e) {
      conditionallyShowPopup(e);
    }

    public void mouseReleased(final MouseEvent e) {
      conditionallyShowPopup(e);
    }
  }
 
  private class MapViewChangeListener implements IMapViewChangeListener{
    public void afterViewChange(Component oldView, Component newView) {
        }

    public void afterViewClose(Component oldView) {
        }

    public void afterViewCreated(Component mapView) {
        }

    public void beforeViewChange(Component oldView, Component newView) {
      final String output = getNewText();
      hideMe();
      getEditControl().ok(output);
        }
  }
 
  private JEditorPane textfield;
  final private InputMethodInUseListener inputMethodInUseListener;
  private final DocumentListener documentListener;
  private int maxWidth;

  @SuppressWarnings("serial")
    public EditNodeTextField(final NodeModel node, final ZoomableLabel parent, final String text, final IEditControl editControl) {
    super(node, text, editControl);
    this.parent = parent;
    this.layoutMapOnTextChange = ResourceController.getResourceController().getBooleanProperty("layout_map_on_text_change");
    documentListener = new MyDocumentListener();

    pasteAction = new DefaultEditorKit.PasteAction(){

      @Override
      public void actionPerformed(ActionEvent e) {
        JTextComponent target = getTextComponent(e);
        if (target == null) {
          return;
        }
        final Transferable contents = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(this);
        if(contents.isDataFlavorSupported(DataFlavor.stringFlavor)){
          try {
            String text = (String) contents.getTransferData(DataFlavor.stringFlavor);
            target.replaceSelection(text);
          }
          catch (Exception ex) {
          }
        }
      }
    };
   
    boldAction = new StyledEditorKit.BoldAction();
    boldAction.putValue(Action.NAME, TextUtils.getText("BoldAction.text"));
    boldAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control B"));
 
    italicAction = new StyledEditorKit.ItalicAction();
    italicAction.putValue(Action.NAME, TextUtils.getText("ItalicAction.text"));
    italicAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control I"));
   
    underlineAction = new StyledEditorKit.UnderlineAction();
    underlineAction.putValue(Action.NAME, TextUtils.getText("UnderlineAction.text"));
    underlineAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control U"));
   
    redAction = new ForegroundAction(TextUtils.getText("red"), Color.RED);
    redAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control R"));
   
    greenAction = new ForegroundAction(TextUtils.getText("green"), Color.GREEN);
    greenAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control G"));
   
    blueAction = new ForegroundAction(TextUtils.getText("blue"), Color.BLUE);
    blueAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control E"));
   
    blackAction = new ForegroundAction(TextUtils.getText("black"), Color.BLACK);
    blackAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control K"));
   
    defaultColorAction = new ExtendedEditorKit.RemoveStyleAttributeAction(StyleConstants.Foreground, TextUtils.getText("DefaultColorAction.text"));
    defaultColorAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control D"));
   
    removeFormattingAction = new ExtendedEditorKit.RemoveStyleAttributeAction(null, TextUtils.getText("simplyhtml.clearFormatLabel"));
    removeFormattingAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control T"));
   
    inputMethodInUseListener = new InputMethodInUseListener();
    if(editControl != null ){
      final ModeController modeController = Controller.getCurrentModeController();
      final MTextController textController = (MTextController) TextController.getController(modeController);
      textfield = textController.createEditorPane(MTextController.NODE_TEXT);
      textfield.setNavigationFilter(new MyNavigationFilter(textfield));
      textfield.addInputMethodListener(inputMethodInUseListener);
    }
  }

  public String getNewText() {
    final SHTMLWriter shtmlWriter = new SHTMLWriter((HTMLDocument) textfield.getDocument());
    try {
          shtmlWriter.write();
        }
        catch (Exception e) {
          LogUtils.severe(e);
        }
    return shtmlWriter.toString();
    }

  private void hideMe() {
    if (textfield == null) {
      return;
    }
    textfield.getDocument().removeDocumentListener(documentListener);
    final IMapViewManager mapViewManager = Controller.getCurrentController().getMapViewManager();
    mapViewManager.removeMapViewChangeListener(mapViewChangeListener);
    mapViewChangeListener = null;
    parent.setPreferredSize(null);
    if(SwingUtilities.getAncestorOfClass(MapView.class, nodeView) != null)
      nodeView.update();
    if(nodeView.isRoot() && parent instanceof MainView)
        parent.setHorizontalAlignment(JLabel.CENTER);
    final Dimension textFieldSize = textfield.getSize();
    final Point textFieldCoordinate = new Point();
    final MapView mapView = nodeView.getMap();
    UITools.convertPointToAncestor(textfield, textFieldCoordinate, mapView);
    textfield.getParent().remove(textfield);
    parent.revalidate();
    parent.repaint();
    mapView.repaint(textFieldCoordinate.x, textFieldCoordinate.y, textFieldSize.width, textFieldSize.height);
    textfield = null;
  }

  private final ZoomableLabel parent;
  private NodeView nodeView;
  private Font font;
  private float zoom;
  private final PasteAction pasteAction;
  private final BoldAction boldAction;
  private final ItalicAction italicAction;
  private final UnderlineAction underlineAction;
  private final ForegroundAction redAction;
  private final ForegroundAction greenAction;
  private final ForegroundAction blueAction;
  private final ForegroundAction blackAction;
  private StyledTextAction defaultColorAction;
  private StyledTextAction removeFormattingAction;
  private int horizontalSpace;
  private int verticalSpace;
  private MapViewChangeListener mapViewChangeListener;

  @Override
    protected JPopupMenu createPopupMenu(Component component) {
    JPopupMenu menu = super.createPopupMenu(component);
      JMenu formatMenu = new JMenu(TextUtils.getText("simplyhtml.formatLabel"));
      menu.add(formatMenu);
    if (textfield.getSelectionStart() == textfield.getSelectionEnd()){
      formatMenu.setEnabled(false);
      return menu;
    }
      formatMenu.add(boldAction);
      formatMenu.add(italicAction);
      formatMenu.add(underlineAction);
      formatMenu.add(redAction);
      formatMenu.add(greenAction);
      formatMenu.add(blueAction);
      formatMenu.add(blackAction);
      formatMenu.add(defaultColorAction);
      formatMenu.add(removeFormattingAction);
    return menu;
    }

  /* (non-Javadoc)
   * @see org.freeplane.view.swing.map.INodeTextField#show()
   */
  @SuppressWarnings("serial")
    @Override
  public void show(final RootPaneContainer frame) {
    final ModeController modeController = Controller.getCurrentModeController();
    final IMapViewManager viewController = modeController.getController().getMapViewManager();
    final MTextController textController = (MTextController) TextController.getController(modeController);
    nodeView = (NodeView) SwingUtilities.getAncestorOfClass(NodeView.class, parent);
    font = parent.getFont();
    zoom = viewController.getZoom();
    if (zoom != 1F) {
      final float fontSize = (int) (Math.rint(font.getSize() * zoom));
      font = font.deriveFont(fontSize);
    }
    final HTMLEditorKit kit = new ScaledEditorKit(){
      @Override
      public void write(Writer out, Document doc, int pos, int len) throws IOException, BadLocationException {
        if (doc instanceof HTMLDocument) {
          HTMLWriter w = new SHTMLWriter(out, (HTMLDocument) doc, pos, len);
          w.write();
        }
        else {
          super.write(out, doc, pos, len);
        }
      }
    };
    textfield.setEditorKit(kit);

    final InputMap inputMap = textfield.getInputMap();
    final ActionMap actionMap = textfield.getActionMap();
    actionMap.put(DefaultEditorKit.pasteAction, pasteAction);
   
    inputMap.put((KeyStroke) boldAction.getValue(Action.ACCELERATOR_KEY), "boldAction");
    actionMap.put("boldAction",boldAction);
   
    inputMap.put((KeyStroke) italicAction.getValue(Action.ACCELERATOR_KEY), "italicAction");
    actionMap.put("italicAction", italicAction);
   
    inputMap.put((KeyStroke) underlineAction.getValue(Action.ACCELERATOR_KEY), "underlineAction");
    actionMap.put("underlineAction", underlineAction);
   
    inputMap.put((KeyStroke) redAction.getValue(Action.ACCELERATOR_KEY), "redAction");
    actionMap.put("redAction", redAction);
   
    inputMap.put((KeyStroke) greenAction.getValue(Action.ACCELERATOR_KEY), "greenAction");
    actionMap.put("greenAction", greenAction);
   
    inputMap.put((KeyStroke) blueAction.getValue(Action.ACCELERATOR_KEY), "blueAction");
    actionMap.put("blueAction", blueAction);
   
    inputMap.put((KeyStroke) blackAction.getValue(Action.ACCELERATOR_KEY), "blackAction");
    actionMap.put("blackAction", blackAction);
   
    inputMap.put((KeyStroke) defaultColorAction.getValue(Action.ACCELERATOR_KEY), "defaultColorAction");
    actionMap.put("defaultColorAction", defaultColorAction);
   
    inputMap.put((KeyStroke) removeFormattingAction.getValue(Action.ACCELERATOR_KEY), "removeFormattingAction");
    actionMap.put("removeFormattingAction", removeFormattingAction);
   
    final Color nodeTextColor = parent.getForeground();
    textfield.setCaretColor(nodeTextColor);
    final StringBuilder ruleBuilder = new StringBuilder(100);
    ruleBuilder.append("body {");
    ruleBuilder.append("font-family: ").append(font.getFamily()).append(";");
    final int fontSize = Math.round(font.getSize() / UITools.FONT_SCALE_FACTOR);
    ruleBuilder.append("font-size: ").append(fontSize).append("pt;");
    if (font.isItalic()) {
      ruleBuilder.append("font-style: italic; ");
    }
    if (font.isBold()) {
      ruleBuilder.append("font-weight: bold; ");
    }
    ruleBuilder.append("color: ").append(ColorUtils.colorToString(nodeTextColor)).append(";");
      final Color bgColor = getBackground();
    ruleBuilder.append("background-color: ").append(ColorUtils.colorToString(bgColor)).append(";");
    ruleBuilder.append("}\n");
    final HTMLDocument document = (HTMLDocument) textfield.getDocument();
    final StyleSheet styleSheet = document.getStyleSheet();
    styleSheet.addRule(ruleBuilder.toString());
    textfield.setText(text);
    final MapView mapView = (MapView) viewController.getMapViewComponent();
    if(! mapView.isValid())
      mapView.validate();
    final NodeStyleController nsc = NodeStyleController.getController(modeController);
    maxWidth = nsc.getMaxWidth(node);
    final Icon icon = parent.getIcon();
    if(icon != null){
      maxWidth -= icon.getIconWidth();
      maxWidth -= parent.getIconTextGap();
    }
    maxWidth = mapView.getZoomed(maxWidth);
    extraWidth = ResourceController.getResourceController().getIntProperty("editor_extra_width", 80);
    extraWidth = mapView.getZoomed(extraWidth);
    final TextFieldListener textFieldListener = new TextFieldListener();
    this.textFieldListener = textFieldListener;
    textfield.addFocusListener(textFieldListener);
    textfield.addKeyListener(textFieldListener);
    textfield.addMouseListener(textFieldListener);
    mapViewChangeListener = new MapViewChangeListener();
    Controller.getCurrentController().getMapViewManager().addMapViewChangeListener(mapViewChangeListener);
    SpellCheckerController.getController().enableAutoSpell(textfield, true);
    mapView.scrollNodeToVisible(nodeView);
    assert( parent.isValid());
    final int nodeWidth = parent.getWidth();
    final int nodeHeight = parent.getHeight();
    final Dimension textFieldSize;
    textfield.setBorder(new MatteBorder(2, 2, 2, 2, nodeView.getSelectedColor()));
    textFieldSize = textfield.getPreferredSize();
    textFieldSize.width += 1;
        if(textFieldSize.width < extraWidth)
            textFieldSize.width = extraWidth;
        if(textFieldSize.width < 10)
            textFieldSize.width = 10;
    if (textFieldSize.width > maxWidth) {
      textFieldSize.width = maxWidth;
      setLineWrap();
      textFieldSize.height = textfield.getPreferredSize().height;
    }
    final Rectangle textR = ((ZoomableLabelUI)parent.getUI()).getTextR(parent);
    textFieldSize.width = Math.max(textFieldSize.width, textR.width);
    textFieldSize.height = Math.max(textFieldSize.height, textR.height);
    textfield.setSize(textFieldSize.width, textFieldSize.height);
    horizontalSpace = Math.max(nodeWidth - textFieldSize.width, textR.x);
    verticalSpace = Math.max(nodeHeight - textFieldSize.height, textR.y);
    final Dimension newParentSize = new Dimension(horizontalSpace + textFieldSize.width, verticalSpace + textFieldSize.height);
    parent.setPreferredSize(newParentSize);

    final Point location = new Point(textR.x - 2, textR.y);
    if(! layoutMapOnTextChange)
      UITools.convertPointToAncestor(parent, location, mapView);
    textfield.setBounds(location.x, location.y, textFieldSize.width, textFieldSize.height);
    parent.setText("");
        if(nodeView.isRoot() && parent instanceof MainView)
            parent.setHorizontalAlignment(JLabel.LEFT);
    if(layoutMapOnTextChange)
      parent.add(textfield, 0);
    else
      mapView.add(textfield, 0);
    final EventBuffer eventQueue = MTextController.getController().getEventQueue();
    KeyEvent firstEvent = eventQueue.getFirstEvent();
    redispatchKeyEvents(textfield, firstEvent);
    if (firstEvent == null) {
      MouseEvent currentEvent = eventQueue.getMouseEvent();
      int pos = document.getLength();
      if(currentEvent != null){
        MouseEvent mouseEvent = (MouseEvent) currentEvent;
        if(mouseEvent.getComponent().equals(parent)){
          final Point point = mouseEvent.getPoint();
          point.x -= textR.x;
          point.y -= textR.y;
          pos = textfield.viewToModel(point);
        }
      }
      textfield.setCaretPosition(pos);
    }
    document.addDocumentListener(documentListener);
    if(textController.isMinimized(node)){
      layout();
    }
    textfield.repaint();
    textfield.requestFocusInWindow();
  }
}
TOP

Related Classes of org.freeplane.view.swing.map.mindmapmode.EditNodeTextField$MapViewChangeListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.