Skip to content

Commit

Permalink
Webview - Add event message passing from the Webview to the IDE (#370)
Browse files Browse the repository at this point in the history
  • Loading branch information
Or-Geva authored Aug 2, 2023
1 parent 4ef2a0b commit ac7af1f
Show file tree
Hide file tree
Showing 17 changed files with 502 additions and 165 deletions.
98 changes: 98 additions & 0 deletions src/main/java/com/jfrog/ide/idea/inspections/JumpToCode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package com.jfrog.ide.idea.inspections;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.editor.markup.HighlighterTargetArea;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiUtilBase;
import org.jetbrains.annotations.NotNull;

/**
* The JumpToCode class is responsible for navigating to a specific location in a code file
* and highlighting the corresponding code.
*/
public class JumpToCode {
Project project;
FileEditorManager fileEditorManager;

/**
* Constructs a new {@code JumpToCode} with the provided project.
*
* @param project The current project.
*/
private JumpToCode(@NotNull Project project) {
this.project = project;
fileEditorManager = FileEditorManager.getInstance(project);
}

public static JumpToCode getInstance(@NotNull Project project) {
return project.getService(JumpToCode.class);
}

/**
* Executes the jump to code operation by opening the file in the editor and highlighting the specified code range.
*
* @param filePath The path of the file to navigate to.
* @param startRow The starting row of the code range.
* @param endRow The ending row of the code range.
* @param startColumn The starting column of the code range.
* @param endColumn The ending column of the code range.
*/
public void execute(String filePath, int startRow, int endRow, int startColumn, int endColumn) {
if (this.project == null || this.fileEditorManager == null) return;
VirtualFile file = getVirtualFile(filePath);
if (file == null) return;
ApplicationManager.getApplication().invokeLater(() -> {
openFileInEditor(file);
highlightCode(startRow, endRow, startColumn, endColumn);
});
}

private void openFileInEditor(VirtualFile file) {
fileEditorManager.openFile(file, true);
}

private void highlightCode(int startRow, int endRow, int startColumn, int endColumn) {
Editor editor = fileEditorManager.getSelectedTextEditor();
if (editor == null) return;
Document document = getDocument(editor);
if (document == null) return;
int startOffset = getOffset(document, startRow - 1, startColumn - 1);
int endOffset = getOffset(document, endRow - 1, endColumn - 1);
highlightCode(editor, startOffset, endOffset);
scrollToHighlightedCode(editor, startOffset);
}

private VirtualFile getVirtualFile(String path) {
return LocalFileSystem.getInstance().findFileByPath(path);
}

private Document getDocument(Editor editor) {
PsiFile psiFile = PsiUtilBase.getPsiFileInEditor(editor, project);
if (psiFile == null) return null;
return psiFile.getViewProvider().getDocument();
}

private int getOffset(Document document, int row, int column) {
return StringUtil.lineColToOffset(document.getText(), row, column);
}

private void highlightCode(Editor editor, int startOffset, int endOffset) {
SelectionModel selectionModel = editor.getSelectionModel();
selectionModel.setSelection(startOffset, endOffset);
editor.getMarkupModel().addRangeHighlighter(startOffset, endOffset, 0, null, HighlighterTargetArea.EXACT_RANGE);
}

private void scrollToHighlightedCode(Editor editor, int startOffset) {
editor.getCaretModel().moveToOffset(startOffset);
editor.getScrollingModel().scrollToCaret(ScrollType.CENTER);
}
}
64 changes: 25 additions & 39 deletions src/main/java/com/jfrog/ide/idea/ui/JFrogLocalToolWindow.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,43 +8,45 @@
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.impl.jdkDownloader.RuntimeChooserUtil;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.Navigatable;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.ui.*;
import com.intellij.ui.HyperlinkLabel;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.OnePixelSplitter;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.SideBorder;
import com.intellij.ui.TreeSpeedSearch;
import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.JBPanel;
import com.intellij.ui.jcef.JBCefApp;
import com.intellij.ui.jcef.JBCefBrowser;
import com.intellij.util.ui.UIUtil;
import com.jfrog.ide.common.nodes.*;
import com.jfrog.ide.common.nodes.ApplicableIssueNode;
import com.jfrog.ide.common.nodes.FileIssueNode;
import com.jfrog.ide.common.nodes.IssueNode;
import com.jfrog.ide.common.nodes.LicenseViolationNode;
import com.jfrog.ide.common.nodes.VulnerabilityNode;
import com.jfrog.ide.idea.actions.CollapseAllAction;
import com.jfrog.ide.idea.actions.ExpandAllAction;
import com.jfrog.ide.idea.actions.GoToSettingsAction;
import com.jfrog.ide.idea.actions.ScanTimeLabelAction;
import com.jfrog.ide.idea.configuration.GlobalSettings;
import com.jfrog.ide.idea.events.ApplicationEvents;
import com.jfrog.ide.idea.inspections.JumpToCode;
import com.jfrog.ide.idea.log.Logger;
import com.jfrog.ide.idea.scan.ScanManager;
import com.jfrog.ide.idea.ui.jcef.message.MessageType;
import com.jfrog.ide.idea.ui.utils.ComponentUtils;
import com.jfrog.ide.idea.ui.webview.WebviewManager;
import com.jfrog.ide.idea.ui.webview.WebviewObjectConverter;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.cef.browser.CefBrowser;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import javax.swing.tree.TreeSelectionModel;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;

import static com.jfrog.ide.idea.ui.JFrogToolWindow.SCROLL_BAR_SCROLLING_UNITS;
import static com.jfrog.ide.idea.ui.webview.event.model.WebviewEvent.Type.SHOW_PAGE;

/**
* @author yahavi
Expand Down Expand Up @@ -72,10 +74,10 @@ public JFrogLocalToolWindow(@NotNull Project project) {
leftPanel.add(createJcefNotSupportedView(), 0);
return;
}
JBCefBrowser jbCefBrowser;

JComponent browserComponent;
try {
browserComponent = initVulnerabilityInfoBrowser();
jbCefBrowser = initVulnerabilityInfoBrowser(project);
} catch (IOException | URISyntaxException e) {
Logger.getInstance().error("Local view couldn't be initialized.", e);
leftPanel.removeAll();
Expand All @@ -92,7 +94,7 @@ public JFrogLocalToolWindow(@NotNull Project project) {

alertIfCacheExpired();
refreshView();
registerListeners(browserComponent);
registerListeners(jbCefBrowser.getComponent());
isInitialized = true;
}

Expand Down Expand Up @@ -222,12 +224,10 @@ private void setLeftPanelContent(JComponent component) {
leftPanelContent.add(component, 0);
}

private JComponent initVulnerabilityInfoBrowser() throws IOException, URISyntaxException {
webviewManager = new WebviewManager();
private JBCefBrowser initVulnerabilityInfoBrowser(@NotNull Project project) throws IOException, URISyntaxException {
webviewManager = new WebviewManager(project);
Disposer.register(this, webviewManager);

CefBrowser browser = webviewManager.createBrowser(() -> updateIssueOrLicenseInWebview(selectedIssue));
return (JComponent) browser.getUIComponent();
return webviewManager.getBrowser();
}

/**
Expand All @@ -248,35 +248,21 @@ private JComponent createComponentsTreeView() {

private void updateIssueOrLicenseInWebview(IssueNode issueNode) {
if (issueNode instanceof VulnerabilityNode issue) {
webviewManager.sendMessage(MessageType.SHOW_PAGE, WebviewObjectConverter.convertIssueToDepPage(issue));
webviewManager.sendMessage(SHOW_PAGE, WebviewObjectConverter.convertIssueToDepPage(issue));
} else if (issueNode instanceof ApplicableIssueNode) {
ApplicableIssueNode node = (ApplicableIssueNode) issueNode;
webviewManager.sendMessage(MessageType.SHOW_PAGE, WebviewObjectConverter.convertIssueToDepPage(node.getIssue()));
webviewManager.sendMessage(SHOW_PAGE, WebviewObjectConverter.convertIssueToDepPage(node.getIssue()));
navigateToFile(node);
} else if (issueNode instanceof LicenseViolationNode license) {
webviewManager.sendMessage(MessageType.SHOW_PAGE, WebviewObjectConverter.convertLicenseToDepPage(license));
webviewManager.sendMessage(SHOW_PAGE, WebviewObjectConverter.convertLicenseToDepPage(license));
} else if (issueNode instanceof FileIssueNode node) {
webviewManager.sendMessage(MessageType.SHOW_PAGE, WebviewObjectConverter.convertFileIssueToIssuePage(node));
webviewManager.sendMessage(SHOW_PAGE, WebviewObjectConverter.convertFileIssueToIssuePage(node));
navigateToFile(node);
}
}

private void navigateToFile(FileIssueNode node) {
ApplicationManager.getApplication().invokeLater(() -> {
VirtualFile sourceCodeFile = LocalFileSystem.getInstance().findFileByIoFile(new File(node.getFilePath()));
if (sourceCodeFile == null) {
return;
}
PsiFile targetFile = PsiManager.getInstance(project).findFile(sourceCodeFile);
if (targetFile == null) {
return;
}
int lineOffset = StringUtil.lineColToOffset(targetFile.getText(), node.getRowStart(), node.getColStart());
PsiElement element = targetFile.findElementAt(lineOffset);
if (element instanceof Navigatable) {
((Navigatable) element).navigate(true);
} else targetFile.navigate(true);
});
JumpToCode.getInstance(project).execute(node.getFilePath(), node.getRowStart(), node.getRowEnd(), node.getColStart(), node.getColEnd());
}

/**
Expand Down

This file was deleted.

12 changes: 0 additions & 12 deletions src/main/java/com/jfrog/ide/idea/ui/jcef/message/MessagePipe.java

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Loading

0 comments on commit ac7af1f

Please sign in to comment.