Package browsewordatcaret

Source Code of browsewordatcaret.BWACEditorComponent

/*
* Copyright 2012 Minas Manthos
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package browsewordatcaret;

import com.intellij.codeInsight.hint.HintManager;
import com.intellij.codeInsight.hint.HintManagerImpl;
import com.intellij.codeInsight.hint.HintUtil;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.editor.event.*;
import com.intellij.openapi.editor.ex.MarkupModelEx;
import com.intellij.openapi.editor.markup.HighlighterLayer;
import com.intellij.openapi.editor.markup.HighlighterTargetArea;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.LightweightHint;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

public class BWACEditorComponent implements SelectionListener, CaretListener, DocumentListener {
    private Editor editor;
    private final List<RangeHighlighter> items = new ArrayList<RangeHighlighter>();
    private volatile int updating;
    private boolean autoHighlight;

    private static final int HIGHLIGHTLAYER = HighlighterLayer.SELECTION - 1; // unmittelbar unter Selektion-level
    private static final int UPDATEDELAY = 400;

    public BWACEditorComponent(Editor editor, boolean autoHighlight) {
        this.editor = editor;
        this.autoHighlight = autoHighlight;

        editor.getSelectionModel().addSelectionListener(this);
        editor.getCaretModel().addCaretListener(this);
        editor.getDocument().addDocumentListener(this);
    }

    public void dispose() {
//        clearHighlighters();
        editor.getSelectionModel().removeSelectionListener(this);
        editor.getCaretModel().removeCaretListener(this);
        editor.getDocument().removeDocumentListener(this);
//        editor = null;
    }

    @Override
    public void selectionChanged(SelectionEvent selectionEvent) {
        if (updating > 0) {
            return;
        }

        // wenn ColumnMode -> gibts nicht mehr zu tun
        if (editor.isColumnMode()) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    buildHighlighters(null); // noch löschen, da vielleicht etwas selektiert war und umgestellt wurde
                }
            });
            return;
        }
        // Selektion wurde aufgehoben -> nichts machen -> sobald cursor ausserhalb kommt wird ge'cleared... ( siehe caretPositionChanged...)
        if (selectionEvent.getNewRange().getLength() == 0) {
            return;
        }

        String text = editor.getDocument().getText();
        TextRange textRange = selectionEvent.getNewRange();

        // aufgrund selektiertem Text erstellen
        final String highlightText;
        if ((textRange.getStartOffset() != 0 || textRange.getEndOffset() != text.length()) && // fix issue 5: komplettem text ausschliessen
                BWACUtils.isStartEnd(text, textRange.getStartOffset(), textRange.getEndOffset(), false)) {
            highlightText = textRange.substring(text);
        } else {
            highlightText = null; // ansonsten löschen
        }
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                buildHighlighters(highlightText);
            }
        });
    }

    private Timer caretChangedDelayTimer = new Timer(UPDATEDELAY, new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            synchronized (items) {
                int currentOffset = editor.getCaretModel().getOffset();
                // wenn der Cursor innerhalb eines unserer RangeHighlighter kommt -> return
                if (!items.isEmpty() && getItemIndex(currentOffset) >= 0) {
                    return;
                }
                performHighlight();
            }
        }
    }) {
        {
            setRepeats(false);
        }
    };

    private void performHighlight() {
        // aktuelles Wort unter dem Cursor nehmen...
        final String wordToHighlight;
        if (autoHighlight && !editor.getSelectionModel().hasSelection()) {
            int currentOffset = editor.getCaretModel().getOffset();
            wordToHighlight = BWACUtils.extractWordFrom(editor.getDocument().getText(), currentOffset);
        } else {
            wordToHighlight = null;
        }

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                buildHighlighters(StringUtil.isEmpty(wordToHighlight) ? null : wordToHighlight);
            }
        });
    }

    public boolean isAutoHighlight() {
        return autoHighlight;
    }

    public void setAutoHighlight(boolean autoHighlight) {
        if (this.autoHighlight != autoHighlight) {
            this.autoHighlight = autoHighlight;
            if (!editor.getSelectionModel().hasSelection()) {
                performHighlight();
            }
        }
    }

    @Override
    public void caretPositionChanged(CaretEvent caretEvent) {
        if (updating > 0) {
            return;
        }
        caretChangedDelayTimer.restart();
    }

    @Override
    public void beforeDocumentChange(DocumentEvent documentEvent) {
    }

    @Override
    public void documentChanged(DocumentEvent documentEvent) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                buildHighlighters(null); // bei changed -> löschen
            }
        });
    }

    private static final Key<BWACHandlerBrowse.BrowseDirection> KEY = Key.create("BWACHandlerBrowse.BrowseDirection.KEY");

    public void browse(@NotNull final BWACHandlerBrowse.BrowseDirection browseDirection) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                updating++;
                try {
                    synchronized (items) {
                        // wenn noch keine RangeHighlights vorhanden ->
                        if (items.isEmpty() || caretChangedDelayTimer.isRunning()) {
                            // aktuelles Wort unter dem Cursor nehmen...
                            String currentWord = BWACUtils.extractWordFrom(editor.getDocument().getText(), editor.getCaretModel().getOffset());
                            if (currentWord == null) {
                                return; // kein wort -> nichts zu machen
                            }
                            buildHighlighters(currentWord);
                        }
                        int index = getItemIndex(editor.getCaretModel().getOffset()) + (BWACHandlerBrowse.BrowseDirection.NEXT.equals(browseDirection) ? 1 : -1);

                        if (index >= 0 && index < items.size()) {
                            int offset = items.get(index).getStartOffset();
                            moveToOffset(offset);
                        } else if (items.size() > 0) {
                            if (editor.getUserData(KEY) == browseDirection) {
                                // performed again -> start from top/bottom
                                editor.putUserData(KEY, null);
                                int offset = items.get(browseDirection == BWACHandlerBrowse.BrowseDirection.NEXT ? 0 : items.size() - 1).getStartOffset();
                                moveToOffset(offset);
                            } else {
                                final String message;
                                if (BWACApplicationComponent.getInstance().isWrapAround()) {
                                    // top/bottom reached -> remember browse direction
                                    editor.putUserData(KEY, browseDirection);
                                    CaretListener listener = new CaretListener() {
                                        @Override
                                        public void caretPositionChanged(CaretEvent e) {
                                            editor.putUserData(KEY, null);
                                            editor.getCaretModel().removeCaretListener(this);
                                        }
                                    };
                                    editor.getCaretModel().addCaretListener(listener);
                                    message = getPerformAgainMessage(browseDirection);
                                } else {
                                    message = "Not found";
                                }
                                // show hint
                                LightweightHint hint = new LightweightHint(HintUtil.createInformationLabel(message));
                                HintManagerImpl.getInstanceImpl().showEditorHint(hint, editor,
                                        browseDirection == BWACHandlerBrowse.BrowseDirection.NEXT ? HintManager.UNDER : HintManager.ABOVE,
                                        HintManager.HIDE_BY_ANY_KEY | HintManager.HIDE_BY_TEXT_CHANGE | HintManager.HIDE_BY_SCROLLING,
                                        0, false);
                            }
                        }
                    }
                } finally {
                    updating--;
                }
            }
        });
    }

    @NotNull
    private String getPerformAgainMessage(@NotNull final BWACHandlerBrowse.BrowseDirection browseDirection) {
        AnAction action = ActionManager.getInstance().getAction(browseDirection == BWACHandlerBrowse.BrowseDirection.NEXT ? "BrowseWordAtCaretPlugin.Next" : "BrowseWordAtCaretPlugin.Previous");
        String shortcutsText = KeymapUtil.getFirstKeyboardShortcutText(action);
        String message;
        if (shortcutsText.length() > 0) {
            if (browseDirection == BWACHandlerBrowse.BrowseDirection.NEXT) {
                message = "Not found, press " + shortcutsText + " to browse from the top";
            } else {
                message = "Not found, press " + shortcutsText + " to browse from the bottom";
            }
        } else {
            if (browseDirection == BWACHandlerBrowse.BrowseDirection.NEXT) {
                message = "Not found, perform \"Browse to next word\" again to browse from the top";
            } else {
                message = "Not found, perform \"Browse to previous word\" again to browse from the bottom";
            }
        }
        return JDOMUtil.escapeText(message, false, false);
    }

    private int getItemIndex(int offset) {
        synchronized (items) {
            for (int i = 0; i < items.size(); i++) {
                RangeHighlighter item = items.get(i);
                if (offset >= item.getStartOffset() && offset <= item.getEndOffset()) {
                    return i;
                }
            }
        }
        return -1;
    }

    // DISPATCH THREAD METHODS

    private void moveToOffset(int offset) {
        ApplicationManager.getApplication().assertIsDispatchThread();
        // Cursor setzen
        editor.getCaretModel().moveToOffset(offset);
        /*
        // Wort selektieren
        if (ApplicationManager.getApplication().getComponent(BWACApplicationComponent.class).prefSelectWord) {
            editor.getSelectionModel().setSelection(offset, offset + highlightText.length());
        }
        */
        // in sichtbaren Bereich bringen
        editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
    }

    private void buildHighlighters(final String highlightText) {
        ApplicationManager.getApplication().assertIsDispatchThread();
        synchronized (items) {
            // aktuelle löschen
            final MarkupModelEx markupModel = (MarkupModelEx) editor.getMarkupModel();
            for (RangeHighlighter rangeHighlighter : items) {
                if (markupModel.containsHighlighter(rangeHighlighter)) {
                    markupModel.removeHighlighter(rangeHighlighter);
                }
            }
            items.clear();
            // und erstellen
            if (highlightText != null) {
                // text durchsuchen
                String text = editor.getDocument().getText();
                // textAttribute für RangeHighlighter holen
                final TextAttributes textAttributes = editor.getColorsScheme().getAttributes(BWACColorSettingsPage.BROWSEWORDATCARET);

                int index = -1;
                do {
                    index = text.indexOf(highlightText, index + 1);
                    // wenn gefunden und ganzes wort -> aufnehmen
                    if (index >= 0 && BWACUtils.isStartEnd(text, index, index + highlightText.length(), true)) {
                        RangeHighlighter rangeHighlighter = markupModel.addRangeHighlighter(index, index + highlightText.length(), HIGHLIGHTLAYER, textAttributes, HighlighterTargetArea.EXACT_RANGE);
                        rangeHighlighter.setErrorStripeTooltip(highlightText);
                        items.add(rangeHighlighter);
                    }
                } while (index >= 0);
            }
        }
    }
}
TOP

Related Classes of browsewordatcaret.BWACEditorComponent

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.