diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index 921e076bd..d83826602 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -2028,6 +2028,8 @@ DecalModel.lbl.choose = From file... ExportDecalDialog.title = Export Decal ExportDecalDialog.decalList.lbl = Decal 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}''.

Would you like to look for this file? ! Component Preset Chooser Dialog ComponentPresetChooserDialog.title = Choose component preset diff --git a/core/src/net/sf/openrocket/appearance/DecalImage.java b/core/src/net/sf/openrocket/appearance/DecalImage.java index cd12cc69e..58e3ed57e 100644 --- a/core/src/net/sf/openrocket/appearance/DecalImage.java +++ b/core/src/net/sf/openrocket/appearance/DecalImage.java @@ -6,6 +6,7 @@ import java.io.IOException; import java.io.InputStream; import net.sf.openrocket.util.ChangeSource; +import net.sf.openrocket.util.DecalNotFoundException; /** * Interface to handle image files for decals @@ -26,18 +27,42 @@ public interface DecalImage extends ChangeSource, Comparable { * @throws FileNotFoundException * @throws IOException */ - public InputStream getBytes() throws FileNotFoundException, IOException; + public InputStream getBytes() throws FileNotFoundException, IOException, DecalNotFoundException; /** * exports an image into the File * @param file The File handler object * @throws IOException */ - public void exportImage(File file) throws IOException; + public void exportImage(File file) throws IOException, DecalNotFoundException; /** * wake up call to listeners * @param source The source of the wake up call */ 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); } diff --git a/core/src/net/sf/openrocket/appearance/defaults/ResourceDecalImage.java b/core/src/net/sf/openrocket/appearance/defaults/ResourceDecalImage.java index 85d24ebf6..b1a53853c 100644 --- a/core/src/net/sf/openrocket/appearance/defaults/ResourceDecalImage.java +++ b/core/src/net/sf/openrocket/appearance/defaults/ResourceDecalImage.java @@ -16,7 +16,10 @@ import net.sf.openrocket.util.StateChangeListener; public class ResourceDecalImage implements DecalImage { /** 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 @@ -63,5 +66,28 @@ public class ResourceDecalImage implements DecalImage { public int compareTo(DecalImage o) { 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); + } + + } diff --git a/core/src/net/sf/openrocket/document/Attachment.java b/core/src/net/sf/openrocket/document/Attachment.java index a46d6300f..24a44911e 100644 --- a/core/src/net/sf/openrocket/document/Attachment.java +++ b/core/src/net/sf/openrocket/document/Attachment.java @@ -6,6 +6,7 @@ import java.io.InputStream; import net.sf.openrocket.util.AbstractChangeSource; 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 IOException */ - public abstract InputStream getBytes() throws FileNotFoundException, IOException; + public abstract InputStream getBytes() throws FileNotFoundException, IOException, DecalNotFoundException; /** * {@inheritDoc} diff --git a/core/src/net/sf/openrocket/document/DecalRegistry.java b/core/src/net/sf/openrocket/document/DecalRegistry.java index 7f512bff9..4f1cb233d 100644 --- a/core/src/net/sf/openrocket/document/DecalRegistry.java +++ b/core/src/net/sf/openrocket/document/DecalRegistry.java @@ -20,8 +20,10 @@ import java.util.regex.Pattern; import net.sf.openrocket.appearance.DecalImage; 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.DecalNotFoundException; import net.sf.openrocket.util.FileUtils; import net.sf.openrocket.util.StateChangeListener; @@ -91,7 +93,7 @@ public class DecalRegistry { decalName = makeUniqueName(location.getName()); d = new DecalImageImpl(decalName, attachment); - d.setFileSystemLocation(location); + d.setDecalFile(location); registeredDecals.put(decalName, d); return d; @@ -121,7 +123,10 @@ public class DecalRegistry { private final Attachment delegate; 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) { this.name = name; @@ -151,10 +156,13 @@ public class DecalRegistry { * @throws IOException */ @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 - File exportedFile = getFileSystemLocation(); + File exportedFile = getDecalFile(); if (exportedFile != null) { + if (!exportedFile.exists()) { + throw new DecalNotFoundException(exportedFile.getAbsolutePath(), this); + } InputStream rawIs = new FileInputStream(exportedFile); try { byte[] bytes = FileUtils.readBytes(rawIs); @@ -164,38 +172,45 @@ public class DecalRegistry { } } - - return delegate.getBytes(); + try { + return delegate.getBytes(); + } catch (DecalNotFoundException decex) { + throw new DecalNotFoundException(delegate.getName(), this); + } } @Override - public void exportImage(File file) throws IOException { - try { - InputStream is = getBytes(); - OutputStream os = new BufferedOutputStream(new FileOutputStream(file)); - - FileUtils.copy(is, os); - - is.close(); - os.close(); - - this.fileSystemLocation = file; - - } catch (IOException iex) { - throw new BugException(iex); - } + public void exportImage(File file) throws IOException, DecalNotFoundException { + InputStream is; + is = getBytes(); + OutputStream os = new BufferedOutputStream(new FileOutputStream(file)); + + FileUtils.copy(is, os); + + is.close(); + os.close(); } /** * * @return */ - File getFileSystemLocation() { - return fileSystemLocation; + public File getDecalFile() { + return decalFile; } - - void setFileSystemLocation(File fileSystemLocation) { - this.fileSystemLocation = fileSystemLocation; + + public void setDecalFile(File file) { + this.decalFile = file; + } + + @Override + public boolean isIgnored() { + return this.ignored; + } + + @Override + public void setIgnored(boolean ignored) { + this.ignored = ignored; } @Override @@ -211,7 +226,7 @@ public class DecalRegistry { @Override protected DecalImageImpl clone() { DecalImageImpl clone = new DecalImageImpl(this.delegate); - clone.fileSystemLocation = this.fileSystemLocation; + clone.decalFile = this.decalFile; return clone; } @@ -237,7 +252,7 @@ public class DecalRegistry { private DecalImageImpl findDecalForFile(File file) { for (DecalImageImpl d : registeredDecals.values()) { - if (file.equals(d.getFileSystemLocation())) { + if (file.equals(d.getDecalFile())) { return d; } } diff --git a/core/src/net/sf/openrocket/document/attachments/FileSystemAttachment.java b/core/src/net/sf/openrocket/document/attachments/FileSystemAttachment.java index 08ed7f7de..815312f36 100644 --- a/core/src/net/sf/openrocket/document/attachments/FileSystemAttachment.java +++ b/core/src/net/sf/openrocket/document/attachments/FileSystemAttachment.java @@ -7,6 +7,7 @@ import java.io.IOException; import java.io.InputStream; 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 */ @Override - public InputStream getBytes() throws IOException { + public InputStream getBytes() throws DecalNotFoundException, IOException { return new FileInputStream(location); } diff --git a/core/src/net/sf/openrocket/document/attachments/ZipFileAttachment.java b/core/src/net/sf/openrocket/document/attachments/ZipFileAttachment.java index d1baa9bfb..c48640f3e 100644 --- a/core/src/net/sf/openrocket/document/attachments/ZipFileAttachment.java +++ b/core/src/net/sf/openrocket/document/attachments/ZipFileAttachment.java @@ -1,7 +1,6 @@ package net.sf.openrocket.document.attachments; import java.io.ByteArrayInputStream; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.URL; @@ -9,6 +8,7 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import net.sf.openrocket.document.Attachment; +import net.sf.openrocket.util.DecalNotFoundException; import net.sf.openrocket.util.FileUtils; public class ZipFileAttachment extends Attachment { @@ -21,7 +21,7 @@ public class ZipFileAttachment extends Attachment { } @Override - public InputStream getBytes() throws IOException { + public InputStream getBytes() throws DecalNotFoundException, IOException { String name = getName(); ZipInputStream zis = new ZipInputStream(zipFileLocation.openStream()); @@ -35,7 +35,7 @@ public class ZipFileAttachment extends Attachment { } entry = zis.getNextEntry(); } - throw new FileNotFoundException("Unable to locate decal for name " + name); + throw new DecalNotFoundException(name, null); } finally { zis.close(); } diff --git a/core/src/net/sf/openrocket/file/AttachmentUtils.java b/core/src/net/sf/openrocket/file/AttachmentUtils.java index 5d76d2036..e0bc3e749 100644 --- a/core/src/net/sf/openrocket/file/AttachmentUtils.java +++ b/core/src/net/sf/openrocket/file/AttachmentUtils.java @@ -8,11 +8,12 @@ import java.io.InputStream; import java.io.OutputStream; import net.sf.openrocket.document.Attachment; +import net.sf.openrocket.util.DecalNotFoundException; import net.sf.openrocket.util.FileUtils; 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(); OutputStream os = new BufferedOutputStream(new FileOutputStream(outFile)); diff --git a/core/src/net/sf/openrocket/file/GeneralRocketSaver.java b/core/src/net/sf/openrocket/file/GeneralRocketSaver.java index 4d4d5863e..1a8a26b42 100644 --- a/core/src/net/sf/openrocket/file/GeneralRocketSaver.java +++ b/core/src/net/sf/openrocket/file/GeneralRocketSaver.java @@ -22,6 +22,7 @@ import net.sf.openrocket.file.openrocket.OpenRocketSaver; import net.sf.openrocket.file.rocksim.export.RocksimSaver; import net.sf.openrocket.rocketcomponent.InsideColorComponent; import net.sf.openrocket.rocketcomponent.RocketComponent; +import net.sf.openrocket.util.DecalNotFoundException; import net.sf.openrocket.util.MathUtil; public class GeneralRocketSaver { @@ -52,7 +53,7 @@ public class GeneralRocketSaver { * @param document the document to save. * @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()); } @@ -64,7 +65,7 @@ public class GeneralRocketSaver { * @param options the storage options. * @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); } @@ -76,7 +77,7 @@ public class GeneralRocketSaver { * @param progress a SavingProgress object used to provide progress information * @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); } @@ -89,7 +90,7 @@ public class GeneralRocketSaver { * @param progress a SavingProgress object used to provide progress information * @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) // file, then if the save is successful, it will copy the file over the old one. @@ -105,6 +106,9 @@ public class GeneralRocketSaver { } try { save(dest.getName(), s, doc, opts); + } catch (DecalNotFoundException decex) { + temporaryNewFile.delete(); + throw decex; } finally { 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 // which follows. @@ -181,8 +185,8 @@ public class GeneralRocketSaver { saveAllPartsZipFile(output, document, options, usedDecals); } - public void saveAllPartsZipFile(OutputStream output, OpenRocketDocument document, StorageOptions options, Set decals) throws IOException { - + public void saveAllPartsZipFile(OutputStream output, OpenRocketDocument document, StorageOptions options, Set decals) throws IOException, DecalNotFoundException { + // Open a zip stream to write to. ZipOutputStream zos = new ZipOutputStream(output); zos.setLevel(9); @@ -196,9 +200,12 @@ public class GeneralRocketSaver { zos.closeEntry(); // Now we write out all the decal images files. - for (DecalImage image : decals) { - + if (image.isIgnored()) { + image.setIgnored(false); + continue; + } + String name = image.getName(); ZipEntry decal = new ZipEntry(name); zos.putNextEntry(decal); diff --git a/core/src/net/sf/openrocket/util/DecalNotFoundException.java b/core/src/net/sf/openrocket/util/DecalNotFoundException.java new file mode 100644 index 000000000..b3a2a49cb --- /dev/null +++ b/core/src/net/sf/openrocket/util/DecalNotFoundException.java @@ -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 + */ +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()); + } +} diff --git a/swing/src/net/sf/openrocket/gui/dialogs/DecalNotFoundDialog.java b/swing/src/net/sf/openrocket/gui/dialogs/DecalNotFoundDialog.java new file mode 100644 index 000000000..e14c05a15 --- /dev/null +++ b/swing/src/net/sf/openrocket/gui/dialogs/DecalNotFoundDialog.java @@ -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 + */ +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 , 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); + } +} diff --git a/swing/src/net/sf/openrocket/gui/main/BasicFrame.java b/swing/src/net/sf/openrocket/gui/main/BasicFrame.java index 74279499b..d3182f3e4 100644 --- a/swing/src/net/sf/openrocket/gui/main/BasicFrame.java +++ b/swing/src/net/sf/openrocket/gui/main/BasicFrame.java @@ -60,8 +60,11 @@ import javax.swing.tree.DefaultTreeSelectionModel; import javax.swing.tree.TreePath; 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.rocketcomponent.AxialStage; +import net.sf.openrocket.util.DecalNotFoundException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -1418,14 +1421,31 @@ public class BasicFrame extends JFrame { } } + StorageOptions options = new StorageOptions(); + 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 { - StorageOptions options = new StorageOptions(); - options.setFileType(StorageOptions.FileType.ROCKSIM); ROCKET_SAVER.save(file, document, options); // Do not update the save state of the document. return true; } catch (IOException e) { 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:", e.getMessage() }, "Saving failed", JOptionPane.ERROR_MESSAGE); 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 { Reflection.handleWrappedException(e); } diff --git a/swing/src/net/sf/openrocket/gui/main/ExportDecalDialog.java b/swing/src/net/sf/openrocket/gui/main/ExportDecalDialog.java index bb7afe25a..18e3c4ba1 100644 --- a/swing/src/net/sf/openrocket/gui/main/ExportDecalDialog.java +++ b/swing/src/net/sf/openrocket/gui/main/ExportDecalDialog.java @@ -20,10 +20,12 @@ import javax.swing.JPanel; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.appearance.DecalImage; 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.SwingPreferences; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.startup.Application; +import net.sf.openrocket.util.DecalNotFoundException; @SuppressWarnings("serial") public class ExportDecalDialog extends JDialog { @@ -102,6 +104,8 @@ public class ExportDecalDialog extends JDialog { try { decal.exportImage(selectedFile); + } catch (DecalNotFoundException e) { + DecalNotFoundDialog.showDialog(this, e); } catch (IOException iex) { String message = MessageFormat.format(trans.get("ExportDecalDialog.exception"), selectedFile.getAbsoluteFile()); JOptionPane.showMessageDialog(this, message, "", JOptionPane.ERROR_MESSAGE); diff --git a/swing/src/net/sf/openrocket/gui/util/EditDecalHelper.java b/swing/src/net/sf/openrocket/gui/util/EditDecalHelper.java index 7fbf24e17..146630e23 100644 --- a/swing/src/net/sf/openrocket/gui/util/EditDecalHelper.java +++ b/swing/src/net/sf/openrocket/gui/util/EditDecalHelper.java @@ -11,6 +11,7 @@ import net.sf.openrocket.appearance.DecalImage; import net.sf.openrocket.arch.SystemInfo; import net.sf.openrocket.arch.SystemInfo.Platform; 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.watcher.FileWatcher; import net.sf.openrocket.gui.watcher.WatchEvent; @@ -21,6 +22,7 @@ import net.sf.openrocket.rocketcomponent.InsideColorComponentHandler; import net.sf.openrocket.rocketcomponent.RocketComponent; import com.google.inject.Inject; +import net.sf.openrocket.util.DecalNotFoundException; public class EditDecalHelper { @@ -83,7 +85,7 @@ public class EditDecalHelper { //First Check preferences if (usageCount == 1 && (sysPrefSet || isSnapConfined)) { String commandLine = isSnapConfined ? "xdg-open %%" : prefs.getDecalEditorCommandLine(); - launchEditor(prefs.isDecalEditorPreferenceSystem(), commandLine, decal); + launchEditor(parent, prefs.isDecalEditorPreferenceSystem(), commandLine, decal); return decal; } @@ -121,7 +123,7 @@ public class EditDecalHelper { decal = makeDecalUniqueInside(doc, component, decal); } - launchEditor(useSystemEditor, commandLine, decal); + launchEditor(parent, useSystemEditor, commandLine, decal); return decal; @@ -154,7 +156,7 @@ public class EditDecalHelper { 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(); // Create Temp File. @@ -188,6 +190,11 @@ public class EditDecalHelper { } catch (IOException ioex) { String message = MessageFormat.format(trans.get("EditDecalHelper.createFileException"), tmpFile.getAbsoluteFile()); throw new EditDecalHelperException(message, ioex); + } catch (DecalNotFoundException decex) { + if (DecalNotFoundDialog.showDialog(parent, decex)) { + launchEditor(parent, useSystemEditor, commandTemplate, decal); + } + return; } diff --git a/swing/src/net/sf/openrocket/gui/util/MessageWidthUtil.java b/swing/src/net/sf/openrocket/gui/util/MessageWidthUtil.java new file mode 100644 index 000000000..1c8f22e1e --- /dev/null +++ b/swing/src/net/sf/openrocket/gui/util/MessageWidthUtil.java @@ -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 + */ +public abstract class MessageWidthUtil { + /** + * Set the message width of to 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("

%s

", px, message); + } +} diff --git a/swing/src/net/sf/openrocket/utils/RocksimConverter.java b/swing/src/net/sf/openrocket/utils/RocksimConverter.java index e60a808a1..651e61c3f 100644 --- a/swing/src/net/sf/openrocket/utils/RocksimConverter.java +++ b/swing/src/net/sf/openrocket/utils/RocksimConverter.java @@ -9,6 +9,8 @@ import net.sf.openrocket.document.StorageOptions; import net.sf.openrocket.file.GeneralRocketLoader; import net.sf.openrocket.file.GeneralRocketSaver; 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. @@ -64,6 +66,8 @@ public class RocksimConverter { System.err.println("ERROR: Error loading '" + inputFile + "': " + e.getMessage()); } catch (IOException e) { System.err.println("ERROR: Error saving '" + outputFile + "': " + e.getMessage()); + } catch (DecalNotFoundException decex) { + DecalNotFoundDialog.showDialog(null, decex); } }