added undo/redu, clipboard
This commit is contained in:
parent
aac1531fae
commit
6f626b7607
@ -38,6 +38,7 @@ public class FileEditor extends JDialog {
|
|||||||
private JButton prevPageBtn = null;
|
private JButton prevPageBtn = null;
|
||||||
private JButton nextPageBtn = null;
|
private JButton nextPageBtn = null;
|
||||||
private JLabel pageOffsetLabel = null;
|
private JLabel pageOffsetLabel = null;
|
||||||
|
private javax.swing.undo.UndoManager undoManager;
|
||||||
|
|
||||||
public FileEditor(Window parent, File file, AppConfig config, boolean readOnly) {
|
public FileEditor(Window parent, File file, AppConfig config, boolean readOnly) {
|
||||||
super(parent, (readOnly ? "Prohlížeč - " : "Editor - ") + file.getName(), ModalityType.MODELESS);
|
super(parent, (readOnly ? "Prohlížeč - " : "Editor - ") + file.getName(), ModalityType.MODELESS);
|
||||||
@ -72,11 +73,11 @@ public class FileEditor extends JDialog {
|
|||||||
textArea.setTabSize(4);
|
textArea.setTabSize(4);
|
||||||
textArea.setEditable(!readOnly);
|
textArea.setEditable(!readOnly);
|
||||||
|
|
||||||
// V read-only režimu zajistit viditelnost kurzoru a možnost označování
|
// Undo/Redo support
|
||||||
if (readOnly) {
|
undoManager = new javax.swing.undo.UndoManager();
|
||||||
textArea.getCaret().setVisible(true);
|
textArea.getDocument().addUndoableEditListener(e -> {
|
||||||
textArea.setCaretColor(Color.BLACK);
|
undoManager.addEdit(e.getEdit());
|
||||||
}
|
});
|
||||||
|
|
||||||
// Sledování změn (pouze pro editovatelný režim)
|
// Sledování změn (pouze pro editovatelný režim)
|
||||||
if (!readOnly) {
|
if (!readOnly) {
|
||||||
@ -99,6 +100,12 @@ public class FileEditor extends JDialog {
|
|||||||
statusPanel.add(statusSelLabel, BorderLayout.EAST);
|
statusPanel.add(statusSelLabel, BorderLayout.EAST);
|
||||||
add(statusPanel, BorderLayout.SOUTH);
|
add(statusPanel, BorderLayout.SOUTH);
|
||||||
|
|
||||||
|
// Apply appearance settings (colors, contrast caret etc)
|
||||||
|
applyAppearance();
|
||||||
|
|
||||||
|
// Kontextové menu pro clipboard
|
||||||
|
setupContextMenu();
|
||||||
|
|
||||||
// Klávesové zkratky
|
// Klávesové zkratky
|
||||||
setupKeyBindings();
|
setupKeyBindings();
|
||||||
|
|
||||||
@ -112,6 +119,109 @@ public class FileEditor extends JDialog {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setupContextMenu() {
|
||||||
|
JPopupMenu popup = new JPopupMenu();
|
||||||
|
|
||||||
|
JMenuItem undoItem = new JMenuItem("Zpět");
|
||||||
|
undoItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_DOWN_MASK));
|
||||||
|
undoItem.addActionListener(e -> { if (undoManager.canUndo()) undoManager.undo(); });
|
||||||
|
|
||||||
|
JMenuItem redoItem = new JMenuItem("Znovu");
|
||||||
|
redoItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, InputEvent.CTRL_DOWN_MASK));
|
||||||
|
redoItem.addActionListener(e -> { if (undoManager.canRedo()) undoManager.redo(); });
|
||||||
|
|
||||||
|
popup.add(undoItem);
|
||||||
|
popup.add(redoItem);
|
||||||
|
popup.addSeparator();
|
||||||
|
|
||||||
|
JMenuItem cutItem = new JMenuItem(new javax.swing.text.DefaultEditorKit.CutAction());
|
||||||
|
cutItem.setText("Vyjmout");
|
||||||
|
cutItem.setMnemonic(KeyEvent.VK_X);
|
||||||
|
|
||||||
|
JMenuItem copyItem = new JMenuItem(new javax.swing.text.DefaultEditorKit.CopyAction());
|
||||||
|
copyItem.setText("Kopírovat");
|
||||||
|
copyItem.setMnemonic(KeyEvent.VK_C);
|
||||||
|
|
||||||
|
JMenuItem pasteItem = new JMenuItem(new javax.swing.text.DefaultEditorKit.PasteAction());
|
||||||
|
pasteItem.setText("Vložit");
|
||||||
|
pasteItem.setMnemonic(KeyEvent.VK_V);
|
||||||
|
|
||||||
|
popup.add(cutItem);
|
||||||
|
popup.add(copyItem);
|
||||||
|
popup.add(pasteItem);
|
||||||
|
popup.addSeparator();
|
||||||
|
|
||||||
|
JMenuItem selectAllItem = new JMenuItem("Vybrat vše");
|
||||||
|
selectAllItem.setMnemonic(KeyEvent.VK_A);
|
||||||
|
selectAllItem.addActionListener(e -> textArea.selectAll());
|
||||||
|
popup.add(selectAllItem);
|
||||||
|
|
||||||
|
popup.addPopupMenuListener(new javax.swing.event.PopupMenuListener() {
|
||||||
|
@Override
|
||||||
|
public void popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent e) {
|
||||||
|
boolean editable = textArea.isEditable();
|
||||||
|
undoItem.setEnabled(editable && undoManager.canUndo());
|
||||||
|
redoItem.setEnabled(editable && undoManager.canRedo());
|
||||||
|
cutItem.setEnabled(editable);
|
||||||
|
pasteItem.setEnabled(editable);
|
||||||
|
}
|
||||||
|
@Override public void popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent e) {}
|
||||||
|
@Override public void popupMenuCanceled(javax.swing.event.PopupMenuEvent e) {}
|
||||||
|
});
|
||||||
|
|
||||||
|
textArea.setComponentPopupMenu(popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyAppearance() {
|
||||||
|
Color bg = config.getBackgroundColor();
|
||||||
|
if (bg != null) {
|
||||||
|
boolean dark = isDark(bg);
|
||||||
|
// Apply to JTextArea
|
||||||
|
textArea.setBackground(bg);
|
||||||
|
textArea.setForeground(dark ? Color.WHITE : Color.BLACK);
|
||||||
|
textArea.setCaretColor(dark ? Color.WHITE : Color.BLACK);
|
||||||
|
|
||||||
|
// Apply to the rest of the components recursively
|
||||||
|
applyRecursiveColors(getContentPane(), bg, dark);
|
||||||
|
} else {
|
||||||
|
// Default colors - make sure caret is at least visible
|
||||||
|
Color defaultBg = textArea.getBackground();
|
||||||
|
if (defaultBg != null) {
|
||||||
|
boolean dark = isDark(defaultBg);
|
||||||
|
textArea.setCaretColor(dark ? Color.WHITE : Color.BLACK);
|
||||||
|
} else {
|
||||||
|
textArea.setCaretColor(Color.BLACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force caret visibility in read-only mode
|
||||||
|
if (readOnly) {
|
||||||
|
textArea.getCaret().setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyRecursiveColors(Container container, Color bg, boolean dark) {
|
||||||
|
if (container == null) return;
|
||||||
|
container.setBackground(bg);
|
||||||
|
for (Component c : container.getComponents()) {
|
||||||
|
if (c instanceof JPanel || c instanceof JScrollPane || c instanceof JViewport) {
|
||||||
|
c.setBackground(bg);
|
||||||
|
}
|
||||||
|
if (c instanceof JLabel) {
|
||||||
|
c.setForeground(dark ? Color.WHITE : Color.BLACK);
|
||||||
|
}
|
||||||
|
if (c instanceof Container) {
|
||||||
|
applyRecursiveColors((Container) c, bg, dark);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isDark(Color c) {
|
||||||
|
if (c == null) return false;
|
||||||
|
double darkness = 1 - (0.299 * c.getRed() + 0.587 * c.getGreen() + 0.114 * c.getBlue()) / 255;
|
||||||
|
return darkness >= 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
private void createMenuBar() {
|
private void createMenuBar() {
|
||||||
JMenuBar menuBar = new JMenuBar();
|
JMenuBar menuBar = new JMenuBar();
|
||||||
|
|
||||||
@ -136,6 +246,60 @@ public class FileEditor extends JDialog {
|
|||||||
|
|
||||||
menuBar.add(fileMenu);
|
menuBar.add(fileMenu);
|
||||||
|
|
||||||
|
// Menu Edit
|
||||||
|
JMenu editMenu = new JMenu("Edit");
|
||||||
|
editMenu.setMnemonic(java.awt.event.KeyEvent.VK_E);
|
||||||
|
|
||||||
|
JMenuItem undoItem = new JMenuItem("Zpět");
|
||||||
|
undoItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_DOWN_MASK));
|
||||||
|
undoItem.addActionListener(e -> { if (undoManager.canUndo()) undoManager.undo(); });
|
||||||
|
editMenu.add(undoItem);
|
||||||
|
|
||||||
|
JMenuItem redoItem = new JMenuItem("Znovu");
|
||||||
|
redoItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, InputEvent.CTRL_DOWN_MASK));
|
||||||
|
redoItem.addActionListener(e -> { if (undoManager.canRedo()) undoManager.redo(); });
|
||||||
|
editMenu.add(redoItem);
|
||||||
|
|
||||||
|
editMenu.addSeparator();
|
||||||
|
|
||||||
|
JMenuItem cutItem = new JMenuItem(new javax.swing.text.DefaultEditorKit.CutAction());
|
||||||
|
cutItem.setText("Vyjmout");
|
||||||
|
cutItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.CTRL_DOWN_MASK));
|
||||||
|
editMenu.add(cutItem);
|
||||||
|
|
||||||
|
JMenuItem copyItem = new JMenuItem(new javax.swing.text.DefaultEditorKit.CopyAction());
|
||||||
|
copyItem.setText("Kopírovat");
|
||||||
|
copyItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK));
|
||||||
|
editMenu.add(copyItem);
|
||||||
|
|
||||||
|
JMenuItem pasteItem = new JMenuItem(new javax.swing.text.DefaultEditorKit.PasteAction());
|
||||||
|
pasteItem.setText("Vložit");
|
||||||
|
pasteItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_DOWN_MASK));
|
||||||
|
editMenu.add(pasteItem);
|
||||||
|
|
||||||
|
editMenu.addSeparator();
|
||||||
|
|
||||||
|
JMenuItem selectAllItem = new JMenuItem("Vybrat vše");
|
||||||
|
selectAllItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.CTRL_DOWN_MASK));
|
||||||
|
selectAllItem.addActionListener(e -> textArea.selectAll());
|
||||||
|
editMenu.add(selectAllItem);
|
||||||
|
|
||||||
|
// Update menu items state when menu is selected
|
||||||
|
editMenu.addMenuListener(new javax.swing.event.MenuListener() {
|
||||||
|
@Override
|
||||||
|
public void menuSelected(javax.swing.event.MenuEvent e) {
|
||||||
|
boolean editable = textArea.isEditable();
|
||||||
|
undoItem.setEnabled(editable && undoManager.canUndo());
|
||||||
|
redoItem.setEnabled(editable && undoManager.canRedo());
|
||||||
|
cutItem.setEnabled(editable);
|
||||||
|
pasteItem.setEnabled(editable);
|
||||||
|
}
|
||||||
|
@Override public void menuDeselected(javax.swing.event.MenuEvent e) {}
|
||||||
|
@Override public void menuCanceled(javax.swing.event.MenuEvent e) {}
|
||||||
|
});
|
||||||
|
|
||||||
|
menuBar.add(editMenu);
|
||||||
|
|
||||||
// Menu Nastavení
|
// Menu Nastavení
|
||||||
JMenu settingsMenu = new JMenu("Nastavení");
|
JMenu settingsMenu = new JMenu("Nastavení");
|
||||||
settingsMenu.setMnemonic(java.awt.event.KeyEvent.VK_N);
|
settingsMenu.setMnemonic(java.awt.event.KeyEvent.VK_N);
|
||||||
@ -215,6 +379,21 @@ public class FileEditor extends JDialog {
|
|||||||
},
|
},
|
||||||
KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, 0),
|
KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, 0),
|
||||||
JComponent.WHEN_IN_FOCUSED_WINDOW);
|
JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||||
|
|
||||||
|
// Ctrl+Z - Undo
|
||||||
|
rootPane.registerKeyboardAction(e -> {
|
||||||
|
if (undoManager.canUndo()) undoManager.undo();
|
||||||
|
}, KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_DOWN_MASK), JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||||
|
|
||||||
|
// Ctrl+Y - Redo
|
||||||
|
rootPane.registerKeyboardAction(e -> {
|
||||||
|
if (undoManager.canRedo()) undoManager.redo();
|
||||||
|
}, KeyStroke.getKeyStroke(KeyEvent.VK_Y, InputEvent.CTRL_DOWN_MASK), JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||||
|
|
||||||
|
// Ctrl+Shift+Z - Redo (alternative shortcut)
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setHexMode(boolean on) {
|
private void setHexMode(boolean on) {
|
||||||
@ -256,6 +435,7 @@ public class FileEditor extends JDialog {
|
|||||||
textArea.setEditable(!readOnly);
|
textArea.setEditable(!readOnly);
|
||||||
textArea.setFont(config.getEditorFont());
|
textArea.setFont(config.getEditorFont());
|
||||||
}
|
}
|
||||||
|
applyAppearance();
|
||||||
updateStatus();
|
updateStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,6 +622,7 @@ public class FileEditor extends JDialog {
|
|||||||
textArea.setCaretPosition(0);
|
textArea.setCaretPosition(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (undoManager != null) undoManager.discardAllEdits();
|
||||||
modified = false;
|
modified = false;
|
||||||
updateTitle();
|
updateTitle();
|
||||||
updateStatus();
|
updateStatus();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user