diff --git a/CHANGELOG.md b/CHANGELOG.md index 8456f3326..975a28719 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ All notable changes to this project will be documented in this file. - AS3 P-code - hilight and edit traits outside classes - [#1585] SVG import - support for style tag (CSS) - [#1585] SVG import - support for switch tag +- Preview in image file selection dialogs ### Changed - [#1471] Import script menuitem renamed to Import scripts. diff --git a/src/com/jpexs/decompiler/flash/gui/FileChooserImagePreview.java b/src/com/jpexs/decompiler/flash/gui/FileChooserImagePreview.java new file mode 100644 index 000000000..7cf9489fe --- /dev/null +++ b/src/com/jpexs/decompiler/flash/gui/FileChooserImagePreview.java @@ -0,0 +1,104 @@ +package com.jpexs.decompiler.flash.gui; + +import javax.swing.*; +import java.beans.*; +import java.awt.*; +import java.io.File; +import javax.swing.border.Border; + +public class FileChooserImagePreview extends JComponent + implements PropertyChangeListener { + + ImageIcon thumbnail = null; + File file = null; + + public static final int PREVIEW_SIZE = 150; + + public FileChooserImagePreview(JFileChooser fc) { + setPreferredSize(new Dimension(PREVIEW_SIZE, 50)); + fc.addPropertyChangeListener(this); + + JLabel topLabel = new JLabel(AppStrings.translate("FileChooser.preview"), SwingConstants.CENTER); + Border b = UIManager.getBorder("FileChooser.listViewBorder"); + topLabel.setBorder(b); + JPanel previewPanel = new JPanel() { + @Override + protected void paintComponent(Graphics g) { + if (thumbnail == null) { + loadImage(); + } + if (thumbnail != null) { + int x = getWidth() / 2 - thumbnail.getIconWidth() / 2; + int y = getHeight() / 2 - thumbnail.getIconHeight() / 2; + + if (y < 0) { + y = 0; + } + + if (x < 5) { + x = 5; + } + thumbnail.paintIcon(this, g, x, y); + } else { + String str = AppStrings.translate("FileChooser.previewNotAvailable"); + g.drawString(str, getWidth() / 2 - g.getFontMetrics().stringWidth(str) / 2, getHeight() / 2 + g.getFontMetrics().getHeight() / 2); + } + } + }; + JPanel fullPanel = new JPanel(new BorderLayout()); + fullPanel.add(topLabel, BorderLayout.NORTH); + fullPanel.add(previewPanel, BorderLayout.CENTER); + setLayout(new BorderLayout()); + add(new JScrollPane(fullPanel), BorderLayout.CENTER); + + } + + public void loadImage() { + if (file == null) { + thumbnail = null; + return; + } + + ImageIcon tmpIcon = new ImageIcon(file.getPath()); + + if (tmpIcon != null) { + if (tmpIcon.getImageLoadStatus() == MediaTracker.COMPLETE) { + if (tmpIcon.getIconWidth() > PREVIEW_SIZE) { + thumbnail = new ImageIcon(tmpIcon.getImage().getScaledInstance(PREVIEW_SIZE, -1, Image.SCALE_DEFAULT)); + } else { //no need to miniaturize + thumbnail = tmpIcon; + } + } else { + thumbnail = null; + } + + } + } + + @Override + public void propertyChange(PropertyChangeEvent e) { + boolean update = false; + String prop = e.getPropertyName(); + + //If the directory changed, don't show an image. + if (JFileChooser.DIRECTORY_CHANGED_PROPERTY.equals(prop)) { + file = null; + update = true; + + //If a file became selected, find out which one. + } else if (JFileChooser.SELECTED_FILE_CHANGED_PROPERTY.equals(prop)) { + file = (File) e.getNewValue(); + update = true; + } + + //Update the preview accordingly. + if (update) { + thumbnail = null; + if (isShowing()) { + loadImage(); + repaint(); + } + } + } + +} diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index 5c3d646ae..bb8e7e826 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -163,6 +163,7 @@ import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Desktop; +import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Font; import java.awt.datatransfer.DataFlavor; @@ -230,9 +231,11 @@ import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.filechooser.FileFilter; import javax.swing.plaf.basic.BasicTreeUI; +import javax.swing.plaf.metal.MetalFileChooserUI; import javax.swing.tree.DefaultTreeSelectionModel; import javax.swing.tree.TreePath; import jsyntaxpane.DefaultSyntaxKit; +import org.pushingpixels.substance.internal.ui.SubstanceFileChooserUI; /** * @@ -2639,7 +2642,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se } for (SWF swf : swfs) { - File selectedFile = showImportFileChooser("filter.xml|*.xml"); + File selectedFile = showImportFileChooser("filter.xml|*.xml", false); if (selectedFile != null) { File selfile = Helper.fixDialogFile(selectedFile); String xml = Helper.readTextFile(selfile.getPath()); @@ -2956,16 +2959,16 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se TreeItem ti0 = items.get(0); File file = null; if (ti0 instanceof DefineSoundTag) { - file = showImportFileChooser("filter.sounds|*.mp3;*.wav|filter.sounds.mp3|*.mp3|filter.sounds.wav|*.wav"); + file = showImportFileChooser("filter.sounds|*.mp3;*.wav|filter.sounds.mp3|*.mp3|filter.sounds.wav|*.wav", false); } if (ti0 instanceof ImageTag) { - file = showImportFileChooser("filter.images|*.jpg;*.jpeg;*.gif;*.png;*.bmp"); + file = showImportFileChooser("filter.images|*.jpg;*.jpeg;*.gif;*.png;*.bmp", true); } if (ti0 instanceof ShapeTag) { - file = showImportFileChooser("filter.images|*.jpg;*.jpeg;*.gif;*.png;*.bmp;*.svg"); + file = showImportFileChooser("filter.images|*.jpg;*.jpeg;*.gif;*.png;*.bmp;*.svg", true); } if (ti0 instanceof DefineBinaryDataTag) { - file = showImportFileChooser(""); + file = showImportFileChooser("", false); } for (TreeItem ti : items) { doReplaceAction(ti, file); @@ -3064,7 +3067,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se if (item instanceof ShapeTag) { ShapeTag st = (ShapeTag) item; String filter = "filter.images|*.jpg;*.jpeg;*.gif;*.png;*.bmp;*.svg"; - File selectedFile = showImportFileChooser(filter); + File selectedFile = showImportFileChooser(filter, true); if (selectedFile != null) { File selfile = Helper.fixDialogFile(selectedFile); byte[] data = null; @@ -3106,7 +3109,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se if (item instanceof DefineBitsJPEG3Tag || item instanceof DefineBitsJPEG4Tag) { ImageTag it = (ImageTag) item; if (it.importSupported()) { - File selectedFile = showImportFileChooser(""); + File selectedFile = showImportFileChooser("", false); if (selectedFile != null) { File selfile = Helper.fixDialogFile(selectedFile); byte[] data = Helper.readFile(selfile.getAbsolutePath()); @@ -3157,11 +3160,20 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se export(true); } - public File showImportFileChooser(String filter) { + public File showImportFileChooser(String filter, boolean imagePreview) { String[] filterArray = filter.length() > 0 ? filter.split("\\|") : new String[0]; JFileChooser fc = new JFileChooser(); + System.err.println("" + fc.getPreferredSize().width); + // SubstanceFileChooserUI s = new SubstanceFileChooserUI(fc); + //MetalFileChooserUI f; fc.setCurrentDirectory(new File(Configuration.lastOpenDir.get())); + if (imagePreview) { + fc.setAccessory(new FileChooserImagePreview(fc)); + Dimension prefferedSize = new Dimension(fc.getPreferredSize()); + prefferedSize.width += FileChooserImagePreview.PREVIEW_SIZE; + fc.setPreferredSize(prefferedSize); + } boolean first = true; for (int i = 0; i < filterArray.length; i += 2) { final String filterName = filterArray[i]; diff --git a/src/com/jpexs/decompiler/flash/gui/generictageditors/BinaryDataEditor.java b/src/com/jpexs/decompiler/flash/gui/generictageditors/BinaryDataEditor.java index 0a8b1e303..7525d44fe 100644 --- a/src/com/jpexs/decompiler/flash/gui/generictageditors/BinaryDataEditor.java +++ b/src/com/jpexs/decompiler/flash/gui/generictageditors/BinaryDataEditor.java @@ -84,7 +84,7 @@ public class BinaryDataEditor extends JButton implements GenericTagEditor { } private void buttonActionPerformed(ActionEvent evt) { - File selectedFile = mainPanel.showImportFileChooser(""); + File selectedFile = mainPanel.showImportFileChooser("", false); if (selectedFile != null) { File selfile = Helper.fixDialogFile(selectedFile); byte[] data = Helper.readFile(selfile.getAbsolutePath()); diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties index 4612a94cc..a1c220ad8 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties @@ -802,4 +802,7 @@ message.confirm.recentSearches.clear = Do you really want to clear recent search message.input.gotoCharacter.title = Go to character message.input.gotoCharacter = Enter character id -message.character.notfound = Character %characterid% not found. \ No newline at end of file +message.character.notfound = Character %characterid% not found. + +FileChooser.preview = Preview +FileChooser.previewNotAvailable = (preview not available) diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties index a36e39d55..6ee5582ce 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties @@ -778,4 +778,7 @@ message.confirm.recentSearches.clear = Opravdu chcete vymazat ned\u00e1vno hleda message.input.gotoCharacter.title = P\u0159ej\u00edt na charakter message.input.gotoCharacter = Zadejte id charakteru -message.character.notfound = Charakter %characterid% nenalezen. \ No newline at end of file +message.character.notfound = Charakter %characterid% nenalezen. + +FileChooser.preview = N\u00e1hled +FileChooser.previewNotAvailable = (n\u00e1hled nen\u00ed dostupn\u00fd)