Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/SourceCodePanel.java
41161 views
1
/*
2
* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
25
package sun.jvm.hotspot.ui;
26
27
import java.awt.*;
28
import java.awt.event.*;
29
import java.awt.geom.Rectangle2D;
30
import java.io.*;
31
import java.net.*;
32
import java.util.*;
33
import javax.swing.*;
34
import javax.swing.text.BadLocationException;
35
36
/** Panel supporting loading of and scrolling through source code.
37
Contains convenience routines for implementing the Editor
38
interface. */
39
40
public class SourceCodePanel extends JPanel {
41
private JTextArea source;
42
private RowHeader header;
43
private String filename;
44
// Amount of white space between edges, line numbers and icons
45
private static final int LINE_NO_SPACE = 4;
46
// Size of icons in resources directory
47
private static final int ICON_SIZE = 12;
48
// Icons used in panel drawing
49
private static Icon topFrameCurLine;
50
private static Icon lowerFrameCurLine;
51
private static Icon breakpoint;
52
// State
53
private int highlightedLine = -1;
54
private Set<Integer> breakpoints = new HashSet<>(); // Zero-based lines internally
55
// Parent Editor container and EditorCommands object for setting breakpoints
56
private EditorCommands comm;
57
private Editor parent;
58
59
/** Support for displaying icons and line numbers in row header of
60
scroll pane */
61
class RowHeader extends JPanel {
62
private JViewport view;
63
private boolean showLineNumbers;
64
private int width;
65
private int rowHeight;
66
private boolean initted;
67
68
public RowHeader() {
69
super();
70
initted = true;
71
addHierarchyBoundsListener(new HierarchyBoundsAdapter() {
72
public void ancestorResized(HierarchyEvent e) {
73
recomputeSize();
74
}
75
});
76
}
77
78
public void paint(Graphics g) {
79
super.paint(g);
80
if (getShowLineNumbers()) {
81
// Visible region of header panel, in coordinate system of the
82
// panel, is provided by clip bounds of Graphics object. This
83
// is used to figure out which line numbers to draw.
84
Rectangle clip = g.getClipBounds();
85
// To avoid missing lines, round down starting line number and
86
// round up ending line number
87
int start = clip.y / rowHeight;
88
int end = start + (clip.height + (rowHeight - 1)) / rowHeight;
89
// Draw these line numbers, right justified to look better
90
FontMetrics fm = getFontMetrics(getFont());
91
int ascent = fm.getMaxAscent(); // Causes proper alignment -- trial-and-error
92
for (int i = start; i <= end; i++) {
93
// Line numbers are 1-based
94
String str = Integer.toString(i + 1);
95
int strWidth = GraphicsUtilities.getStringWidth(str, fm);
96
g.drawString(str, width - strWidth - LINE_NO_SPACE, ascent + rowHeight * i);
97
98
// Draw breakpoint if necessary
99
if (breakpoints.contains(i)) {
100
breakpoint.paintIcon(this, g, LINE_NO_SPACE, rowHeight * i);
101
}
102
103
// Draw current line icon if necessary
104
if (i == highlightedLine) {
105
// FIXME: use correct icon (not always topmost frame)
106
topFrameCurLine.paintIcon(this, g, LINE_NO_SPACE, rowHeight * i);
107
}
108
}
109
}
110
}
111
112
public boolean getShowLineNumbers() {
113
return showLineNumbers;
114
}
115
116
public void setShowLineNumbers(boolean val) {
117
if (val != showLineNumbers) {
118
showLineNumbers = val;
119
recomputeSize();
120
// Force re-layout
121
invalidate();
122
validate();
123
}
124
}
125
126
public void setFont(Font f) {
127
super.setFont(f);
128
rowHeight = getFontMetrics(f).getHeight();
129
recomputeSize();
130
}
131
132
void setViewport(JViewport view) {
133
this.view = view;
134
}
135
136
void recomputeSize() {
137
if (!initted) return;
138
if (view == null) return;
139
width = ICON_SIZE + 2 * LINE_NO_SPACE;
140
try {
141
int numLines = 1 + source.getLineOfOffset(source.getDocument().getEndPosition().getOffset() - 1);
142
String str = Integer.toString(numLines);
143
if (getShowLineNumbers()) {
144
// Compute width based on whether we are drawing line numbers
145
width += GraphicsUtilities.getStringWidth(str, getFontMetrics(getFont())) + LINE_NO_SPACE;
146
}
147
// FIXME: add on width for all icons (breakpoint, current line,
148
// current line in caller frame)
149
Dimension d = new Dimension(width, numLines * getFontMetrics(getFont()).getHeight());
150
setSize(d);
151
setPreferredSize(d);
152
} catch (BadLocationException e) {
153
e.printStackTrace();
154
}
155
}
156
}
157
158
public SourceCodePanel() {
159
maybeLoadIcons();
160
161
// Build user interface
162
setLayout(new BorderLayout());
163
source = new JTextArea();
164
source.setEditable(false);
165
source.getCaret().setVisible(true);
166
header = new RowHeader();
167
header.setShowLineNumbers(true);
168
JScrollPane scroller = new JScrollPane(source);
169
JViewport rowView = new JViewport();
170
rowView.setView(header);
171
header.setViewport(rowView);
172
rowView.setScrollMode(JViewport.SIMPLE_SCROLL_MODE);
173
scroller.setRowHeader(rowView);
174
add(scroller, BorderLayout.CENTER);
175
// Reset font now that header and source are present
176
setFont(getFont());
177
178
source.addFocusListener(new FocusAdapter() {
179
public void focusGained(FocusEvent e) {
180
source.getCaret().setVisible(true);
181
}
182
});
183
184
source.addKeyListener(new KeyAdapter() {
185
public void keyPressed(KeyEvent e) {
186
if (e.getKeyCode() == KeyEvent.VK_F9) {
187
int lineNo = getCurrentLineNumber();
188
// Only the debugger can figure out whether we are setting
189
// or clearing a breakpoint, since it has the debug
190
// information available and knows whether we're on a
191
// valid line
192
comm.toggleBreakpointAtLine(parent, lineNo);
193
}
194
}
195
});
196
197
}
198
199
public void setFont(Font f) {
200
super.setFont(f);
201
if (source != null) {
202
source.setFont(f);
203
}
204
if (header != null) {
205
header.setFont(f);
206
}
207
}
208
209
public boolean getShowLineNumbers() {
210
return header.getShowLineNumbers();
211
}
212
213
public void setShowLineNumbers(boolean val) {
214
header.setShowLineNumbers(val);
215
}
216
217
public boolean openFile(String filename) {
218
try {
219
this.filename = filename;
220
File file = new File(filename);
221
int len = (int) file.length();
222
StringBuilder buf = new StringBuilder(len); // Approximation
223
char[] tmp = new char[4096];
224
FileReader in = new FileReader(file);
225
int res = 0;
226
do {
227
res = in.read(tmp, 0, tmp.length);
228
if (res >= 0) {
229
buf.append(tmp, 0, res);
230
}
231
} while (res != -1);
232
in.close();
233
String text = buf.toString();
234
source.setText(text);
235
header.recomputeSize();
236
return true;
237
} catch (IOException e) {
238
return false;
239
}
240
}
241
242
public String getSourceFileName() {
243
return filename;
244
}
245
246
/** Line number is one-based */
247
public int getCurrentLineNumber() {
248
try {
249
return 1 + source.getLineOfOffset(source.getCaretPosition());
250
} catch (BadLocationException e) {
251
return 0;
252
}
253
}
254
255
/** Line number is one-based */
256
public void showLineNumber(int lineNo) {
257
try {
258
int offset = source.getLineStartOffset(lineNo - 1);
259
Rectangle2D rect2d = source.modelToView2D(offset);
260
if (rect2d == null) {
261
return;
262
}
263
Rectangle rect = new Rectangle((int) rect2d.getX(), (int) rect2d.getY(),
264
(int) rect2d.getWidth(), (int) rect2d.getHeight());
265
source.scrollRectToVisible(rect);
266
} catch (BadLocationException e) {
267
e.printStackTrace();
268
}
269
}
270
271
/** Line number is one-based */
272
public void highlightLineNumber(int lineNo) {
273
highlightedLine = lineNo - 1;
274
}
275
276
public void showBreakpointAtLine(int lineNo) { breakpoints.add(lineNo - 1); repaint(); }
277
public boolean hasBreakpointAtLine(int lineNo){ return breakpoints.contains(lineNo - 1); }
278
public void clearBreakpointAtLine(int lineNo) { breakpoints.remove(lineNo - 1); repaint(); }
279
public void clearBreakpoints() { breakpoints.clear(); repaint(); }
280
281
public void setEditorCommands(EditorCommands comm, Editor parent) {
282
this.comm = comm;
283
this.parent = parent;
284
}
285
286
public void requestFocus() {
287
source.requestFocus();
288
}
289
290
//----------------------------------------------------------------------
291
// Internals only below this point
292
//
293
294
private void maybeLoadIcons() {
295
if (topFrameCurLine == null) {
296
topFrameCurLine = loadIcon("resources/arrow.png");
297
lowerFrameCurLine = loadIcon("resources/triangle.png");
298
breakpoint = loadIcon("resources/breakpoint.png");
299
}
300
}
301
302
private Icon loadIcon(String which) {
303
URL url = getClass().getResource(which);
304
return new ImageIcon(url);
305
}
306
}
307
308