Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
J
jadx
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open-source
jadx
Commits
3bc96719
Commit
3bc96719
authored
Jul 18, 2019
by
Skylot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
perf(gui): speed up line numbers rendering (#714)
parent
7fd959e6
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
79 additions
and
97 deletions
+79
-97
CodePanel.java
jadx-gui/src/main/java/jadx/gui/ui/codearea/CodePanel.java
+16
-17
LineNumbers.java
jadx-gui/src/main/java/jadx/gui/ui/codearea/LineNumbers.java
+63
-80
No files found.
jadx-gui/src/main/java/jadx/gui/ui/codearea/CodePanel.java
View file @
3bc96719
package
jadx
.
gui
.
ui
.
codearea
;
import
java.awt.
BorderLayout
;
import
java.awt.
*
;
import
java.awt.event.ActionEvent
;
import
java.awt.event.KeyEvent
;
import
javax.swing.AbstractAction
;
import
javax.swing.JPanel
;
import
javax.swing.JScrollPane
;
import
javax.swing.KeyStroke
;
import
javax.swing.*
;
import
org.fife.ui.rtextarea.RTextScrollPane
;
import
jadx.gui.treemodel.JNode
;
import
jadx.gui.treemodel.JResource
;
import
jadx.gui.ui.ContentPanel
;
import
jadx.gui.utils.UiUtils
;
...
...
@@ -21,21 +21,21 @@ public class CodePanel extends JPanel {
private
final
SearchBar
searchBar
;
private
final
AbstractCodeArea
codeArea
;
private
final
J
ScrollPane
codeScrollPane
;
private
final
RText
ScrollPane
codeScrollPane
;
@SuppressWarnings
(
"serial"
)
public
CodePanel
(
ContentPanel
contentPanel
,
AbstractCodeArea
codeArea
)
{
this
.
codeArea
=
codeArea
;
searchBar
=
new
SearchBar
(
codeArea
);
codeScrollPane
=
new
JScrollPane
(
codeArea
);
codeScrollPane
=
new
RTextScrollPane
(
codeArea
,
false
);
setLayout
(
new
BorderLayout
());
add
(
searchBar
,
BorderLayout
.
NORTH
);
add
(
codeScrollPane
,
BorderLayout
.
CENTER
);
initLineNumbers
();
KeyStroke
key
=
KeyStroke
.
getKeyStroke
(
KeyEvent
.
VK_F
,
UiUtils
.
ctrlButton
());
UiUtils
.
addKeyBinding
(
codeArea
,
key
,
"SearchAction"
,
new
AbstractAction
()
{
private
static
final
long
serialVersionUID
=
71338030532869694L
;
@Override
public
void
actionPerformed
(
ActionEvent
e
)
{
searchBar
.
toggle
();
...
...
@@ -50,20 +50,19 @@ public class CodePanel extends JPanel {
public
void
load
()
{
codeArea
.
load
();
initLineNumbers
();
}
private
void
initLineNumbers
()
{
// TODO: fix slow line rendering on big files
if
(
codeArea
.
getDocument
().
getLength
()
<=
100_000
)
{
LineNumbers
numbers
=
new
LineNumbers
(
codeArea
);
numbers
.
setUseSourceLines
(
isUseSourceLines
());
codeScrollPane
.
setRowHeaderView
(
numbers
);
}
LineNumbers
numbers
=
new
LineNumbers
(
codeArea
);
numbers
.
setUseSourceLines
(
isUseSourceLines
());
codeScrollPane
.
setRowHeaderView
(
numbers
);
}
private
boolean
isUseSourceLines
()
{
if
(
codeArea
.
getNode
()
instanceof
JResource
)
{
JResource
resNode
=
(
JResource
)
codeArea
.
getNode
();
JNode
node
=
codeArea
.
getNode
();
if
(
node
instanceof
JResource
)
{
JResource
resNode
=
(
JResource
)
node
;
return
!
resNode
.
getLineMapping
().
isEmpty
();
}
return
false
;
...
...
jadx-gui/src/main/java/jadx/gui/ui/codearea/LineNumbers.java
View file @
3bc96719
...
...
@@ -3,7 +3,6 @@ package jadx.gui.ui.codearea;
import
java.awt.*
;
import
java.awt.event.MouseAdapter
;
import
java.awt.event.MouseEvent
;
import
java.util.HashMap
;
import
java.util.Map
;
import
javax.swing.*
;
...
...
@@ -13,11 +12,7 @@ import javax.swing.border.EmptyBorder;
import
javax.swing.border.MatteBorder
;
import
javax.swing.event.CaretEvent
;
import
javax.swing.event.CaretListener
;
import
javax.swing.text.AttributeSet
;
import
javax.swing.text.BadLocationException
;
import
javax.swing.text.Element
;
import
javax.swing.text.StyleConstants
;
import
javax.swing.text.Utilities
;
import
org.fife.ui.rsyntaxtextarea.SyntaxScheme
;
import
org.fife.ui.rsyntaxtextarea.Token
;
...
...
@@ -36,19 +31,23 @@ public class LineNumbers extends JPanel implements CaretListener {
private
final
AbstractCodeArea
codeArea
;
private
boolean
useSourceLines
=
true
;
private
int
lastDigits
;
private
int
lastLine
;
private
Map
<
String
,
FontMetrics
>
fonts
;
private
transient
int
lastDigits
;
private
transient
int
lastLine
;
private
final
transient
Color
numberColor
;
private
final
transient
Color
normalNumColor
;
private
final
transient
Color
currentColor
;
private
final
transient
Border
border
;
private
transient
Insets
textAreaInsets
;
private
transient
Rectangle
visibleRect
=
new
Rectangle
();
public
LineNumbers
(
AbstractCodeArea
codeArea
)
{
this
.
codeArea
=
codeArea
;
setFont
(
codeArea
.
getFont
());
SyntaxScheme
syntaxScheme
=
codeArea
.
getSyntaxScheme
();
numberColor
=
syntaxScheme
.
getStyle
(
Token
.
LITERAL_NUMBER_DECIMAL_INT
).
foreground
;
normalNumColor
=
syntaxScheme
.
getStyle
(
Token
.
ANNOTATION
).
foreground
;
currentColor
=
syntaxScheme
.
getStyle
(
Token
.
LITERAL_STRING_DOUBLE_QUOTE
).
foreground
;
border
=
new
MatteBorder
(
0
,
0
,
0
,
1
,
syntaxScheme
.
getStyle
(
Token
.
COMMENT_MULTILINE
).
foreground
);
setBackground
(
codeArea
.
getBackground
());
...
...
@@ -78,7 +77,7 @@ public class LineNumbers extends JPanel implements CaretListener {
private
void
setPreferredWidth
()
{
Element
root
=
codeArea
.
getDocument
().
getDefaultRootElement
();
int
lines
=
root
.
getElementCount
();
int
digits
=
Math
.
max
(
String
.
valueOf
(
lines
).
length
(),
3
);
int
digits
=
Math
.
max
(
String
.
valueOf
(
lines
).
length
(),
4
);
if
(
lastDigits
!=
digits
)
{
lastDigits
=
digits
;
FontMetrics
fontMetrics
=
getFontMetrics
(
getFont
());
...
...
@@ -97,7 +96,13 @@ public class LineNumbers extends JPanel implements CaretListener {
@Override
public
void
paintComponent
(
Graphics
g
)
{
super
.
paintComponent
(
g
);
visibleRect
=
g
.
getClipBounds
(
visibleRect
);
if
(
visibleRect
==
null
)
{
visibleRect
=
getVisibleRect
();
}
if
(
visibleRect
==
null
)
{
return
;
}
applyRenderHints
(
g
);
Font
font
=
codeArea
.
getFont
();
...
...
@@ -110,26 +115,39 @@ public class LineNumbers extends JPanel implements CaretListener {
FontMetrics
fontMetrics
=
codeArea
.
getFontMetrics
(
font
);
Insets
insets
=
getInsets
();
int
availableWidth
=
size
.
width
-
insets
.
left
-
insets
.
right
;
Rectangle
clip
=
g
.
getClipBounds
();
int
rowStartOffset
=
codeArea
.
viewToModel
(
new
Point
(
0
,
clip
.
y
)
);
int
endOffset
=
codeArea
.
viewToModel
(
new
Point
(
0
,
clip
.
y
+
clip
.
height
)
);
int
availableWidth
=
size
.
width
-
insets
.
right
;
int
cellHeight
=
codeArea
.
getLineHeight
(
);
int
ascent
=
codeArea
.
getMaxAscent
(
);
while
(
rowStartOffset
<=
endOffset
)
{
textAreaInsets
=
codeArea
.
getInsets
(
textAreaInsets
);
if
(
visibleRect
.
y
<
textAreaInsets
.
top
)
{
visibleRect
.
height
-=
(
textAreaInsets
.
top
-
visibleRect
.
y
);
visibleRect
.
y
=
textAreaInsets
.
top
;
}
int
topLine
=
(
visibleRect
.
y
-
textAreaInsets
.
top
)
/
cellHeight
;
int
actualTopY
=
topLine
*
cellHeight
+
textAreaInsets
.
top
;
int
y
=
actualTopY
+
ascent
;
int
endY
=
visibleRect
.
y
+
visibleRect
.
height
+
ascent
;
Element
rootElement
=
codeArea
.
getDocument
().
getDefaultRootElement
();
int
currentLine
=
1
+
rootElement
.
getElementIndex
(
codeArea
.
getCaretPosition
());
int
lineNum
=
topLine
+
1
;
int
linesCount
=
codeArea
.
getLineCount
();
boolean
isCurLine
=
updateColor
(
g
,
false
,
true
);
while
(
y
<
endY
&&
lineNum
<=
linesCount
)
{
try
{
String
lineNumber
=
getTextLineNumber
(
rowStartOffset
);
if
(
lineNumber
!=
null
)
{
if
(
isCurrentLine
(
rowStartOffset
))
{
g
.
setColor
(
currentColor
);
}
else
{
g
.
setColor
(
numberColor
);
}
int
stringWidth
=
fontMetrics
.
stringWidth
(
lineNumber
);
int
x
=
availableWidth
-
stringWidth
+
insets
.
left
;
int
y
=
getOffsetY
(
rowStartOffset
,
fontMetrics
);
g
.
drawString
(
lineNumber
,
x
,
y
);
String
lineStr
=
getTextLineNumber
(
lineNum
);
if
(
lineStr
!=
null
)
{
isCurLine
=
updateColor
(
g
,
lineNum
==
currentLine
,
isCurLine
);
int
x
=
availableWidth
-
fontMetrics
.
stringWidth
(
lineStr
);
g
.
drawString
(
lineStr
,
x
,
y
);
}
else
if
(!
useSourceLines
)
{
break
;
}
rowStartOffset
=
Utilities
.
getRowEnd
(
codeArea
,
rowStartOffset
)
+
1
;
lineNum
++;
y
+=
cellHeight
;
}
catch
(
Exception
e
)
{
if
(
LOG
.
isDebugEnabled
())
{
LOG
.
debug
(
"Line numbers draw error"
,
e
);
...
...
@@ -139,6 +157,17 @@ public class LineNumbers extends JPanel implements CaretListener {
}
}
private
boolean
updateColor
(
Graphics
g
,
boolean
newCurLine
,
boolean
oldCurLine
)
{
if
(
oldCurLine
!=
newCurLine
)
{
if
(
newCurLine
)
{
g
.
setColor
(
currentColor
);
}
else
{
g
.
setColor
(
useSourceLines
?
numberColor
:
normalNumColor
);
}
}
return
newCurLine
;
}
private
void
applyRenderHints
(
Graphics
g
)
{
if
(
g
instanceof
Graphics2D
)
{
Graphics2D
g2d
=
(
Graphics2D
)
g
;
...
...
@@ -152,62 +181,16 @@ public class LineNumbers extends JPanel implements CaretListener {
}
}
private
boolean
isCurrentLine
(
int
rowStartOffset
)
{
int
caretPosition
=
codeArea
.
getCaretPosition
();
Element
root
=
codeArea
.
getDocument
().
getDefaultRootElement
();
return
root
.
getElementIndex
(
rowStartOffset
)
==
root
.
getElementIndex
(
caretPosition
);
}
@Nullable
protected
String
getTextLineNumber
(
int
rowStartOffset
)
{
Element
root
=
codeArea
.
getDocument
().
getDefaultRootElement
();
int
index
=
root
.
getElementIndex
(
rowStartOffset
);
Element
line
=
root
.
getElement
(
index
);
if
(
line
.
getStartOffset
()
!=
rowStartOffset
)
{
return
null
;
}
int
lineNumber
=
index
+
1
;
if
(
useSourceLines
)
{
Integer
sourceLine
=
codeArea
.
getSourceLine
(
lineNumber
);
if
(
sourceLine
==
null
)
{
return
null
;
}
return
String
.
valueOf
(
sourceLine
);
protected
String
getTextLineNumber
(
int
lineNumber
)
{
if
(!
useSourceLines
)
{
return
String
.
valueOf
(
lineNumber
);
}
return
String
.
valueOf
(
lineNumber
);
}
private
int
getOffsetY
(
int
rowStartOffset
,
FontMetrics
fontMetrics
)
throws
BadLocationException
{
Rectangle
r
=
codeArea
.
modelToView
(
rowStartOffset
);
if
(
r
==
null
)
{
throw
new
BadLocationException
(
"Can't get Y offset"
,
rowStartOffset
);
}
int
lineHeight
=
fontMetrics
.
getHeight
();
int
y
=
r
.
y
+
r
.
height
;
int
descent
=
0
;
if
(
r
.
height
==
lineHeight
)
{
descent
=
fontMetrics
.
getDescent
();
}
else
{
if
(
fonts
==
null
)
{
fonts
=
new
HashMap
<>();
}
Element
root
=
codeArea
.
getDocument
().
getDefaultRootElement
();
int
index
=
root
.
getElementIndex
(
rowStartOffset
);
Element
line
=
root
.
getElement
(
index
);
for
(
int
i
=
0
;
i
<
line
.
getElementCount
();
i
++)
{
Element
child
=
line
.
getElement
(
i
);
AttributeSet
as
=
child
.
getAttributes
();
String
fontFamily
=
(
String
)
as
.
getAttribute
(
StyleConstants
.
FontFamily
);
Integer
fontSize
=
(
Integer
)
as
.
getAttribute
(
StyleConstants
.
FontSize
);
String
key
=
fontFamily
+
fontSize
;
FontMetrics
fm
=
fonts
.
computeIfAbsent
(
key
,
k
->
{
Font
font
=
new
Font
(
fontFamily
,
Font
.
PLAIN
,
fontSize
);
return
codeArea
.
getFontMetrics
(
font
);
});
descent
=
Math
.
max
(
descent
,
fm
.
getDescent
());
}
Integer
sourceLine
=
codeArea
.
getSourceLine
(
lineNumber
);
if
(
sourceLine
==
null
)
{
return
null
;
}
return
y
-
descent
;
return
String
.
valueOf
(
sourceLine
)
;
}
@Override
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment