search in file
This commit is contained in:
parent
68fe5ca0c6
commit
26d62d2902
@ -35,10 +35,17 @@ public class FileEditor extends JDialog {
|
||||
// Allow loading entire file into memory up to this limit (100 MB)
|
||||
private final long maxFullLoadBytes = 100L * 1024L * 1024L; // 100 MB
|
||||
private JPanel hexControlPanel = null;
|
||||
private JPanel northPanel = null;
|
||||
private JButton prevPageBtn = null;
|
||||
private JButton nextPageBtn = null;
|
||||
private JLabel pageOffsetLabel = null;
|
||||
private javax.swing.undo.UndoManager undoManager;
|
||||
|
||||
// Search support
|
||||
private JPanel searchPanel;
|
||||
private JTextField searchField;
|
||||
private JLabel searchStatusLabel;
|
||||
private static String lastSearchValue = "";
|
||||
|
||||
public FileEditor(Window parent, File file, AppConfig config, boolean readOnly) {
|
||||
super(parent, (readOnly ? "Prohlížeč - " : "Editor - ") + file.getName(), ModalityType.MODELESS);
|
||||
@ -61,9 +68,164 @@ public class FileEditor extends JDialog {
|
||||
});
|
||||
}
|
||||
|
||||
private void initSearchPanel() {
|
||||
searchPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 2));
|
||||
searchPanel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.GRAY));
|
||||
|
||||
searchField = new JTextField(20);
|
||||
searchField.addActionListener(e -> findNext());
|
||||
|
||||
JButton nextBtn = new JButton("Dále");
|
||||
nextBtn.addActionListener(e -> findNext());
|
||||
|
||||
JButton prevBtn = new JButton("Zpět");
|
||||
prevBtn.addActionListener(e -> findPrevious());
|
||||
|
||||
JButton closeBtn = new JButton("X");
|
||||
closeBtn.setMargin(new Insets(0, 5, 0, 5));
|
||||
closeBtn.addActionListener(e -> hideSearchPanel());
|
||||
|
||||
searchStatusLabel = new JLabel("");
|
||||
|
||||
searchPanel.add(new JLabel("Hledat:"));
|
||||
searchPanel.add(searchField);
|
||||
searchPanel.add(nextBtn);
|
||||
searchPanel.add(prevBtn);
|
||||
searchPanel.add(closeBtn);
|
||||
searchPanel.add(searchStatusLabel);
|
||||
|
||||
searchPanel.setVisible(false);
|
||||
}
|
||||
|
||||
private void showSearchPanel() {
|
||||
searchPanel.setVisible(true);
|
||||
String selection = textArea.getSelectedText();
|
||||
if (selection != null && !selection.isEmpty() && !selection.contains("\n")) {
|
||||
searchField.setText(selection);
|
||||
lastSearchValue = selection;
|
||||
} else if (!lastSearchValue.isEmpty()) {
|
||||
searchField.setText(lastSearchValue);
|
||||
} else if (config != null) {
|
||||
java.util.List<String> hist = config.getContentSearchHistory();
|
||||
if (hist != null && !hist.isEmpty()) {
|
||||
lastSearchValue = hist.get(0);
|
||||
searchField.setText(lastSearchValue);
|
||||
}
|
||||
}
|
||||
|
||||
searchField.requestFocusInWindow();
|
||||
searchField.selectAll();
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
searchField.requestFocusInWindow();
|
||||
searchField.selectAll();
|
||||
});
|
||||
|
||||
if (northPanel != null) {
|
||||
northPanel.revalidate();
|
||||
northPanel.repaint();
|
||||
}
|
||||
revalidate();
|
||||
}
|
||||
|
||||
private void hideSearchPanel() {
|
||||
searchPanel.setVisible(false);
|
||||
textArea.requestFocusInWindow();
|
||||
revalidate();
|
||||
}
|
||||
|
||||
private void findNext() {
|
||||
String text = searchField.getText();
|
||||
if (text.isEmpty()) text = lastSearchValue;
|
||||
if (text == null || text.isEmpty()) return;
|
||||
lastSearchValue = text;
|
||||
updateSearchHistory(text);
|
||||
|
||||
if (searchField.getText().isEmpty()) searchField.setText(text);
|
||||
|
||||
String content = textArea.getText();
|
||||
int start = textArea.getCaretPosition();
|
||||
|
||||
// If we have a selection that matches, start after it
|
||||
if (textArea.getSelectionEnd() > textArea.getSelectionStart()) {
|
||||
if (content.substring(textArea.getSelectionStart(), textArea.getSelectionEnd()).equalsIgnoreCase(text)) {
|
||||
start = textArea.getSelectionEnd();
|
||||
}
|
||||
}
|
||||
|
||||
int idx = content.toLowerCase().indexOf(text.toLowerCase(), start);
|
||||
if (idx == -1) {
|
||||
// wrap around
|
||||
idx = content.toLowerCase().indexOf(text.toLowerCase(), 0);
|
||||
}
|
||||
|
||||
if (idx != -1) {
|
||||
textArea.setSelectionStart(idx);
|
||||
textArea.setSelectionEnd(idx + text.length());
|
||||
textArea.getCaret().setSelectionVisible(true);
|
||||
try {
|
||||
Rectangle rect = textArea.modelToView2D(idx).getBounds();
|
||||
textArea.scrollRectToVisible(rect);
|
||||
} catch (Exception ignore) {}
|
||||
searchStatusLabel.setText("");
|
||||
} else {
|
||||
searchStatusLabel.setText("Nenalezeno");
|
||||
}
|
||||
}
|
||||
|
||||
private void findPrevious() {
|
||||
String text = searchField.getText();
|
||||
if (text.isEmpty()) text = lastSearchValue;
|
||||
if (text == null || text.isEmpty()) return;
|
||||
lastSearchValue = text;
|
||||
updateSearchHistory(text);
|
||||
|
||||
if (searchField.getText().isEmpty()) searchField.setText(text);
|
||||
|
||||
String content = textArea.getText();
|
||||
int start = textArea.getSelectionStart() - 1;
|
||||
if (start < 0) start = content.length() - 1;
|
||||
|
||||
int idx = content.toLowerCase().lastIndexOf(text.toLowerCase(), start);
|
||||
if (idx == -1) {
|
||||
// wrap around
|
||||
idx = content.toLowerCase().lastIndexOf(text.toLowerCase(), content.length() - 1);
|
||||
}
|
||||
|
||||
if (idx != -1) {
|
||||
textArea.setSelectionStart(idx);
|
||||
textArea.setSelectionEnd(idx + text.length());
|
||||
textArea.getCaret().setSelectionVisible(true);
|
||||
try {
|
||||
Rectangle rect = textArea.modelToView2D(idx).getBounds();
|
||||
textArea.scrollRectToVisible(rect);
|
||||
} catch (Exception ignore) {}
|
||||
searchStatusLabel.setText("");
|
||||
} else {
|
||||
searchStatusLabel.setText("Nenalezeno");
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSearchHistory(String text) {
|
||||
if (config == null || text == null || text.isEmpty()) return;
|
||||
java.util.List<String> hist = new java.util.ArrayList<>(config.getContentSearchHistory());
|
||||
hist.remove(text);
|
||||
hist.add(0, text);
|
||||
if (hist.size() > 20) hist = hist.subList(0, 20);
|
||||
config.saveContentSearchHistory(hist);
|
||||
config.saveConfig();
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
northPanel = new JPanel();
|
||||
northPanel.setLayout(new BoxLayout(northPanel, BoxLayout.Y_AXIS));
|
||||
add(northPanel, BorderLayout.NORTH);
|
||||
|
||||
initSearchPanel();
|
||||
northPanel.add(searchPanel);
|
||||
|
||||
// Menu bar
|
||||
createMenuBar();
|
||||
|
||||
@ -284,6 +446,18 @@ public class FileEditor extends JDialog {
|
||||
selectAllItem.addActionListener(e -> textArea.selectAll());
|
||||
editMenu.add(selectAllItem);
|
||||
|
||||
editMenu.addSeparator();
|
||||
|
||||
JMenuItem findItem = new JMenuItem("Hledat...");
|
||||
findItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.CTRL_DOWN_MASK));
|
||||
findItem.addActionListener(e -> showSearchPanel());
|
||||
editMenu.add(findItem);
|
||||
|
||||
JMenuItem findNextItem = new JMenuItem("Hledat další");
|
||||
findNextItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F3, 0));
|
||||
findNextItem.addActionListener(e -> findNext());
|
||||
editMenu.add(findNextItem);
|
||||
|
||||
// Update menu items state when menu is selected
|
||||
editMenu.addMenuListener(new javax.swing.event.MenuListener() {
|
||||
@Override
|
||||
@ -352,8 +526,14 @@ public class FileEditor extends JDialog {
|
||||
JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||
}
|
||||
|
||||
// ESC - Zavřít
|
||||
rootPane.registerKeyboardAction(e -> closeEditor(),
|
||||
// ESC - Zavřít nebo skrýt hledání
|
||||
rootPane.registerKeyboardAction(e -> {
|
||||
if (searchPanel.isVisible()) {
|
||||
hideSearchPanel();
|
||||
} else {
|
||||
closeEditor();
|
||||
}
|
||||
},
|
||||
KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
|
||||
JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||
|
||||
@ -394,6 +574,19 @@ public class FileEditor extends JDialog {
|
||||
rootPane.registerKeyboardAction(e -> {
|
||||
if (undoManager.canRedo()) undoManager.redo();
|
||||
}, KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK), JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||
|
||||
// Hledání
|
||||
rootPane.registerKeyboardAction(e -> showSearchPanel(),
|
||||
KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.CTRL_DOWN_MASK),
|
||||
JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||
|
||||
rootPane.registerKeyboardAction(e -> findNext(),
|
||||
KeyStroke.getKeyStroke(KeyEvent.VK_F3, 0),
|
||||
JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||
|
||||
rootPane.registerKeyboardAction(e -> findPrevious(),
|
||||
KeyStroke.getKeyStroke(KeyEvent.VK_F3, InputEvent.SHIFT_DOWN_MASK),
|
||||
JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||
}
|
||||
|
||||
private void setHexMode(boolean on) {
|
||||
@ -422,9 +615,10 @@ public class FileEditor extends JDialog {
|
||||
textArea.setFont(new Font("Monospaced", Font.PLAIN, textArea.getFont().getSize()));
|
||||
ensureHexControls();
|
||||
if (hexControlPanel.getParent() == null) {
|
||||
add(hexControlPanel, BorderLayout.NORTH);
|
||||
northPanel.add(hexControlPanel);
|
||||
}
|
||||
hexControlPanel.setVisible(true);
|
||||
northPanel.revalidate();
|
||||
} else {
|
||||
// switch back to text view if possible
|
||||
// close RA if open
|
||||
@ -434,6 +628,10 @@ public class FileEditor extends JDialog {
|
||||
loadFile();
|
||||
textArea.setEditable(!readOnly);
|
||||
textArea.setFont(config.getEditorFont());
|
||||
if (hexControlPanel != null) {
|
||||
hexControlPanel.setVisible(false);
|
||||
northPanel.revalidate();
|
||||
}
|
||||
}
|
||||
applyAppearance();
|
||||
updateStatus();
|
||||
@ -593,8 +791,9 @@ public class FileEditor extends JDialog {
|
||||
pageOffsetBytes = 0L;
|
||||
loadHexPage();
|
||||
ensureHexControls();
|
||||
if (hexControlPanel.getParent() == null) add(hexControlPanel, BorderLayout.NORTH);
|
||||
if (hexControlPanel.getParent() == null) northPanel.add(hexControlPanel);
|
||||
hexControlPanel.setVisible(true);
|
||||
northPanel.revalidate();
|
||||
textArea.setEditable(false);
|
||||
textArea.setFont(new Font("Monospaced", Font.PLAIN, textArea.getFont().getSize()));
|
||||
hexMode = true;
|
||||
@ -608,8 +807,9 @@ public class FileEditor extends JDialog {
|
||||
textArea.setEditable(false);
|
||||
textArea.setFont(new Font("Monospaced", Font.PLAIN, textArea.getFont().getSize()));
|
||||
ensureHexControls();
|
||||
if (hexControlPanel.getParent() == null) add(hexControlPanel, BorderLayout.NORTH);
|
||||
if (hexControlPanel.getParent() == null) northPanel.add(hexControlPanel);
|
||||
hexControlPanel.setVisible(true);
|
||||
northPanel.revalidate();
|
||||
} else if (hexMode) {
|
||||
buildHexViewText(0L);
|
||||
} else {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user