Merge pull request #1019 from SiboVG/issue-136

[fixes #136] Use warning dialog upon decal source file error
This commit is contained in:
Joe Pfeiffer 2022-01-28 15:14:40 -07:00 committed by GitHub
commit 4332732ade
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 288 additions and 53 deletions

View File

@ -2028,6 +2028,8 @@ DecalModel.lbl.choose = From file...
ExportDecalDialog.title = Export Decal ExportDecalDialog.title = Export Decal
ExportDecalDialog.decalList.lbl = Decal ExportDecalDialog.decalList.lbl = Decal
ExportDecalDialog.exception = Unable to write decal to file ''{0}'' ExportDecalDialog.exception = Unable to write decal to file ''{0}''
ExportDecalDialog.source.title = No decal source file
ExportDecalDialog.source.exception = Could not find decal source file ''{0}''.<br><br>Would you like to look for this file?
! Component Preset Chooser Dialog ! Component Preset Chooser Dialog
ComponentPresetChooserDialog.title = Choose component preset ComponentPresetChooserDialog.title = Choose component preset

View File

@ -6,6 +6,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import net.sf.openrocket.util.ChangeSource; import net.sf.openrocket.util.ChangeSource;
import net.sf.openrocket.util.DecalNotFoundException;
/** /**
* Interface to handle image files for decals * Interface to handle image files for decals
@ -26,18 +27,42 @@ public interface DecalImage extends ChangeSource, Comparable<DecalImage> {
* @throws FileNotFoundException * @throws FileNotFoundException
* @throws IOException * @throws IOException
*/ */
public InputStream getBytes() throws FileNotFoundException, IOException; public InputStream getBytes() throws FileNotFoundException, IOException, DecalNotFoundException;
/** /**
* exports an image into the File * exports an image into the File
* @param file The File handler object * @param file The File handler object
* @throws IOException * @throws IOException
*/ */
public void exportImage(File file) throws IOException; public void exportImage(File file) throws IOException, DecalNotFoundException;
/** /**
* wake up call to listeners * wake up call to listeners
* @param source The source of the wake up call * @param source The source of the wake up call
*/ */
public void fireChangeEvent(Object source); public void fireChangeEvent(Object source);
/**
* Get the decal file on which the DecalImage is based
* @return decal source file
*/
public File getDecalFile();
/**
* Set the decal file on which the DecalImage is based
* @param file decal source file
*/
public void setDecalFile(File file);
/**
* Checks whether this DecalImage should be ignored when saving the OpenRocket document.
* @return true if DecalImage should be ignored, false if should be saved
*/
public boolean isIgnored();
/**
* Sets the flag to know whether this DecalImage should be ignored when saving the OpenRocket document.
* @param ignored true if DecalImage should be ignored, false if should be saved
*/
public void setIgnored(boolean ignored);
} }

View File

@ -16,7 +16,10 @@ import net.sf.openrocket.util.StateChangeListener;
public class ResourceDecalImage implements DecalImage { public class ResourceDecalImage implements DecalImage {
/** File path to the image*/ /** File path to the image*/
final String resource; private String resource;
// Flag to check whether this DecalImage should be ignored for saving
private boolean ignored = false;
/** /**
* main constructor, stores the file path given * main constructor, stores the file path given
@ -64,4 +67,27 @@ public class ResourceDecalImage implements DecalImage {
return getName().compareTo(o.getName()); return getName().compareTo(o.getName());
} }
@Override
public void setDecalFile(File file) {
if (file != null) {
this.resource = file.getAbsolutePath();
}
}
@Override
public boolean isIgnored() {
return this.ignored;
}
@Override
public void setIgnored(boolean ignored) {
this.ignored = ignored;
}
@Override
public File getDecalFile() {
return new File(resource);
}
} }

View File

@ -6,6 +6,7 @@ import java.io.InputStream;
import net.sf.openrocket.util.AbstractChangeSource; import net.sf.openrocket.util.AbstractChangeSource;
import net.sf.openrocket.util.ChangeSource; import net.sf.openrocket.util.ChangeSource;
import net.sf.openrocket.util.DecalNotFoundException;
/** /**
* *
@ -39,7 +40,7 @@ public abstract class Attachment extends AbstractChangeSource implements Compara
* @throws FileNotFoundException * @throws FileNotFoundException
* @throws IOException * @throws IOException
*/ */
public abstract InputStream getBytes() throws FileNotFoundException, IOException; public abstract InputStream getBytes() throws FileNotFoundException, IOException, DecalNotFoundException;
/** /**
* {@inheritDoc} * {@inheritDoc}

View File

@ -20,8 +20,10 @@ import java.util.regex.Pattern;
import net.sf.openrocket.appearance.DecalImage; import net.sf.openrocket.appearance.DecalImage;
import net.sf.openrocket.document.attachments.FileSystemAttachment; import net.sf.openrocket.document.attachments.FileSystemAttachment;
import net.sf.openrocket.util.BugException; import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.ChangeSource; import net.sf.openrocket.util.ChangeSource;
import net.sf.openrocket.util.DecalNotFoundException;
import net.sf.openrocket.util.FileUtils; import net.sf.openrocket.util.FileUtils;
import net.sf.openrocket.util.StateChangeListener; import net.sf.openrocket.util.StateChangeListener;
@ -91,7 +93,7 @@ public class DecalRegistry {
decalName = makeUniqueName(location.getName()); decalName = makeUniqueName(location.getName());
d = new DecalImageImpl(decalName, attachment); d = new DecalImageImpl(decalName, attachment);
d.setFileSystemLocation(location); d.setDecalFile(location);
registeredDecals.put(decalName, d); registeredDecals.put(decalName, d);
return d; return d;
@ -121,7 +123,10 @@ public class DecalRegistry {
private final Attachment delegate; private final Attachment delegate;
private String name; private String name;
private File fileSystemLocation; private File decalFile;
private final Translator trans = Application.getTranslator();
// Flag to check whether this DecalImage should be ignored for saving
private boolean ignored = false;
private DecalImageImpl(String name, Attachment delegate) { private DecalImageImpl(String name, Attachment delegate) {
this.name = name; this.name = name;
@ -151,10 +156,13 @@ public class DecalRegistry {
* @throws IOException * @throws IOException
*/ */
@Override @Override
public InputStream getBytes() throws FileNotFoundException, IOException { public InputStream getBytes() throws FileNotFoundException, IOException, DecalNotFoundException {
// First check if the decal is located on the file system // First check if the decal is located on the file system
File exportedFile = getFileSystemLocation(); File exportedFile = getDecalFile();
if (exportedFile != null) { if (exportedFile != null) {
if (!exportedFile.exists()) {
throw new DecalNotFoundException(exportedFile.getAbsolutePath(), this);
}
InputStream rawIs = new FileInputStream(exportedFile); InputStream rawIs = new FileInputStream(exportedFile);
try { try {
byte[] bytes = FileUtils.readBytes(rawIs); byte[] bytes = FileUtils.readBytes(rawIs);
@ -164,38 +172,45 @@ public class DecalRegistry {
} }
} }
try {
return delegate.getBytes(); return delegate.getBytes();
} catch (DecalNotFoundException decex) {
throw new DecalNotFoundException(delegate.getName(), this);
}
} }
@Override @Override
public void exportImage(File file) throws IOException { public void exportImage(File file) throws IOException, DecalNotFoundException {
try { InputStream is;
InputStream is = getBytes(); is = getBytes();
OutputStream os = new BufferedOutputStream(new FileOutputStream(file)); OutputStream os = new BufferedOutputStream(new FileOutputStream(file));
FileUtils.copy(is, os); FileUtils.copy(is, os);
is.close(); is.close();
os.close(); os.close();
this.fileSystemLocation = file;
} catch (IOException iex) {
throw new BugException(iex);
}
} }
/** /**
* *
* @return * @return
*/ */
File getFileSystemLocation() { public File getDecalFile() {
return fileSystemLocation; return decalFile;
} }
void setFileSystemLocation(File fileSystemLocation) { public void setDecalFile(File file) {
this.fileSystemLocation = fileSystemLocation; this.decalFile = file;
}
@Override
public boolean isIgnored() {
return this.ignored;
}
@Override
public void setIgnored(boolean ignored) {
this.ignored = ignored;
} }
@Override @Override
@ -211,7 +226,7 @@ public class DecalRegistry {
@Override @Override
protected DecalImageImpl clone() { protected DecalImageImpl clone() {
DecalImageImpl clone = new DecalImageImpl(this.delegate); DecalImageImpl clone = new DecalImageImpl(this.delegate);
clone.fileSystemLocation = this.fileSystemLocation; clone.decalFile = this.decalFile;
return clone; return clone;
} }
@ -237,7 +252,7 @@ public class DecalRegistry {
private DecalImageImpl findDecalForFile(File file) { private DecalImageImpl findDecalForFile(File file) {
for (DecalImageImpl d : registeredDecals.values()) { for (DecalImageImpl d : registeredDecals.values()) {
if (file.equals(d.getFileSystemLocation())) { if (file.equals(d.getDecalFile())) {
return d; return d;
} }
} }

View File

@ -7,6 +7,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import net.sf.openrocket.document.Attachment; import net.sf.openrocket.document.Attachment;
import net.sf.openrocket.util.DecalNotFoundException;
/** /**
* *
@ -41,7 +42,7 @@ public class FileSystemAttachment extends Attachment {
* creates the stream based on the location passed while building * creates the stream based on the location passed while building
*/ */
@Override @Override
public InputStream getBytes() throws IOException { public InputStream getBytes() throws DecalNotFoundException, IOException {
return new FileInputStream(location); return new FileInputStream(location);
} }

View File

@ -1,7 +1,6 @@
package net.sf.openrocket.document.attachments; package net.sf.openrocket.document.attachments;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL; import java.net.URL;
@ -9,6 +8,7 @@ import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream; import java.util.zip.ZipInputStream;
import net.sf.openrocket.document.Attachment; import net.sf.openrocket.document.Attachment;
import net.sf.openrocket.util.DecalNotFoundException;
import net.sf.openrocket.util.FileUtils; import net.sf.openrocket.util.FileUtils;
public class ZipFileAttachment extends Attachment { public class ZipFileAttachment extends Attachment {
@ -21,7 +21,7 @@ public class ZipFileAttachment extends Attachment {
} }
@Override @Override
public InputStream getBytes() throws IOException { public InputStream getBytes() throws DecalNotFoundException, IOException {
String name = getName(); String name = getName();
ZipInputStream zis = new ZipInputStream(zipFileLocation.openStream()); ZipInputStream zis = new ZipInputStream(zipFileLocation.openStream());
@ -35,7 +35,7 @@ public class ZipFileAttachment extends Attachment {
} }
entry = zis.getNextEntry(); entry = zis.getNextEntry();
} }
throw new FileNotFoundException("Unable to locate decal for name " + name); throw new DecalNotFoundException(name, null);
} finally { } finally {
zis.close(); zis.close();
} }

View File

@ -8,11 +8,12 @@ import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import net.sf.openrocket.document.Attachment; import net.sf.openrocket.document.Attachment;
import net.sf.openrocket.util.DecalNotFoundException;
import net.sf.openrocket.util.FileUtils; import net.sf.openrocket.util.FileUtils;
public abstract class AttachmentUtils { public abstract class AttachmentUtils {
public static void exportAttachment(Attachment a, File outFile) throws IOException { public static void exportAttachment(Attachment a, File outFile) throws IOException, DecalNotFoundException {
InputStream is = a.getBytes(); InputStream is = a.getBytes();
OutputStream os = new BufferedOutputStream(new FileOutputStream(outFile)); OutputStream os = new BufferedOutputStream(new FileOutputStream(outFile));

View File

@ -22,6 +22,7 @@ import net.sf.openrocket.file.openrocket.OpenRocketSaver;
import net.sf.openrocket.file.rocksim.export.RocksimSaver; import net.sf.openrocket.file.rocksim.export.RocksimSaver;
import net.sf.openrocket.rocketcomponent.InsideColorComponent; import net.sf.openrocket.rocketcomponent.InsideColorComponent;
import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.util.DecalNotFoundException;
import net.sf.openrocket.util.MathUtil; import net.sf.openrocket.util.MathUtil;
public class GeneralRocketSaver { public class GeneralRocketSaver {
@ -52,7 +53,7 @@ public class GeneralRocketSaver {
* @param document the document to save. * @param document the document to save.
* @throws IOException in case of an I/O error. * @throws IOException in case of an I/O error.
*/ */
public final void save(File dest, OpenRocketDocument document) throws IOException { public final void save(File dest, OpenRocketDocument document) throws IOException, DecalNotFoundException {
save(dest, document, document.getDefaultStorageOptions()); save(dest, document, document.getDefaultStorageOptions());
} }
@ -64,7 +65,7 @@ public class GeneralRocketSaver {
* @param options the storage options. * @param options the storage options.
* @throws IOException in case of an I/O error. * @throws IOException in case of an I/O error.
*/ */
public final void save(File dest, OpenRocketDocument document, StorageOptions options) throws IOException { public final void save(File dest, OpenRocketDocument document, StorageOptions options) throws IOException, DecalNotFoundException {
save(dest, document, options, null); save(dest, document, options, null);
} }
@ -76,7 +77,7 @@ public class GeneralRocketSaver {
* @param progress a SavingProgress object used to provide progress information * @param progress a SavingProgress object used to provide progress information
* @throws IOException in case of an I/O error. * @throws IOException in case of an I/O error.
*/ */
public final void save(File dest, OpenRocketDocument doc, SavingProgress progress) throws IOException { public final void save(File dest, OpenRocketDocument doc, SavingProgress progress) throws IOException, DecalNotFoundException {
save(dest, doc, doc.getDefaultStorageOptions(), progress); save(dest, doc, doc.getDefaultStorageOptions(), progress);
} }
@ -89,7 +90,7 @@ public class GeneralRocketSaver {
* @param progress a SavingProgress object used to provide progress information * @param progress a SavingProgress object used to provide progress information
* @throws IOException in case of an I/O error. * @throws IOException in case of an I/O error.
*/ */
public final void save(File dest, OpenRocketDocument doc, StorageOptions opts, SavingProgress progress) throws IOException { public final void save(File dest, OpenRocketDocument doc, StorageOptions opts, SavingProgress progress) throws IOException, DecalNotFoundException {
// This method is the core operational method. It saves the document into a new (hopefully unique) // This method is the core operational method. It saves the document into a new (hopefully unique)
// file, then if the save is successful, it will copy the file over the old one. // file, then if the save is successful, it will copy the file over the old one.
@ -105,6 +106,9 @@ public class GeneralRocketSaver {
} }
try { try {
save(dest.getName(), s, doc, opts); save(dest.getName(), s, doc, opts);
} catch (DecalNotFoundException decex) {
temporaryNewFile.delete();
throw decex;
} finally { } finally {
s.close(); s.close();
} }
@ -145,7 +149,7 @@ public class GeneralRocketSaver {
} }
} }
private void save(String fileName, OutputStream output, OpenRocketDocument document, StorageOptions options) throws IOException { private void save(String fileName, OutputStream output, OpenRocketDocument document, StorageOptions options) throws IOException, DecalNotFoundException {
// For now, we don't save decal information in ROCKSIM files, so don't do anything // For now, we don't save decal information in ROCKSIM files, so don't do anything
// which follows. // which follows.
@ -181,7 +185,7 @@ public class GeneralRocketSaver {
saveAllPartsZipFile(output, document, options, usedDecals); saveAllPartsZipFile(output, document, options, usedDecals);
} }
public void saveAllPartsZipFile(OutputStream output, OpenRocketDocument document, StorageOptions options, Set<DecalImage> decals) throws IOException { public void saveAllPartsZipFile(OutputStream output, OpenRocketDocument document, StorageOptions options, Set<DecalImage> decals) throws IOException, DecalNotFoundException {
// Open a zip stream to write to. // Open a zip stream to write to.
ZipOutputStream zos = new ZipOutputStream(output); ZipOutputStream zos = new ZipOutputStream(output);
@ -196,8 +200,11 @@ public class GeneralRocketSaver {
zos.closeEntry(); zos.closeEntry();
// Now we write out all the decal images files. // Now we write out all the decal images files.
for (DecalImage image : decals) { for (DecalImage image : decals) {
if (image.isIgnored()) {
image.setIgnored(false);
continue;
}
String name = image.getName(); String name = image.getName();
ZipEntry decal = new ZipEntry(name); ZipEntry decal = new ZipEntry(name);

View File

@ -0,0 +1,43 @@
package net.sf.openrocket.util;
import net.sf.openrocket.appearance.DecalImage;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.startup.Application;
import java.text.MessageFormat;
/**
* Exception for decals without a valid source file.
*
* @author Sibo Van Gool <sibo.vangool@hotmail.com>
*/
public class DecalNotFoundException extends Exception {
private final DecalImage decal;
private final Translator trans = Application.getTranslator();
/**
* Exception for decals without a valid source file.
* @param message the file path or decal name of the faulty DecalImage
* @param decal DecalImage that has an issue with its source file
*/
public DecalNotFoundException(String message, DecalImage decal) {
super(message);
this.decal = decal;
}
/**
* Get the DecalImage that was the cause of this DecalNotFoundException.
* @return DecalImage that had an issue with its source file
*/
public DecalImage getDecal() {
return decal;
}
/**
* Automatically combine the exception message with the DecalImage file name.
*/
@Override
public String getMessage() {
return MessageFormat.format(trans.get("ExportDecalDialog.source.exception"), super.getMessage());
}
}

View File

@ -0,0 +1,50 @@
package net.sf.openrocket.gui.dialogs;
import net.sf.openrocket.gui.util.MessageWidthUtil;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.DecalNotFoundException;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import java.awt.Component;
import java.io.File;
/**
* Dialog for handling a DecalNotFoundException.
*
* @author Sibo Van Gool <sibo.vangool@hotmail.com>
*/
public abstract class DecalNotFoundDialog {
/**
* Show a yes/no dialog telling the user that a certain decal source file can't be found and asking whether he/she
* wants to look for that file. If prompted yes, a FileChooser opens up to select the file. If a file is selected,
* the source file of the decal, present in <decex>, will be replaced with the selected file.
* @param parent parent window for the pop-up windows
* @param decex exception containing the decal file path as message and DecalImage
* @return true if the decal has been replaced/found, false if the decal source file issue did not get fixed by the user
*/
public static boolean showDialog(Component parent, DecalNotFoundException decex) {
Translator trans = Application.getTranslator();
// Show 'look up file" yes/no dialog
String message = MessageWidthUtil.setMessageWidth(decex.getMessage(), 400);
int resultYesNo = JOptionPane.showConfirmDialog(parent, message,
trans.get("ExportDecalDialog.source.title"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
int resultFileChooser = JFileChooser.CANCEL_OPTION;
// Look for the file
if (resultYesNo == JOptionPane.YES_OPTION) {
JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultDirectory());
resultFileChooser = chooser.showOpenDialog(parent);
if (resultFileChooser == JFileChooser.APPROVE_OPTION) {
File file = chooser.getSelectedFile();
decex.getDecal().setDecalFile(file);
}
}
return (resultYesNo == JOptionPane.YES_OPTION) && (resultFileChooser == JFileChooser.APPROVE_OPTION);
}
}

View File

@ -60,8 +60,11 @@ import javax.swing.tree.DefaultTreeSelectionModel;
import javax.swing.tree.TreePath; import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel; import javax.swing.tree.TreeSelectionModel;
import net.sf.openrocket.appearance.DecalImage;
import net.sf.openrocket.gui.dialogs.DecalNotFoundDialog;
import net.sf.openrocket.gui.widgets.SelectColorButton; import net.sf.openrocket.gui.widgets.SelectColorButton;
import net.sf.openrocket.rocketcomponent.AxialStage; import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.util.DecalNotFoundException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -1418,14 +1421,31 @@ public class BasicFrame extends JFrame {
} }
} }
try {
StorageOptions options = new StorageOptions(); StorageOptions options = new StorageOptions();
options.setFileType(StorageOptions.FileType.ROCKSIM); options.setFileType(StorageOptions.FileType.ROCKSIM);
return saveRocksimFile(file, options);
}
/**
* Perform the actual saving of the Rocksim file
* @param file file to be stored
* @param options storage options to use
* @return true if the file was written
*/
private boolean saveRocksimFile(File file, StorageOptions options) {
try {
ROCKET_SAVER.save(file, document, options); ROCKET_SAVER.save(file, document, options);
// Do not update the save state of the document. // Do not update the save state of the document.
return true; return true;
} catch (IOException e) { } catch (IOException e) {
return false; return false;
} catch (DecalNotFoundException decex) {
DecalImage decal = decex.getDecal();
// Check if the user replaced the source file, if not, just ignore the faulty decal on the next save
if (!DecalNotFoundDialog.showDialog(null, decex) && decal != null) {
decal.setIgnored(true);
}
return saveRocksimFile(file, options); // Resave
} }
} }
@ -1509,6 +1529,16 @@ public class BasicFrame extends JFrame {
"An I/O error occurred while saving:", "An I/O error occurred while saving:",
e.getMessage() }, "Saving failed", JOptionPane.ERROR_MESSAGE); e.getMessage() }, "Saving failed", JOptionPane.ERROR_MESSAGE);
return false; return false;
}
else if (cause instanceof DecalNotFoundException) {
DecalNotFoundException decex = (DecalNotFoundException) cause;
DecalImage decal = decex.getDecal();
// Check if the user replaced the source file, if not, just ignore the faulty decal on the next save
if (!DecalNotFoundDialog.showDialog(null, decex) && decal != null) {
decal.setIgnored(true);
}
return saveAsOpenRocket(file); // Resave
} else { } else {
Reflection.handleWrappedException(e); Reflection.handleWrappedException(e);
} }

View File

@ -20,10 +20,12 @@ import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout; import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.appearance.DecalImage; import net.sf.openrocket.appearance.DecalImage;
import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.gui.dialogs.DecalNotFoundDialog;
import net.sf.openrocket.gui.util.FileHelper; import net.sf.openrocket.gui.util.FileHelper;
import net.sf.openrocket.gui.util.SwingPreferences; import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.startup.Application; import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.DecalNotFoundException;
@SuppressWarnings("serial") @SuppressWarnings("serial")
public class ExportDecalDialog extends JDialog { public class ExportDecalDialog extends JDialog {
@ -102,6 +104,8 @@ public class ExportDecalDialog extends JDialog {
try { try {
decal.exportImage(selectedFile); decal.exportImage(selectedFile);
} catch (DecalNotFoundException e) {
DecalNotFoundDialog.showDialog(this, e);
} catch (IOException iex) { } catch (IOException iex) {
String message = MessageFormat.format(trans.get("ExportDecalDialog.exception"), selectedFile.getAbsoluteFile()); String message = MessageFormat.format(trans.get("ExportDecalDialog.exception"), selectedFile.getAbsoluteFile());
JOptionPane.showMessageDialog(this, message, "", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(this, message, "", JOptionPane.ERROR_MESSAGE);

View File

@ -11,6 +11,7 @@ import net.sf.openrocket.appearance.DecalImage;
import net.sf.openrocket.arch.SystemInfo; import net.sf.openrocket.arch.SystemInfo;
import net.sf.openrocket.arch.SystemInfo.Platform; import net.sf.openrocket.arch.SystemInfo.Platform;
import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.gui.dialogs.DecalNotFoundDialog;
import net.sf.openrocket.gui.dialogs.EditDecalDialog; import net.sf.openrocket.gui.dialogs.EditDecalDialog;
import net.sf.openrocket.gui.watcher.FileWatcher; import net.sf.openrocket.gui.watcher.FileWatcher;
import net.sf.openrocket.gui.watcher.WatchEvent; import net.sf.openrocket.gui.watcher.WatchEvent;
@ -21,6 +22,7 @@ import net.sf.openrocket.rocketcomponent.InsideColorComponentHandler;
import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.RocketComponent;
import com.google.inject.Inject; import com.google.inject.Inject;
import net.sf.openrocket.util.DecalNotFoundException;
public class EditDecalHelper { public class EditDecalHelper {
@ -83,7 +85,7 @@ public class EditDecalHelper {
//First Check preferences //First Check preferences
if (usageCount == 1 && (sysPrefSet || isSnapConfined)) { if (usageCount == 1 && (sysPrefSet || isSnapConfined)) {
String commandLine = isSnapConfined ? "xdg-open %%" : prefs.getDecalEditorCommandLine(); String commandLine = isSnapConfined ? "xdg-open %%" : prefs.getDecalEditorCommandLine();
launchEditor(prefs.isDecalEditorPreferenceSystem(), commandLine, decal); launchEditor(parent, prefs.isDecalEditorPreferenceSystem(), commandLine, decal);
return decal; return decal;
} }
@ -121,7 +123,7 @@ public class EditDecalHelper {
decal = makeDecalUniqueInside(doc, component, decal); decal = makeDecalUniqueInside(doc, component, decal);
} }
launchEditor(useSystemEditor, commandLine, decal); launchEditor(parent, useSystemEditor, commandLine, decal);
return decal; return decal;
@ -154,7 +156,7 @@ public class EditDecalHelper {
return newImage; return newImage;
} }
private void launchEditor(boolean useSystemEditor, String commandTemplate, final DecalImage decal) throws EditDecalHelperException { private void launchEditor(Window parent, boolean useSystemEditor, String commandTemplate, final DecalImage decal) throws EditDecalHelperException {
String decalId = decal.getName(); String decalId = decal.getName();
// Create Temp File. // Create Temp File.
@ -188,6 +190,11 @@ public class EditDecalHelper {
} catch (IOException ioex) { } catch (IOException ioex) {
String message = MessageFormat.format(trans.get("EditDecalHelper.createFileException"), tmpFile.getAbsoluteFile()); String message = MessageFormat.format(trans.get("EditDecalHelper.createFileException"), tmpFile.getAbsoluteFile());
throw new EditDecalHelperException(message, ioex); throw new EditDecalHelperException(message, ioex);
} catch (DecalNotFoundException decex) {
if (DecalNotFoundDialog.showDialog(parent, decex)) {
launchEditor(parent, useSystemEditor, commandTemplate, decal);
}
return;
} }

View File

@ -0,0 +1,19 @@
package net.sf.openrocket.gui.util;
/**
* Helper class for setting the message width for e.g. JOptionPane pop-ups using HTML formatting.
*
* @author Sibo Van Gool <sibo.vangool@hotmail.com>
*/
public abstract class MessageWidthUtil {
/**
* Set the message width of <message> to <px> pixels using HTML formatting.
* @param message message to be formatted
* @param px width of the message in pixels
* @return HTML-formatted message
*
*/
public static String setMessageWidth(String message, int px) {
return String.format("<html><body><p style='width: %dpx'>%s</p></body></html>", px, message);
}
}

View File

@ -9,6 +9,8 @@ import net.sf.openrocket.document.StorageOptions;
import net.sf.openrocket.file.GeneralRocketLoader; import net.sf.openrocket.file.GeneralRocketLoader;
import net.sf.openrocket.file.GeneralRocketSaver; import net.sf.openrocket.file.GeneralRocketSaver;
import net.sf.openrocket.file.RocketLoadException; import net.sf.openrocket.file.RocketLoadException;
import net.sf.openrocket.gui.dialogs.DecalNotFoundDialog;
import net.sf.openrocket.util.DecalNotFoundException;
/** /**
* Utility that loads Rocksim file formats and saves them in ORK format. * Utility that loads Rocksim file formats and saves them in ORK format.
@ -64,6 +66,8 @@ public class RocksimConverter {
System.err.println("ERROR: Error loading '" + inputFile + "': " + e.getMessage()); System.err.println("ERROR: Error loading '" + inputFile + "': " + e.getMessage());
} catch (IOException e) { } catch (IOException e) {
System.err.println("ERROR: Error saving '" + outputFile + "': " + e.getMessage()); System.err.println("ERROR: Error saving '" + outputFile + "': " + e.getMessage());
} catch (DecalNotFoundException decex) {
DecalNotFoundDialog.showDialog(null, decex);
} }
} }