@@ -55,14 +55,11 @@ import java.nio.charset.Charset
5555import java.nio.file.Files
5656import java.nio.file.Path
5757import javax.swing.*
58- import javax.swing.event.HyperlinkEvent
59- import javax.swing.event.HyperlinkListener
6058import javax.swing.event.TreeSelectionEvent
6159import javax.swing.event.TreeSelectionListener
6260import javax.swing.filechooser.FileNameExtensionFilter
6361import javax.swing.table.DefaultTableCellRenderer
6462import javax.swing.table.DefaultTableModel
65- import javax.swing.text.html.HTMLEditorKit
6663import javax.swing.tree.DefaultMutableTreeNode
6764import javax.swing.tree.DefaultTreeModel
6865
@@ -112,7 +109,7 @@ class SarifViewerWindowFactory : ToolWindowFactory {
112109 private var comboBranchPR = ComboBox (arrayOf(BranchItemComboBox (0 , " main" , " " , " " )))
113110 private val tableInfos = JBTable (DefaultTableModel (arrayOf<Any >(" Property" , " Value" ), 0 ))
114111 private val tableSteps = JBTable (DefaultTableModel (arrayOf<Any >(" Path" ), 0 ))
115- private val steps = JEditorPane ()
112+ private val steps = JPanel ()
116113 private val errorField = JLabel (" Error message here " )
117114 private val errorToolbar = JToolBar (" " , JToolBar .HORIZONTAL )
118115 private val loadingPanel = JPanel ()
@@ -265,16 +262,9 @@ class SarifViewerWindowFactory : ToolWindowFactory {
265262 }
266263
267264 private fun JBPanel <JBPanel <* >>.buildSkeleton () {
268- steps.isEditable = false
269- steps.addHyperlinkListener(object : HyperlinkListener {
270- override fun hyperlinkUpdate (hle : HyperlinkEvent ? ) {
271- if (HyperlinkEvent .EventType .ACTIVATED == hle?.eventType) {
272- hle?.description.toString().split(" :" ).let { location ->
273- openFile(project, location[0 ], location[1 ].toInt())
274- }
275- }
276- }
277- })
265+ steps.layout = BoxLayout (steps, BoxLayout .Y_AXIS )
266+ tableSteps.size = Dimension (steps.width, steps.height)
267+ steps.add(tableSteps)
278268
279269 // Add the table to a scroll pane
280270 val scrollPane = JScrollPane (tableInfos)
@@ -486,7 +476,12 @@ class SarifViewerWindowFactory : ToolWindowFactory {
486476 defaultTableModel.addRow(arrayOf<Any >(" Rule's description" , leaf.ruleDescription))
487477 defaultTableModel.addRow(arrayOf<Any >(" Location" , leaf.location))
488478 defaultTableModel.addRow(arrayOf<Any >(" GitHub alert number" , leaf.githubAlertNumber))
489- defaultTableModel.addRow(arrayOf<Any >(" GitHub alert url" , " <a href=\" $githubAlertUrl \" >$githubAlertUrl </a" ))
479+ defaultTableModel.addRow(
480+ arrayOf<Any >(
481+ " GitHub alert url" ,
482+ " <a href=\" $githubAlertUrl \" >$githubAlertUrl </a"
483+ )
484+ )
490485
491486 tableInfos.setDefaultRenderer(Object ::class .java, object : DefaultTableCellRenderer () {
492487 override fun getTableCellRendererComponent (
@@ -497,7 +492,14 @@ class SarifViewerWindowFactory : ToolWindowFactory {
497492 row : Int ,
498493 column : Int
499494 ): Component {
500- var c = super .getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column)
495+ var c = super .getTableCellRendererComponent(
496+ table,
497+ value,
498+ isSelected,
499+ hasFocus,
500+ row,
501+ column
502+ )
501503 if (row == tableInfos.rowCount - 1 && column == tableInfos.columnCount - 1 ) {
502504 val url = tableInfos.getValueAt(row, column).toString()
503505 c = JLabel (" <html><a href='$url '>$url </a></html>" )
@@ -514,7 +516,9 @@ class SarifViewerWindowFactory : ToolWindowFactory {
514516 val column = tableInfos.columnAtPoint(e.point)
515517 if (row == tableInfos.rowCount - 1 ) {
516518 if (column == tableInfos.columnCount - 1 ) {
517- if (Desktop .isDesktopSupported() && Desktop .getDesktop().isSupported(Desktop .Action .BROWSE )) {
519+ if (Desktop .isDesktopSupported() && Desktop .getDesktop()
520+ .isSupported(Desktop .Action .BROWSE )
521+ ) {
518522 Desktop .getDesktop().browse(URI (githubAlertUrl))
519523 }
520524 }
@@ -524,11 +528,21 @@ class SarifViewerWindowFactory : ToolWindowFactory {
524528
525529 tableInfos.updateUI()
526530
527- steps.read(leaf.steps.joinToString(" " , " <ul>" , " </ul>" ) { step ->
528- " <li><a href=\" $step \" >${step.split(" /" ).last()} </a></li>"
529- }.byteInputStream(Charset .defaultCharset()), HTMLEditorKit ::class .java)
531+ tableSteps.clearSelection()
530532
531- steps.contentType = " text/html"
533+ tableSteps.model = DefaultTableModel (arrayOf<Any >(" Path" ), 0 )
534+
535+ leaf.steps.forEachIndexed { index, step ->
536+ (tableSteps.model as DefaultTableModel ).addRow(arrayOf<Any >(" $index $step " ))
537+ }
538+
539+ tableSteps.addMouseListener(object : MouseAdapter () {
540+ override fun mouseClicked (e : MouseEvent ) {
541+ val row = tableInfos.rowAtPoint(e.point)
542+ val path = leaf.steps[row].split(" :" )
543+ openFile(project, path[0 ], path[1 ].toInt())
544+ }
545+ })
532546
533547 details.isVisible = true
534548 openFile(
@@ -579,32 +593,33 @@ class SarifViewerWindowFactory : ToolWindowFactory {
579593 true // request focus to editor
580594 )
581595 FileDocumentManager .getInstance().getDocument(virtualFile)?.let { document ->
582- val lineStartOffset = document.getLineStartOffset(lineNumber - 1 )
583- val lineEndOffset = document.getLineEndOffset(lineNumber - 1 )
584- val editor = FileEditorManager .getInstance(project).selectedTextEditor ? : return
585- editor.caretModel.moveToOffset(lineStartOffset)
586- editor.scrollingModel.scrollToCaret(ScrollType .CENTER )
587- editor.selectionModel.setSelection(lineStartOffset, lineEndOffset)
588-
589- val messageType = when (level) {
590- " error" -> MessageType .ERROR
591- " warning" -> MessageType .WARNING
592- else -> MessageType .INFO
593- }
594-
595- // add a balloon on the selection
596- val balloon = JBPopupFactory .getInstance().createHtmlTextBalloonBuilder(
597- ruleDescription,
598- messageType,
599- null
600- ).createBalloon()
601- balloon.show(
602- RelativePoint (
603- editor.contentComponent,
604- editor.visualPositionToXY(editor.caretModel.visualPosition)
605- ), Balloon .Position .above
606- )
596+ if (ruleDescription.isNotEmpty()) {
597+ val lineStartOffset = document.getLineStartOffset(lineNumber - 1 )
598+ val lineEndOffset = document.getLineEndOffset(lineNumber - 1 )
599+ val editor = FileEditorManager .getInstance(project).selectedTextEditor ? : return
600+ editor.caretModel.moveToOffset(lineStartOffset)
601+ editor.scrollingModel.scrollToCaret(ScrollType .CENTER )
602+ editor.selectionModel.setSelection(lineStartOffset, lineEndOffset)
603+
604+ val messageType = when (level) {
605+ " error" -> MessageType .ERROR
606+ " warning" -> MessageType .WARNING
607+ else -> MessageType .INFO
608+ }
607609
610+ // add a balloon on the selection
611+ val balloon = JBPopupFactory .getInstance().createHtmlTextBalloonBuilder(
612+ ruleDescription,
613+ messageType,
614+ null
615+ ).createBalloon()
616+ balloon.show(
617+ RelativePoint (
618+ editor.contentComponent,
619+ editor.visualPositionToXY(editor.caretModel.visualPosition)
620+ ), Balloon .Position .above
621+ )
622+ }
608623 }
609624
610625 }
@@ -620,7 +635,8 @@ class SarifViewerWindowFactory : ToolWindowFactory {
620635
621636 tableInfos.clearSelection()
622637 tableInfos.updateUI()
623- steps.text = " "
638+ tableSteps.clearSelection()
639+ tableSteps.updateUI()
624640 details.isVisible = false
625641 errorToolbar.isVisible = false
626642 }
0 commit comments