com.intellij.xdebugger.impl.ui.ExecutionPointHighlighter.java Source code

Java tutorial

Introduction

Here is the source code for com.intellij.xdebugger.impl.ui.ExecutionPointHighlighter.java

Source

/*
 * Copyright 2000-2015 JetBrains s.r.o.
 *
 * 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 com.intellij.xdebugger.impl.ui;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.colors.EditorColorsListener;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.impl.DocumentMarkupModel;
import com.intellij.openapi.editor.impl.EditorImpl;
import com.intellij.openapi.editor.markup.*;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.AppUIUtil;
import com.intellij.util.DocumentUtil;
import com.intellij.xdebugger.XSourcePosition;
import com.intellij.xdebugger.impl.XDebuggerUtilImpl;
import com.intellij.xdebugger.impl.XSourcePositionImpl;
import com.intellij.xdebugger.ui.DebuggerColors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @author nik
 */
public class ExecutionPointHighlighter {
    private final Project myProject;
    private RangeHighlighter myRangeHighlighter;
    private Editor myEditor;
    private XSourcePosition mySourcePosition;
    private OpenFileDescriptor myOpenFileDescriptor;
    private boolean myNotTopFrame;
    private GutterIconRenderer myGutterIconRenderer;
    private static final Key<Boolean> EXECUTION_POINT_HIGHLIGHTER_KEY = Key
            .create("EXECUTION_POINT_HIGHLIGHTER_KEY");

    private final AtomicBoolean updateRequested = new AtomicBoolean();

    public ExecutionPointHighlighter(final Project project) {
        myProject = project;

        // Update highlighter colors if global color schema was changed
        final EditorColorsManager colorsManager = EditorColorsManager.getInstance();
        if (colorsManager != null) { // in some debugger tests EditorColorsManager component isn't loaded
            colorsManager.addEditorColorsListener(new EditorColorsListener() {
                @Override
                public void globalSchemeChange(EditorColorsScheme scheme) {
                    update(false);
                }
            }, project);
        }
    }

    public void show(final @NotNull XSourcePosition position, final boolean notTopFrame,
            @Nullable final GutterIconRenderer gutterIconRenderer) {
        updateRequested.set(false);
        AppUIUtil.invokeLaterIfProjectAlive(myProject, new Runnable() {
            @Override
            public void run() {
                updateRequested.set(false);

                mySourcePosition = position;

                clearDescriptor();
                myOpenFileDescriptor = XSourcePositionImpl.createOpenFileDescriptor(myProject, position);
                //see IDEA-125645 and IDEA-63459
                //myOpenFileDescriptor.setUseCurrentWindow(true);

                myGutterIconRenderer = gutterIconRenderer;
                myNotTopFrame = notTopFrame;

                doShow(true);
            }
        });
    }

    public void hide() {
        AppUIUtil.invokeOnEdt(new Runnable() {
            @Override
            public void run() {
                updateRequested.set(false);

                removeHighlighter();
                clearDescriptor();
                myEditor = null;
                myGutterIconRenderer = null;
            }
        });
    }

    private void clearDescriptor() {
        if (myOpenFileDescriptor != null) {
            myOpenFileDescriptor.dispose();
            myOpenFileDescriptor = null;
        }
    }

    public void navigateTo() {
        if (myOpenFileDescriptor != null) {
            myOpenFileDescriptor.navigateInEditor(myProject, true);
        }
    }

    @Nullable
    public VirtualFile getCurrentFile() {
        return myOpenFileDescriptor != null ? myOpenFileDescriptor.getFile() : null;
    }

    public void update(final boolean navigate) {
        if (updateRequested.compareAndSet(false, true)) {
            ApplicationManager.getApplication().invokeLater(new Runnable() {
                @Override
                public void run() {
                    if (updateRequested.compareAndSet(true, false)) {
                        doShow(navigate);
                    }
                }
            }, myProject.getDisposed());
        }
    }

    public void updateGutterIcon(@NotNull final GutterIconRenderer renderer) {
        AppUIUtil.invokeOnEdt(new Runnable() {
            @Override
            public void run() {
                if (myRangeHighlighter != null && myGutterIconRenderer != null) {
                    myRangeHighlighter.setGutterIconRenderer(renderer);
                }
            }
        });
    }

    private void doShow(boolean navigate) {
        ApplicationManager.getApplication().assertIsDispatchThread();
        if (ApplicationManager.getApplication().isUnitTestMode())
            return;

        removeHighlighter();

        OpenFileDescriptor fileDescriptor = myOpenFileDescriptor;
        if (!navigate && myOpenFileDescriptor != null) {
            fileDescriptor = new OpenFileDescriptor(myProject, myOpenFileDescriptor.getFile());
        }
        myEditor = fileDescriptor == null ? null : XDebuggerUtilImpl.createEditor(fileDescriptor);
        if (myEditor != null) {
            addHighlighter();
        }
    }

    private void removeHighlighter() {
        if (myEditor != null) {
            adjustCounter(myEditor, -1);
        }

        //if (myNotTopFrame && myEditor != null) {
        //  myEditor.getSelectionModel().removeSelection();
        //}

        if (myRangeHighlighter != null) {
            myRangeHighlighter.dispose();
            myRangeHighlighter = null;
        }
    }

    private void addHighlighter() {
        adjustCounter(myEditor, 1);
        int line = mySourcePosition.getLine();
        Document document = myEditor.getDocument();
        if (line < 0 || line >= document.getLineCount())
            return;

        //if (myNotTopFrame) {
        //  myEditor.getSelectionModel().setSelection(document.getLineStartOffset(line), document.getLineEndOffset(line) + document.getLineSeparatorLength(line));
        //  return;
        //}

        if (myRangeHighlighter != null)
            return;

        EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
        TextAttributes attributes = myNotTopFrame ? scheme.getAttributes(DebuggerColors.NOT_TOP_FRAME_ATTRIBUTES)
                : scheme.getAttributes(DebuggerColors.EXECUTIONPOINT_ATTRIBUTES);
        MarkupModel markupModel = DocumentMarkupModel.forDocument(document, myProject, true);
        if (mySourcePosition instanceof HighlighterProvider) {
            TextRange range = ((HighlighterProvider) mySourcePosition).getHighlightRange();
            if (range != null) {
                range = range.intersection(DocumentUtil.getLineTextRange(document, line));
                if (range != null && !range.isEmpty()) {
                    myRangeHighlighter = markupModel.addRangeHighlighter(range.getStartOffset(),
                            range.getEndOffset(), DebuggerColors.EXECUTION_LINE_HIGHLIGHTERLAYER, attributes,
                            HighlighterTargetArea.EXACT_RANGE);
                }
            }
        }
        if (myRangeHighlighter == null) {
            myRangeHighlighter = markupModel.addLineHighlighter(line,
                    DebuggerColors.EXECUTION_LINE_HIGHLIGHTERLAYER, attributes);
        }
        myRangeHighlighter.putUserData(EXECUTION_POINT_HIGHLIGHTER_KEY, true);
        myRangeHighlighter.setGutterIconRenderer(myGutterIconRenderer);
    }

    private static void adjustCounter(@NotNull final Editor editor, final int increment) {
        if (ApplicationManager.getApplication().isUnitTestMode())
            return;

        // need to always invoke later to maintain order of increment/decrement
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JComponent component = editor.getComponent();
                Object o = component.getClientProperty(EditorImpl.IGNORE_MOUSE_TRACKING);
                Integer value = ((o instanceof Integer) ? (Integer) o : 0) + increment;
                component.putClientProperty(EditorImpl.IGNORE_MOUSE_TRACKING, value > 0 ? value : null);
            }
        });
    }

    public interface HighlighterProvider {
        @Nullable
        TextRange getHighlightRange();
    }
}