Skip to content

Commit

Permalink
Navigator: Allow keeping the directory structure when exporting files
Browse files Browse the repository at this point in the history
  • Loading branch information
ShadelessFox committed Mar 21, 2024
1 parent 25c675f commit 429baa9
Show file tree
Hide file tree
Showing 12 changed files with 160 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.shade.platform.model.runtime.ProgressMonitor;
import com.shade.platform.model.util.IOUtils;
import com.shade.platform.ui.controls.ColoredListCellRenderer;
import com.shade.platform.ui.controls.FileChooser;
import com.shade.platform.ui.controls.TextAttributes;
import com.shade.platform.ui.dialogs.BaseDialog;
import com.shade.platform.ui.dialogs.ProgressDialog;
Expand Down Expand Up @@ -112,7 +113,7 @@ protected void buttonPressed(@NotNull ButtonDescriptor descriptor) {
final ModelExporterProvider provider = exporterCombo.getItemAt(exporterCombo.getSelectedIndex());
final String extension = provider.getExtension();

final JFileChooser chooser = new JFileChooser();
final JFileChooser chooser = new FileChooser();
chooser.setDialogTitle("Save model as");
chooser.setFileFilter(new FileExtensionFilter("%s Files".formatted(provider.getName()), extension));
chooser.setSelectedFile(new File("%s.%s".formatted("exported", extension)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.shade.decima.ui.data.viewer.texture.controls.ImageProvider;
import com.shade.platform.model.data.DataKey;
import com.shade.platform.ui.controls.ColoredListCellRenderer;
import com.shade.platform.ui.controls.FileChooser;
import com.shade.platform.ui.controls.TextAttributes;
import com.shade.platform.ui.dialogs.BaseDialog;
import com.shade.platform.ui.dialogs.ProgressDialog;
Expand Down Expand Up @@ -91,7 +92,7 @@ protected void buttonPressed(@NotNull ButtonDescriptor descriptor) {
final String name = Objects.requireNonNullElse(provider.getName(), "exported");
final String extension = exporter.getExtension();

final JFileChooser chooser = new JFileChooser();
final JFileChooser chooser = new FileChooser();
chooser.setDialogTitle("Save texture as");
chooser.setFileFilter(new FileExtensionFilter("%s Files".formatted(extension.toUpperCase()), extension));
chooser.setSelectedFile(new File("%s.%s".formatted(name, extension)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.shade.decima.ui.data.viewer.audio.AudioPlayerPanel;
import com.shade.decima.ui.data.viewer.audio.AudioPlayerUtils;
import com.shade.decima.ui.data.viewer.audio.Playlist;
import com.shade.platform.ui.controls.FileChooser;
import com.shade.platform.ui.dialogs.ProgressDialog;
import com.shade.platform.ui.menus.MenuItem;
import com.shade.platform.ui.menus.MenuItemContext;
Expand All @@ -27,7 +28,7 @@ public class ExportAllTracksItem extends MenuItem {

@Override
public void perform(@NotNull MenuItemContext ctx) {
final JFileChooser chooser = new JFileChooser();
final JFileChooser chooser = new FileChooser();
chooser.setDialogTitle("Save tracks to");
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
chooser.addChoosableFileFilter(new FileExtensionFilter("OGG Files", "ogg"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.shade.platform.model.util.BufferUtils;
import com.shade.platform.model.util.IOUtils;
import com.shade.platform.ui.UIColor;
import com.shade.platform.ui.controls.FileChooser;
import com.shade.platform.ui.util.UIUtils;
import com.shade.util.NotNull;
import com.shade.util.Nullable;
Expand Down Expand Up @@ -132,7 +133,7 @@ public ExportAction() {

@Override
public void actionPerformed(ActionEvent event) {
final JFileChooser chooser = new JFileChooser();
final JFileChooser chooser = new FileChooser();
chooser.setDialogTitle("Export binary data as");
chooser.setSelectedFile(new File("exported.bin"));
chooser.setAcceptAllFileFilterUsed(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.shade.decima.model.rtti.types.java.HwFont;
import com.shade.decima.ui.controls.FileExtensionFilter;
import com.shade.platform.ui.controls.ColoredListCellRenderer;
import com.shade.platform.ui.controls.FileChooser;
import com.shade.platform.ui.controls.TextAttributes;
import com.shade.platform.ui.dialogs.BaseDialog;
import com.shade.util.NotNull;
Expand Down Expand Up @@ -59,7 +60,7 @@ protected void buttonPressed(@NotNull ButtonDescriptor descriptor) {
final String name = Objects.requireNonNullElse(font.getName(), "font");
final String extension = exporter.getExtension();

final JFileChooser chooser = new JFileChooser();
final JFileChooser chooser = new FileChooser();
chooser.setDialogTitle("Save font as");
chooser.setFileFilter(new FileExtensionFilter("%s Files".formatted(extension.toUpperCase()), extension));
chooser.setSelectedFile(new File("%s.%s".formatted(name, extension)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@
import com.shade.decima.ui.navigator.impl.NavigatorProjectNode;
import com.shade.platform.model.runtime.ProgressMonitor;
import com.shade.platform.model.util.IOUtils;
import com.shade.platform.ui.controls.ColoredListCellRenderer;
import com.shade.platform.ui.controls.CommonTextAttributes;
import com.shade.platform.ui.controls.Mnemonic;
import com.shade.platform.ui.controls.TextAttributes;
import com.shade.platform.ui.controls.*;
import com.shade.platform.ui.dialogs.BaseDialog;
import com.shade.platform.ui.dialogs.ProgressDialog;
import com.shade.platform.ui.util.UIUtils;
Expand Down Expand Up @@ -221,7 +218,7 @@ protected void buttonPressed(@NotNull ButtonDescriptor descriptor) {

outputPath = null;
} else {
final JFileChooser chooser = new JFileChooser();
final JFileChooser chooser = new FileChooser();
chooser.setDialogTitle("Choose output packfile");
chooser.setFileFilter(new FileExtensionFilter("Decima packfile", "bin"));
chooser.setAcceptAllFileFilterUsed(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.shade.decima.ui.editor.core.CoreNodeFile;
import com.shade.decima.ui.editor.core.CoreNodeObject;
import com.shade.platform.ui.PlatformDataKeys;
import com.shade.platform.ui.controls.FileChooser;
import com.shade.platform.ui.menus.MenuItem;
import com.shade.platform.ui.menus.MenuItemContext;
import com.shade.platform.ui.menus.MenuItemRegistration;
Expand All @@ -28,7 +29,7 @@
public class ExportToJsonItem extends MenuItem {
@Override
public void perform(@NotNull MenuItemContext ctx) {
final JFileChooser chooser = new JFileChooser();
final JFileChooser chooser = new FileChooser();
chooser.setDialogTitle("Save as");
chooser.setFileFilter(new FileExtensionFilter("JSON Files", "json"));
chooser.setSelectedFile(new File("exported.json"));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.shade.decima.ui.navigator.menu;

import com.shade.decima.model.util.FilePath;
import com.shade.decima.ui.navigator.impl.NavigatorFileNode;
import com.shade.platform.ui.PlatformDataKeys;
import com.shade.platform.ui.controls.FileChooser;
import com.shade.platform.ui.menus.MenuItem;
import com.shade.platform.ui.menus.MenuItemContext;
import com.shade.platform.ui.menus.MenuItemRegistration;
Expand All @@ -10,27 +12,48 @@
import javax.swing.*;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;

import static com.shade.decima.ui.menu.MenuConstants.*;
import static java.nio.file.StandardOpenOption.*;

@MenuItemRegistration(parent = CTX_MENU_NAVIGATOR_ID, name = "E&xport File\u2026", icon = "Action.exportIcon", group = CTX_MENU_NAVIGATOR_GROUP_EDIT, order = 2000)
@MenuItemRegistration(parent = CTX_MENU_NAVIGATOR_ID, name = "E&xport File\u2026", icon = "Action.exportIcon", group = CTX_MENU_NAVIGATOR_GROUP_EDIT, order = 1000)
public class ExportContentsItem extends MenuItem {
@Override
public void perform(@NotNull MenuItemContext ctx) {
final NavigatorFileNode node = (NavigatorFileNode) ctx.getData(PlatformDataKeys.SELECTION_KEY);
final JFileChooser chooser = new JFileChooser();
chooser.setSelectedFile(new File(node.getLabel()));
final FilePath path = node.getPath();

final JCheckBox keepDirectoryStructure = new JCheckBox("Keep directory structure");
keepDirectoryStructure.setToolTipText("Creates subdirectories for the exported file");

final FileChooser chooser = new FileChooser();
chooser.setSelectedFile(new File(path.last()));
chooser.setOptions(keepDirectoryStructure);

if (chooser.showSaveDialog(JOptionPane.getRootFrame()) != JFileChooser.APPROVE_OPTION) {
return;
}

try {
final Path file = chooser.getSelectedFile().toPath();
final Path output;

if (keepDirectoryStructure.isSelected() && path.length() > 1) {
output = file.resolveSibling(path.full());
Files.createDirectories(output.getParent());
} else {
output = file;
}

if (chooser.showSaveDialog(JOptionPane.getRootFrame()) == JFileChooser.APPROVE_OPTION) {
try (
InputStream is = node.getFile().newInputStream();
OutputStream os = Files.newOutputStream(chooser.getSelectedFile().toPath(), CREATE, WRITE, TRUNCATE_EXISTING)
OutputStream os = Files.newOutputStream(output, CREATE, WRITE, TRUNCATE_EXISTING)
) {
is.transferTo(os);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

import static com.shade.decima.ui.menu.MenuConstants.*;

@MenuItemRegistration(parent = CTX_MENU_NAVIGATOR_ID, name = "I&mport File\u2026", icon = "Action.importIcon", group = CTX_MENU_NAVIGATOR_GROUP_EDIT, order = 1000)
@MenuItemRegistration(parent = CTX_MENU_NAVIGATOR_ID, name = "I&mport File\u2026", icon = "Action.importIcon", group = CTX_MENU_NAVIGATOR_GROUP_EDIT, order = 2000)
public class ImportContentsItem extends MenuItem {
@Override
public void perform(@NotNull MenuItemContext ctx) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.shade.platform.ui.controls;

import com.shade.util.Nullable;

import javax.swing.*;
import java.io.File;

public class FileChooser extends JFileChooser {
public static final String OPTIONS_CHANGED_PROPERTY = "optionsChanged";

private JComponent options;

@Override
public void approveSelection() {
final File file = getSelectedFile();

if (file != null && file.exists() && getDialogType() == SAVE_DIALOG) {
final int result = JOptionPane.showConfirmDialog(
this,
"File '%s' already exists. Do you want to overwrite it?".formatted(file.getName()),
"Confirm",
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE
);

if (result != JOptionPane.OK_OPTION) {
return;
}
}

super.approveSelection();
}

@Nullable
public JComponent getOptions() {
return options;
}

public void setOptions(@Nullable JComponent options) {
final JComponent oldValue = this.options;
this.options = options;
firePropertyChange(OPTIONS_CHANGED_PROPERTY, oldValue, options);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.shade.platform.ui.controls.plaf;

import com.shade.platform.ui.controls.FileChooser;
import com.shade.util.NotNull;
import net.miginfocom.swing.MigLayout;

import javax.swing.*;
import javax.swing.plaf.ComponentUI;
import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

public class FlatFileChooserUI extends com.formdev.flatlaf.ui.FlatFileChooserUI {
private JComponent optionsPanel;

public FlatFileChooserUI(JFileChooser fc) {
super(fc);
}

public static ComponentUI createUI(JComponent c) {
return new FlatFileChooserUI((JFileChooser) c);
}

@Override
public void installComponents(JFileChooser fc) {
super.installComponents(fc);

optionsPanel = new JPanel();
optionsPanel.setLayout(new BorderLayout());

// Gaps and insets are defined according to MetalFileChooserUI.ButtonAreaLayout
final JPanel buttonPanel = getButtonPanel();
buttonPanel.setLayout(new MigLayout("ins 0,gapx 5,ins 17 0 0 0", "push[][fill][fill]"));
buttonPanel.add(optionsPanel, 0);

if (getFileChooser() instanceof FileChooser fc1 && fc1.getOptions() != null) {
optionsPanel.add(fc1.getOptions(), BorderLayout.CENTER);
}
}

@Override
public void uninstallComponents(JFileChooser fc) {
super.uninstallComponents(fc);

optionsPanel = null;
}

@Override
public PropertyChangeListener createPropertyChangeListener(JFileChooser fc) {
final PropertyChangeListener parent = super.createPropertyChangeListener(fc);
return e -> {
if (e.getPropertyName().equals(FileChooser.OPTIONS_CHANGED_PROPERTY)) {
doOptionsChanged(e);
} else {
parent.propertyChange(e);
}
};
}

private void doOptionsChanged(@NotNull PropertyChangeEvent e) {
if (optionsPanel != null) {
if (e.getOldValue() != null) {
optionsPanel.remove((JComponent) e.getOldValue());
}
if (e.getNewValue() != null) {
optionsPanel.add((JComponent) e.getNewValue(), BorderLayout.CENTER);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ ToolTipUI = com.shade.platform.ui.controls.plaf.FlatOutlineToolTipUI
ToolTabbedPaneUI = com.shade.platform.ui.controls.plaf.FlatToolTabbedPaneUI
LabeledSeparatorUI = com.shade.platform.ui.controls.plaf.LabeledSeparatorUI
ThinSplitPaneUI = com.shade.platform.ui.controls.plaf.FlatThinSplitPaneUI
FileChooserUI = com.shade.platform.ui.controls.plaf.FlatFileChooserUI

#General
TitlePane.unifiedBackground = false
Expand Down

0 comments on commit 429baa9

Please sign in to comment.