19 package org.sleuthkit.autopsy.corecomponents;
21 import java.awt.Component;
22 import java.awt.Cursor;
24 import java.awt.event.ActionEvent;
25 import java.awt.event.ActionListener;
27 import java.io.IOException;
28 import java.nio.file.Paths;
29 import java.util.concurrent.ExecutionException;
30 import java.util.logging.Level;
32 import org.openide.util.NbBundle;
34 import javax.swing.JMenuItem;
35 import javax.swing.JOptionPane;
36 import javax.swing.SwingWorker;
37 import javax.swing.text.BadLocationException;
38 import javax.swing.text.Utilities;
39 import org.netbeans.api.progress.ProgressHandle;
40 import org.openide.nodes.Node;
41 import org.openide.util.NbBundle.Messages;
42 import org.openide.util.lookup.ServiceProvider;
58 @SuppressWarnings(
"PMD.SingularField")
59 @ServiceProvider(service = DataContentViewer.class, position = 1)
62 private static final long PAGE_LENGTH = 16384;
63 private final byte[] data =
new byte[(int) PAGE_LENGTH];
64 private static int currentPage = 1;
77 customizeComponents();
78 this.resetComponent();
79 logger.log(Level.INFO,
"Created HexView instance: " +
this);
83 outputTextArea.setComponentPopupMenu(rightClickMenu);
84 ActionListener actList =
new ActionListener() {
86 public void actionPerformed(ActionEvent e) {
87 JMenuItem jmi = (JMenuItem) e.getSource();
88 if (jmi.equals(copyMenuItem)) {
89 outputTextArea.copy();
90 }
else if (jmi.equals(selectAllMenuItem)) {
91 outputTextArea.selectAll();
95 copyMenuItem.addActionListener(actList);
96 selectAllMenuItem.addActionListener(actList);
104 @SuppressWarnings(
"unchecked")
106 private
void initComponents() {
108 rightClickMenu =
new javax.swing.JPopupMenu();
109 copyMenuItem =
new javax.swing.JMenuItem();
110 selectAllMenuItem =
new javax.swing.JMenuItem();
111 jScrollPane3 =
new javax.swing.JScrollPane();
112 outputTextArea =
new javax.swing.JTextArea();
113 jScrollPane2 =
new javax.swing.JScrollPane();
114 hexViewerPanel =
new javax.swing.JPanel();
115 totalPageLabel =
new javax.swing.JLabel();
116 ofLabel =
new javax.swing.JLabel();
117 currentPageLabel =
new javax.swing.JLabel();
118 pageLabel =
new javax.swing.JLabel();
119 prevPageButton =
new javax.swing.JButton();
120 nextPageButton =
new javax.swing.JButton();
121 pageLabel2 =
new javax.swing.JLabel();
122 goToPageTextField =
new javax.swing.JTextField();
123 goToPageLabel =
new javax.swing.JLabel();
124 goToOffsetLabel =
new javax.swing.JLabel();
125 goToOffsetTextField =
new javax.swing.JTextField();
126 launchHxDButton =
new javax.swing.JButton();
128 copyMenuItem.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.copyMenuItem.text"));
129 rightClickMenu.add(copyMenuItem);
131 selectAllMenuItem.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.selectAllMenuItem.text"));
132 rightClickMenu.add(selectAllMenuItem);
134 setPreferredSize(
new java.awt.Dimension(100, 58));
136 jScrollPane3.setPreferredSize(
new java.awt.Dimension(300, 33));
138 outputTextArea.setEditable(
false);
139 outputTextArea.setFont(
new Font(
"Monospaced", Font.PLAIN, 11));
140 outputTextArea.setTabSize(0);
141 outputTextArea.setInheritsPopupMenu(
true);
142 jScrollPane3.setViewportView(outputTextArea);
144 jScrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
145 jScrollPane2.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
147 totalPageLabel.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.totalPageLabel.text_1"));
149 ofLabel.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.ofLabel.text_1"));
151 currentPageLabel.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.currentPageLabel.text_1"));
152 currentPageLabel.setMaximumSize(
new java.awt.Dimension(18, 14));
153 currentPageLabel.setMinimumSize(
new java.awt.Dimension(18, 14));
155 pageLabel.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.pageLabel.text_1"));
156 pageLabel.setMaximumSize(
new java.awt.Dimension(33, 14));
157 pageLabel.setMinimumSize(
new java.awt.Dimension(33, 14));
159 prevPageButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_back.png")));
160 prevPageButton.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.prevPageButton.text"));
161 prevPageButton.setBorderPainted(
false);
162 prevPageButton.setContentAreaFilled(
false);
163 prevPageButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_back_disabled.png")));
164 prevPageButton.setMargin(
new java.awt.Insets(2, 0, 2, 0));
165 prevPageButton.setPreferredSize(
new java.awt.Dimension(23, 23));
166 prevPageButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_back_hover.png")));
167 prevPageButton.addActionListener(
new java.awt.event.ActionListener() {
168 public void actionPerformed(java.awt.event.ActionEvent evt) {
169 prevPageButtonActionPerformed(evt);
173 nextPageButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_forward.png")));
174 nextPageButton.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.nextPageButton.text"));
175 nextPageButton.setBorderPainted(
false);
176 nextPageButton.setContentAreaFilled(
false);
177 nextPageButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_forward_disabled.png")));
178 nextPageButton.setMargin(
new java.awt.Insets(2, 0, 2, 0));
179 nextPageButton.setPreferredSize(
new java.awt.Dimension(23, 23));
180 nextPageButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/corecomponents/btn_step_forward_hover.png")));
181 nextPageButton.addActionListener(
new java.awt.event.ActionListener() {
182 public void actionPerformed(java.awt.event.ActionEvent evt) {
183 nextPageButtonActionPerformed(evt);
187 pageLabel2.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.pageLabel2.text"));
188 pageLabel2.setMaximumSize(
new java.awt.Dimension(29, 14));
189 pageLabel2.setMinimumSize(
new java.awt.Dimension(29, 14));
191 goToPageTextField.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.goToPageTextField.text"));
192 goToPageTextField.addActionListener(
new java.awt.event.ActionListener() {
193 public void actionPerformed(java.awt.event.ActionEvent evt) {
194 goToPageTextFieldActionPerformed(evt);
198 goToPageLabel.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.goToPageLabel.text"));
200 goToOffsetLabel.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.goToOffsetLabel.text"));
202 goToOffsetTextField.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.goToOffsetTextField.text"));
203 goToOffsetTextField.addActionListener(
new java.awt.event.ActionListener() {
204 public void actionPerformed(java.awt.event.ActionEvent evt) {
205 goToOffsetTextFieldActionPerformed(evt);
209 launchHxDButton.setText(
org.openide.util.NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.launchHxDButton.text"));
210 launchHxDButton.addActionListener(
new java.awt.event.ActionListener() {
211 public void actionPerformed(java.awt.event.ActionEvent evt) {
212 launchHxDButtonActionPerformed(evt);
216 javax.swing.GroupLayout hexViewerPanelLayout =
new javax.swing.GroupLayout(hexViewerPanel);
217 hexViewerPanel.setLayout(hexViewerPanelLayout);
218 hexViewerPanelLayout.setHorizontalGroup(
219 hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
220 .addGroup(hexViewerPanelLayout.createSequentialGroup()
222 .addComponent(pageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
224 .addComponent(currentPageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
225 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
226 .addComponent(ofLabel)
227 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
228 .addComponent(totalPageLabel)
230 .addComponent(pageLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
231 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
232 .addComponent(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
234 .addComponent(nextPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
236 .addComponent(goToPageLabel)
237 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
238 .addComponent(goToPageTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)
240 .addComponent(goToOffsetLabel)
241 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
242 .addComponent(goToOffsetTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)
243 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
244 .addComponent(launchHxDButton)
245 .addContainerGap(146, Short.MAX_VALUE))
247 hexViewerPanelLayout.setVerticalGroup(
248 hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
249 .addGroup(hexViewerPanelLayout.createSequentialGroup()
250 .addGroup(hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
251 .addComponent(pageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
252 .addGroup(hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
253 .addComponent(currentPageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
254 .addComponent(ofLabel)
255 .addComponent(totalPageLabel))
256 .addComponent(pageLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
257 .addComponent(nextPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
258 .addComponent(prevPageButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
259 .addComponent(goToPageLabel)
260 .addComponent(goToPageTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
261 .addComponent(goToOffsetLabel)
262 .addGroup(hexViewerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
263 .addComponent(goToOffsetTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
264 .addComponent(launchHxDButton)))
270 jScrollPane2.setViewportView(hexViewerPanel);
272 javax.swing.GroupLayout layout =
new javax.swing.GroupLayout(
this);
273 this.setLayout(layout);
274 layout.setHorizontalGroup(
275 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
276 .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 827, Short.MAX_VALUE)
277 .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
279 layout.setVerticalGroup(
280 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
281 .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
282 .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
283 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
284 .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 239, Short.MAX_VALUE))
289 setDataViewByPageNumber(currentPage - 1);
290 goToPageTextField.setText(Integer.toString(currentPage));
294 setDataViewByPageNumber(currentPage + 1);
295 goToPageTextField.setText(Integer.toString(currentPage));
299 String pageNumberStr = goToPageTextField.getText();
302 pageNumber = Integer.parseInt(pageNumberStr);
303 }
catch (NumberFormatException ex) {
304 pageNumber = totalPages + 1;
306 if (pageNumber > totalPages || pageNumber < 1) {
307 JOptionPane.showMessageDialog(
this,
308 NbBundle.getMessage(
this.getClass(),
309 "DataContentViewerHex.goToPageTextField.msgDlg",
311 NbBundle.getMessage(
this.getClass(),
312 "DataContentViewerHex.goToPageTextField.err"),
313 JOptionPane.WARNING_MESSAGE);
316 setDataViewByPageNumber(pageNumber);
330 String userSelectedLine;
333 userSelectedLine = outputTextArea.getText().subSequence(
334 Utilities.getRowStart(outputTextArea, outputTextArea.getCaretPosition()),
335 Utilities.getRowEnd(outputTextArea, outputTextArea.getCaretPosition()))
338 String hexForUserSelectedLine = userSelectedLine.substring(0, userSelectedLine.indexOf(
':'));
340 return Long.decode(hexForUserSelectedLine) + userInput;
341 }
catch (BadLocationException | StringIndexOutOfBoundsException | NumberFormatException ex) {
350 if (goToOffsetTextField.getText().startsWith(
"+") || goToOffsetTextField.getText().startsWith(
"-")) {
351 offset = getOffsetRelativeToCaretPosition(Long.decode(goToOffsetTextField.getText()));
353 offset = Long.decode(goToOffsetTextField.getText());
355 }
catch (NumberFormatException ex) {
357 JOptionPane.showMessageDialog(
this, NbBundle.getMessage(
this.getClass(),
"DataContentViewerHex.goToOffsetTextField.msgDlg", goToOffsetTextField.getText()));
362 setDataViewByOffset(offset);
364 outputTextArea.setText(NbBundle.getMessage(
DataContentViewerHex.class,
"DataContentViewerHex.setDataView.invalidOffset.negativeOffsetValue"));
368 @NbBundle.Messages({
"DataContentViewerHex.launchError=Unable to launch HxD Editor. "
369 +
"Please specify the HxD install location in Tools -> Options -> External Viewer",
370 "DataContentViewerHex.copyingFile=Copying file to open in HxD..."})
381 private boolean wasCancelled =
false;
385 ProgressHandle progress = ProgressHandle.createHandle(DataContentViewerHex_copyingFile(), () -> {
394 if (!HxDExecutable.exists() || !HxDExecutable.canExecute()) {
395 JOptionPane.showMessageDialog(null, DataContentViewerHex_launchError());
400 File tempFile = Paths.get(tempDirectory,
413 ProcessBuilder launchHxDExecutable =
new ProcessBuilder();
414 launchHxDExecutable.command(String.format(
"\"%s\" \"%s\"",
415 HxDExecutable.getAbsolutePath(),
416 tempFile.getAbsolutePath()));
417 launchHxDExecutable.start();
418 }
catch (IOException ex) {
419 logger.log(Level.WARNING,
"Unsuccessful attempt to launch HxD", ex);
420 JOptionPane.showMessageDialog(null, DataContentViewerHex_launchError());
424 logger.log(Level.SEVERE,
"Unable to copy file into temp directory", ex);
425 JOptionPane.showMessageDialog(null, DataContentViewerHex_launchError());
466 launchWorker(dataSource, (page - 1) * PAGE_LENGTH, page);
475 launchWorker(dataSource, offset, (
int) (offset / PAGE_LENGTH) + 1);
479 "DataContentViewerHex_loading_text=Loading hex from file..."
490 if (this.dataSource == null) {
494 worker =
new HexWorker(source, offset, page);
495 setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
496 outputTextArea.setText(Bundle.DataContentViewerHex_loading_text());
502 if (worker != null) {
509 if ((selectedNode == null)) {
514 if (content == null) {
518 dataSource = content;
520 if (dataSource.getSize() > 0) {
521 totalPages = Math.round((dataSource.getSize() - 1) / PAGE_LENGTH) + 1;
523 totalPageLabel.setText(Integer.toString(totalPages));
525 this.setDataViewByPageNumber(1);
530 return NbBundle.getMessage(this.getClass(),
"DataContentViewerHex.title");
535 return NbBundle.getMessage(this.getClass(),
"DataContentViewerHex.toolTip");
547 this.dataSource = null;
548 currentPageLabel.setText(
"");
549 totalPageLabel.setText(
"");
550 outputTextArea.setText(
"");
551 setComponentsVisibility(
false);
560 currentPageLabel.setVisible(isVisible);
561 totalPageLabel.setVisible(isVisible);
562 ofLabel.setVisible(isVisible);
563 prevPageButton.setVisible(isVisible);
564 nextPageButton.setVisible(isVisible);
565 pageLabel.setVisible(isVisible);
566 pageLabel2.setVisible(isVisible);
567 goToPageTextField.setVisible(isVisible);
568 goToPageLabel.setVisible(isVisible);
569 goToOffsetTextField.setVisible(isVisible);
570 goToOffsetLabel.setVisible(isVisible);
571 launchHxDButton.setVisible(isVisible);
580 return content != null && !(content instanceof BlackboardArtifact) && content.getSize() > 0;
596 private class HexWorker extends SwingWorker<String, Void> {
598 private final byte[] data =
new byte[(int) PAGE_LENGTH];
602 private String errorText =
"";
604 HexWorker(Content content,
long offset,
int newCurrentPage) {
605 this.content = content;
606 this.offset = offset;
607 this.newCurrentPage = newCurrentPage;
613 if (content.getSize() > 0) {
615 bytesRead = content.read(data, offset, PAGE_LENGTH);
616 }
catch (TskCoreException ex) {
617 errorText = NbBundle.getMessage(this.getClass(),
"DataContentViewerHex.setDataView.errorText", offset,
618 offset + PAGE_LENGTH);
619 logger.log(Level.WARNING,
"Error while trying to show the hex content.", ex);
624 if (bytesRead <= 0) {
625 errorText = NbBundle.getMessage(this.getClass(),
"DataContentViewerHex.setDataView.errorText", offset,
626 offset + PAGE_LENGTH);
629 if (errorText.isEmpty()) {
630 int showLength = bytesRead < PAGE_LENGTH ? bytesRead : (int) PAGE_LENGTH;
645 outputTextArea.setText(text);
648 if ((errorText.isEmpty()) && (newCurrentPage < totalPages)) {
649 nextPageButton.setEnabled(
true);
651 nextPageButton.setEnabled(
false);
654 if ((errorText.isEmpty()) && (newCurrentPage > 1)) {
655 prevPageButton.setEnabled(
true);
657 prevPageButton.setEnabled(
false);
660 currentPageLabel.setText(Integer.toString(newCurrentPage));
661 setComponentsVisibility(
true);
662 outputTextArea.setCaretPosition(0);
663 goToPageTextField.setText(Integer.toString(newCurrentPage));
664 currentPage = newCurrentPage;
665 setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
667 }
catch (InterruptedException | ExecutionException ex) {
668 logger.log(Level.SEVERE, String.format(
"Failed to get hex data from content (%d)", content.getId()), ex);
javax.swing.JScrollPane jScrollPane2
static Content getDefaultContent(Node node)
javax.swing.JButton launchHxDButton
void setNode(Node selectedNode)
javax.swing.JLabel currentPageLabel
javax.swing.JPopupMenu rightClickMenu
void setComponentsVisibility(boolean isVisible)
javax.swing.JButton prevPageButton
static String getExternalHexEditorPath()
int isPreferred(Node node)
String getTempDirectory()
javax.swing.JTextField goToOffsetTextField
javax.swing.JLabel goToPageLabel
javax.swing.JTextField goToPageTextField
static< T > long writeToFile(Content content, java.io.File outputFile, ProgressHandle progress, Future< T > worker, boolean source)
void goToOffsetTextFieldActionPerformed(java.awt.event.ActionEvent evt)
boolean isSupported(Node node)
void launchWorker(Content source, long offset, int page)
javax.swing.JMenuItem copyMenuItem
long getOffsetRelativeToCaretPosition(Long userInput)
void goToPageTextFieldActionPerformed(java.awt.event.ActionEvent evt)
void setDataViewByOffset(long offset)
static String byteArrayToHex(byte[] array, int length, long arrayOffset, Font font)
void launchHxDButtonActionPerformed(java.awt.event.ActionEvent evt)
javax.swing.JPanel hexViewerPanel
void setDataViewByPageNumber(int page)
javax.swing.JTextArea outputTextArea
javax.swing.JButton nextPageButton
static String escapeFileName(String fileName)
javax.swing.JMenuItem selectAllMenuItem
synchronized static Logger getLogger(String name)
javax.swing.JLabel goToOffsetLabel
javax.swing.JLabel ofLabel
static Case getCurrentCaseThrows()
void prevPageButtonActionPerformed(java.awt.event.ActionEvent evt)
javax.swing.JLabel totalPageLabel
javax.swing.JLabel pageLabel2
javax.swing.JScrollPane jScrollPane3
javax.swing.JLabel pageLabel
void nextPageButtonActionPerformed(java.awt.event.ActionEvent evt)
DataContentViewer createInstance()
void customizeComponents()