diff --git a/src/main/java/cz/kamma/kfmanager/ui/FileEditor.java b/src/main/java/cz/kamma/kfmanager/ui/FileEditor.java index 7a55b65..e0ff397 100644 --- a/src/main/java/cz/kamma/kfmanager/ui/FileEditor.java +++ b/src/main/java/cz/kamma/kfmanager/ui/FileEditor.java @@ -16,6 +16,7 @@ import java.nio.file.Files; */ public class FileEditor extends JDialog { private JTextArea textArea; + private JScrollPane scrollPane; private File file; private AppConfig config; private boolean modified = false; @@ -54,10 +55,14 @@ public class FileEditor extends JDialog { this.readOnly = readOnly; initComponents(); - loadFile(); + loadFile(); + + // Final window positioning and visibility - only set default size if NOT an image + if (!isImageFile(file)) { + setSize(800, 600); + setLocationRelativeTo(parent); + } - setSize(800, 600); - setLocationRelativeTo(parent); // Intercept window close (X) so we run the same save-confirm flow as other close actions setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); addWindowListener(new java.awt.event.WindowAdapter() { @@ -250,7 +255,7 @@ public class FileEditor extends JDialog { }); } - JScrollPane scrollPane = new JScrollPane(textArea); + scrollPane = new JScrollPane(textArea); add(scrollPane, BorderLayout.CENTER); // Status bar (position, selection) JPanel statusPanel = new JPanel(new BorderLayout()); @@ -385,6 +390,7 @@ public class FileEditor extends JDialog { } private void createMenuBar() { + if (isImageFile(file)) return; JMenuBar menuBar = new JMenuBar(); // File menu @@ -528,7 +534,7 @@ public class FileEditor extends JDialog { // ESC - Zavřít nebo skrýt hledání rootPane.registerKeyboardAction(e -> { - if (searchPanel.isVisible()) { + if (searchPanel != null && searchPanel.isVisible()) { hideSearchPanel(); } else { closeEditor(); @@ -580,7 +586,9 @@ public class FileEditor extends JDialog { }, KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK), JComponent.WHEN_IN_FOCUSED_WINDOW); // Hledání - rootPane.registerKeyboardAction(e -> showSearchPanel(), + rootPane.registerKeyboardAction(e -> { + if (!isImageFile(file)) showSearchPanel(); + }, KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.CTRL_DOWN_MASK), JComponent.WHEN_IN_FOCUSED_WINDOW); @@ -771,6 +779,10 @@ public class FileEditor extends JDialog { } private void loadFile() { + if (isImageFile(file)) { + loadImage(); + return; + } try { // Determine file size first to decide streaming vs full load long size = Files.size(file.toPath()); @@ -843,6 +855,79 @@ public class FileEditor extends JDialog { } return nonPrintable > (len / 4); } + + private boolean isImageFile(File f) { + String name = f.getName().toLowerCase(); + return name.endsWith(".jpg") || name.endsWith(".jpeg") || + name.endsWith(".png") || name.endsWith(".gif") || + name.endsWith(".bmp"); + } + + private void loadImage() { + try { + ImageIcon icon = new ImageIcon(file.getAbsolutePath()); + if (icon.getImageLoadStatus() == MediaTracker.COMPLETE) { + JLabel label = new JLabel(icon); + label.setHorizontalAlignment(JLabel.CENTER); + scrollPane.setViewportView(label); + + statusPosLabel.setText(String.format("Obraz: %d x %d px", + icon.getIconWidth(), icon.getIconHeight())); + statusSelLabel.setText(String.format("Velikost: %s", formatSize(file.length()))); + + // Adjust window size based on image size + adjustWindowSizeForImage(icon.getIconWidth(), icon.getIconHeight()); + + // Disable search and hex for images + if (northPanel != null) { + searchPanel.setVisible(false); + if (hexControlPanel != null) hexControlPanel.setVisible(false); + } + } else { + textArea.setText("Chyba: Nepodařilo se načíst obrázek."); + } + } catch (Exception e) { + textArea.setText("Chyba při načítání obrázku: " + e.getMessage()); + } + } + + private void adjustWindowSizeForImage(int imgWidth, int imgHeigth) { + // First pack to get valid insets + pack(); + + // Get screen size + GraphicsConfiguration gc = getGraphicsConfiguration(); + Rectangle screenBounds = gc.getBounds(); + Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(gc); + + int maxW = screenBounds.width - screenInsets.left - screenInsets.right - 20; + int maxH = screenBounds.height - screenInsets.top - screenInsets.bottom - 20; + + // Use actual insets from title bar and borders after pack() + Insets winInsets = getInsets(); + // Add space for title bar (top), status bar (bottom), and borders + 15px extra + int winW = imgWidth + winInsets.left + winInsets.right + 15; + int winH = imgHeigth + winInsets.top + winInsets.bottom + statusPosLabel.getParent().getHeight() + 15; + + if (winW > maxW) winW = maxW; + if (winH > maxH) winH = maxH; + + // Ensure minimum size + if (winW < 400) winW = 400; + if (winH < 300) winH = 300; + + setPreferredSize(new Dimension(winW, winH)); + setSize(winW, winH); + validate(); + setLocationRelativeTo(getOwner()); + } + + private String formatSize(long size) { + if (size < 1024) return size + " B"; + int exp = (int) (Math.log(size) / Math.log(1024)); + String pre = "KMGTPE".charAt(exp-1) + ""; + return String.format("%.1f %sB", size / Math.pow(1024, exp), pre); + } private void saveFile() { try {