blob: f478fe4cc45329668a18ac7d7d6f88de250146c1 [file] [log] [blame]
/*
* Copyright 2000-2009 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.breakpoints;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.ex.MarkupModelEx;
import com.intellij.openapi.editor.impl.DocumentMarkupModel;
import com.intellij.openapi.editor.markup.GutterDraggableObject;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XDebuggerUtil;
import com.intellij.xdebugger.XSourcePosition;
import com.intellij.xdebugger.breakpoints.XBreakpointProperties;
import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
import com.intellij.xdebugger.breakpoints.XLineBreakpointType;
import com.intellij.xdebugger.ui.DebuggerColors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.dnd.DragSource;
import java.io.File;
import java.util.List;
/**
* @author nik
*/
public class XLineBreakpointImpl<P extends XBreakpointProperties> extends XBreakpointBase<XLineBreakpoint<P>, P, LineBreakpointState<P>> implements XLineBreakpoint<P> {
@Nullable private RangeHighlighter myHighlighter;
private final XLineBreakpointType<P> myType;
private XSourcePosition mySourcePosition;
private boolean myDisposed;
public XLineBreakpointImpl(final XLineBreakpointType<P> type,
XBreakpointManagerImpl breakpointManager,
@Nullable final P properties, LineBreakpointState<P> state) {
super(type, breakpointManager, properties, state);
myType = type;
}
XLineBreakpointImpl(final XLineBreakpointType<P> type,
XBreakpointManagerImpl breakpointManager,
final LineBreakpointState<P> breakpointState) {
super(type, breakpointManager, breakpointState);
myType = type;
}
public void updateUI() {
if (myDisposed) return;
if (ApplicationManager.getApplication().isUnitTestMode()) return;
Document document = getDocument();
if (document == null) return;
EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
TextAttributes attributes = scheme.getAttributes(DebuggerColors.BREAKPOINT_ATTRIBUTES);
removeHighlighter();
MarkupModelEx markupModel = (MarkupModelEx)DocumentMarkupModel.forDocument(document, getProject(), true);
RangeHighlighter highlighter = markupModel.addPersistentLineHighlighter(getLine(), DebuggerColors.BREAKPOINT_HIGHLIGHTER_LAYER,
attributes);
if (highlighter != null) {
updateIcon();
highlighter.setGutterIconRenderer(createGutterIconRenderer());
highlighter.putUserData(DebuggerColors.BREAKPOINT_HIGHLIGHTER_KEY, Boolean.TRUE);
}
myHighlighter = highlighter;
}
@Nullable
public Document getDocument() {
VirtualFile file = getFile();
if (file == null) return null;
return FileDocumentManager.getInstance().getDocument(file);
}
@Nullable
private VirtualFile getFile() {
return VirtualFileManager.getInstance().findFileByUrl(getFileUrl());
}
@Override
@NotNull
public XLineBreakpointType<P> getType() {
return myType;
}
@Override
public int getLine() {
return myState.getLine();
}
@Override
public String getFileUrl() {
return myState.getFileUrl();
}
@Override
public String getPresentableFilePath() {
String url = getFileUrl();
if (url != null && LocalFileSystem.PROTOCOL.equals(VirtualFileManager.extractProtocol(url))) {
return FileUtil.toSystemDependentName(VfsUtilCore.urlToPath(url));
}
return url != null ? url : "";
}
@Override
public String getShortFilePath() {
final String path = getPresentableFilePath();
if (path.isEmpty()) return "";
return new File(path).getName();
}
@Nullable
public RangeHighlighter getHighlighter() {
return myHighlighter;
}
@Override
public XSourcePosition getSourcePosition() {
if (mySourcePosition == null) {
new ReadAction() {
@Override
protected void run(final Result result) {
mySourcePosition = XDebuggerUtil.getInstance().createPosition(getFile(), getLine());
}
}.execute();
}
return mySourcePosition;
}
@Override
public boolean isValid() {
return myHighlighter != null && myHighlighter.isValid();
}
@Override
public void dispose() {
removeHighlighter();
myDisposed = true;
}
private void removeHighlighter() {
if (myHighlighter != null) {
myHighlighter.dispose();
myHighlighter = null;
}
}
@Override
protected GutterDraggableObject createBreakpointDraggableObject() {
return new GutterDraggableObject() {
@Override
public boolean copy(int line, VirtualFile file) {
if (canMoveTo(line, file)) {
setFileUrl(file.getUrl());
setLine(line);
return true;
}
return false;
}
@Override
public Cursor getCursor(int line) {
return canMoveTo(line, getFile()) ? DragSource.DefaultMoveDrop : DragSource.DefaultMoveNoDrop;
}
};
}
private boolean canMoveTo(int line, VirtualFile file) {
return file != null && myType.canPutAt(file, line, getProject()) && getBreakpointManager().findBreakpointAtLine(myType, file, line) == null;
}
public void updatePosition() {
if (myHighlighter != null && myHighlighter.isValid()) {
Document document = myHighlighter.getDocument();
setLine(document.getLineNumber(myHighlighter.getStartOffset()));
}
}
public void setFileUrl(final String newUrl) {
if (!Comparing.equal(getFileUrl(), newUrl)) {
myState.setFileUrl(newUrl);
mySourcePosition = null;
fireBreakpointChanged();
}
}
private void setLine(final int line) {
if (getLine() != line) {
myState.setLine(line);
mySourcePosition = null;
fireBreakpointChanged();
}
}
@Override
public boolean isTemporary() {
return myState.isTemporary();
}
@Override
public void setTemporary(boolean temporary) {
if (isTemporary() != temporary) {
myState.setTemporary(temporary);
fireBreakpointChanged();
}
}
@Override
protected List<? extends AnAction> getAdditionalPopupMenuActions(final XDebugSession session) {
return getType().getAdditionalPopupMenuActions(this, session);
}
@Override
protected void updateIcon() {
final Icon icon = calculateSpecialIcon();
if (icon != null) {
setIcon(icon);
return;
}
setIcon(isTemporary() ? myType.getTemporaryIcon() : myType.getEnabledIcon());
}
}