/* * Licensed Materials - Property of Perforce Software, Inc. * © Copyright Perforce Software, Inc. 2014, 2021 * © Copyright IBM Corp. 2009, 2014 * © Copyright ILOG 1996, 2009 * All Rights Reserved. * * Note to U.S. Government Users Restricted Rights: * The Software and Documentation were developed at private expense and * are "Commercial Items" as that term is defined at 48 CFR 2.101, * consisting of "Commercial Computer Software" and * "Commercial Computer Software Documentation", as such terms are * used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4, * as applicable. */ package utils; import java.awt.Component; import java.awt.Cursor; import java.awt.Dialog; import java.awt.Frame; import java.awt.HeadlessException; import java.awt.Point; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.Vector; import javax.swing.JCheckBox; import javax.swing.JDialog; import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.WindowConstants; import javax.swing.border.EmptyBorder; import javax.swing.filechooser.FileFilter; import ilog.views.IlvManager; import ilog.views.IlvManagerLayer; import ilog.views.IlvManagerView; import ilog.views.io.IlvReadFileException; import ilog.views.io.IlvSingleValueNamedProperty; import ilog.views.maps.IlvAreaOfInterest; import ilog.views.maps.IlvAreasOfInterestProperty; import ilog.views.maps.IlvCoordinateSystemProperty; import ilog.views.maps.IlvDisplayPreferences; import ilog.views.maps.IlvDisplayPreferencesProperty; import ilog.views.maps.IlvMapInputStream; import ilog.views.maps.IlvMapLayerTreeProperty; import ilog.views.maps.IlvMapOutputStream; import ilog.views.maps.IlvMapTileGeneratorConstants; import ilog.views.maps.IlvMapUtil; import ilog.views.maps.beans.IlvExceptionMessage; import ilog.views.maps.beans.IlvJAreaOfInterestPanel; import ilog.views.maps.beans.IlvMapAnnotationProperty; import ilog.views.maps.beans.IlvMapLayerTreeModel; import ilog.views.maps.datasource.IlvMapDataSourceProperty; import ilog.views.maps.format.IlvDefaultDataPathResolver; import ilog.views.maps.format.IlvMapDataPathManager; import ilog.views.maps.format.IlvMapDataPathResolver; import ilog.views.maps.label.IlvMapLabelerProperty; import ilog.views.maps.raster.IlvRasterTemporaryFileManager; import ilog.views.maps.srs.coordsys.IlvCoordinateSystem; import ilog.views.maps.theme.IlvMapStyleControllerProperty; import ilog.views.tiling.IlvThreadedTileLoader; import ilog.views.tiling.IlvTileLoader; import ilog.views.tiling.IlvTiledLayer; import ilog.views.util.swing.layout.IlvVerticalFlowLayout; import plugins.ImportAction; import shared.BaseDemo; import shared.MapBuilder; /** management of save/load actions */ public class IvlFileManager { // Since JViews 8.7, we store the last visible area and try to apply it when // the file is loaded in the map builder. private static final String LAST_AREA = "LastAOE"; //$NON-NLS-1$ static String description; /** * Sets the description of the files able to be loaded in the MapBuilder. This * is the descrition that appears in the file selector. * * @return The String describing the map files. */ public static String getDescription() { return description != null ? description : IlvMapUtil.getString(IvlFileManager.class, "IvlFileManager.FileType"); //$NON-NLS-1$ } /** * Sets the description of the maps files. * * @param d */ public static void setDescription(String d) { description = d; } // final static String MODE_PROPERTY = "mode"; //$NON-NLS-1$ static JFileChooser makeFileChooser() { final JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileFilter(new FileFilter() { Override public boolean accept(File f) { return (f.isDirectory() || f.getName().toLowerCase().endsWith(IlvMapOutputStream.getFileSuffix())); } Override public String getDescription() { return IvlFileManager.getDescription(); } }); fileChooser.removeChoosableFileFilter(fileChooser.getAcceptAllFileFilter()); return fileChooser; } // JV-1725 /** * Shows a save dialog if necessary. * * @param app * application to check for modification * @param view * component to use as dialog root * @return JOptionPane.YES_OPTION or NO_OPTION or CANCEL_OPTION. * @see SaveIvlActionListener */ public static int askSave(BaseDemo app, IlvManagerView view) { if (app.isModified()) { int ans = JOptionPane.showConfirmDialog(view, IlvMapUtil.getString(IvlFileManager.class, "IvlFileManager.MessageConfirmSave"), //$NON-NLS-1$ IlvMapUtil.getString(IvlFileManager.class, "IvlFileManager.TitleConfirmSave"), //$NON-NLS-1$ JOptionPane.YES_NO_CANCEL_OPTION); if (ans == JOptionPane.YES_OPTION) { IvlFileManager.SaveIvlActionListener p = new IvlFileManager.SaveIvlActionListener(app, true); p.actionPerformed(null); if (!p.isSaved()) { ans = JOptionPane.CANCEL_OPTION; } } return ans; } return JOptionPane.YES_OPTION; } /** * Action listener that loads an ivl file. */ public static class LoadIvlActionListener implements ActionListener { // JViews Bug Report #2005.245 /** * An improved data path resolver that tries all possible relative paths * that can be made from a file name: for example, for * "//C/dir1/dir2/file.shp", we will try : basename//C/dir1/dir2/file.shp * basename/dir1/dir2/file.shp basename/dir2/file.shp basename/file.shp */ private static class ImprovedDataPathResolver extends IlvDefaultDataPathResolver { private ImprovedDataPathResolver(String basename) { super(basename); } /** * @see ilog.views.maps.format.IlvDefaultDataPathResolver#resolvePath(java.lang.String) */ Override public String resolvePath(String filename) { String s = super.resolvePath(filename); // if we did not find "filename" (perhaps because it is not a relative // path) if (s == null) { // lets try with any relative path that can be constructed from the // file name File f = new File(filename); String curString = null; Vector<String> parents = new Vector<String>(); while (f != null) { String name = f.getName(); if (name != null && name.length() > 0) { if (curString == null) { curString = name; } else { curString = name + File.separator + curString; } parents.insertElementAt(curString, 0); } f = f.getParentFile(); } for (int i = 0; i < parents.size() && s == null; i++) { s = super.resolvePath(parents.get(i).toString()); } } return s; } Override public URL resolveURL(String urlname) { URL url = super.resolveURL(urlname); try { if ("file".equals(url.getProtocol())) {// lets check if //$NON-NLS-1$ // the file exists InputStream i = url.openStream(); i.close(); } } catch (Exception se) { url = null; } // we did not find "urlname" (perhaps because the basename is a file) if (url == null) { String p = resolvePath(urlname); try { if (p != null && new File(p).exists()) { url = new File(p).toURI().toURL(); } } catch (Exception se) { // ignore } } return url; } } JFileChooser fChooser; private final BaseDemo demo; private final IlvManagerView view; // JV-1725 private boolean shouldAskSave; /** * Creates a loader for the specified view. * * @param demo */ public LoadIvlActionListener(BaseDemo demo) { this.demo = demo; this.view = demo.getView(); // JV-1725 shouldAskSave = true; } /** * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ Override public void actionPerformed(ActionEvent e) { // JV-1725 if (askSave(demo, view) == JOptionPane.CANCEL_OPTION) { return; } if (fChooser == null) { fChooser = makeFileChooser(); } boolean ok = false; while (!ok) { // JViews Bug Report 2005.189 int result = fChooser.showDialog(view, IlvMapUtil.getString(IvlFileManager.class, "IvlFileManager.Title")); //$NON-NLS-1$ if (result != JFileChooser.APPROVE_OPTION) { return; } if (fChooser.getSelectedFile().exists()) { ok = true; } else { JOptionPane.showMessageDialog(fChooser, IlvMapUtil.getString(IvlFileManager.class, "IvlFileManager.ErrorMessage"), //$NON-NLS-1$ IlvMapUtil.getString(IvlFileManager.class, "IvlFileManager.ErrorTitle"), //$NON-NLS-1$ JOptionPane.ERROR_MESSAGE); } } shouldAskSave = false; doLoad(fChooser.getSelectedFile()); shouldAskSave = true; } IlvMapDataPathResolver dpr; /** * Loads the selected ivl file. * * @param file * selected file. */ public void doLoad(File file) { // JV-1725 if (shouldAskSave && askSave(demo, view) == JOptionPane.CANCEL_OPTION) { return; } String ilvFilename = file.getPath(); // JViews Bug Report 2005.218 if (dpr != null) {// remove old datapath resolver IlvMapDataPathManager.RemoveDataPathResolver(dpr); } // JViews Bug Report #2005.218 // JViews Bug Report #2005.245 dpr = new ImprovedDataPathResolver(new File(ilvFilename).getParent()); IlvMapDataPathManager.AddDataPathResolver(dpr); doLoad(demo, file); } /** * Loads a map file in the specified application. * * @param demo * The application. * @param selected * The file lot load. */ public static void doLoad(final BaseDemo demo, File selected) { try { if (demo == null) return; if (!IlvMapInputStream.isIVL(selected.getAbsolutePath())) { String msg = "<html> " + selected.getName() + "<br> " + //$NON-NLS-1$//$NON-NLS-2$ IlvMapUtil.getString(BaseDemo.class, "BaseDemo.NotAIVLFile") + " <br>" + //$NON-NLS-1$//$NON-NLS-2$ IlvMapUtil.getString(BaseDemo.class, "BaseDemo.LoadAnyway") + " <br>" + //$NON-NLS-1$ //$NON-NLS-2$ " </html>"; //$NON-NLS-1$ JLabel label = new JLabel(msg); int rep = JOptionPane.showConfirmDialog(demo, label, IlvMapUtil.getString(BaseDemo.class, "BaseDemo.NotAIVLFileTitle"), //$NON-NLS-1$ JOptionPane.YES_NO_OPTION); if (rep != JOptionPane.YES_OPTION) return; } IlvManagerView view = demo.getView(); IlvManager manager = view.getManager(); clearManager(view, true); String ilvFilename = selected.getPath(); IlvMapInputStream input = new IlvMapInputStream(ilvFilename); input.setDocumentBase(selected.toURI().toURL()); input.read(manager); // restore the visible area (Since JViews 8.7) boolean fit = true; Object o = manager.getNamedProperty(LAST_AREA); if (o instanceof IlvSingleValueNamedProperty) { Object a = ((IlvSingleValueNamedProperty) o).getValue(); if (a instanceof IlvAreaOfInterest) { ((IlvAreaOfInterest) a).zoomTo(view); fit = false; } } if (fit) { view.fitTransformerToContent(); } demo.setCurrentFile(ilvFilename); demo.setLoading(true); IlvCoordinateSystem cs = IlvCoordinateSystemProperty.GetCoordinateSystem(view.getManager()); demo.getCoordinateSystemEditorPanel().setCoordinateSystem(cs); IlvDisplayPreferences pref = IlvDisplayPreferencesProperty.GetDisplayPreferences(view.getManager()); demo.getDisplayPreferencesEditorPanel().setDisplayPreferences(pref); demo.setLoading(false); SwingUtilities.invokeLater(new Runnable() { Override public void run() { demo.setModified(false); } }); view.repaint(); } catch (IOException e1) { new IlvExceptionMessage(e1, e1.getMessage()); } catch (IlvReadFileException e2) { new IlvExceptionMessage(e2, e2.getMessage()); } } } /** * Clears the manager and all its properties. * * @param view * to retrieve the manager. * @param clearAll * if true, will also clear all layers,map layers and data sources. */ public static void clearManager(IlvManagerView view, boolean clearAll) { IlvManager manager = view.getManager(); IlvMapLayerTreeModel model = IlvMapLayerTreeProperty.GetMapLayerTreeModel(manager); /* Correction for JV-1632 */ /* * Calling model.clearAllObjects() is not necessary. We do it after the * "regular" cleaning below. */ if (clearAll) { while (manager.getLayersCount() > 0) { IlvManagerLayer layer = manager.getManagerLayer(0); if (layer instanceof IlvTiledLayer) { IlvTileLoader loader = ((IlvTiledLayer) layer).getTileLoader(); if (loader instanceof IlvThreadedTileLoader) { ((IlvThreadedTileLoader) loader).dispose(); } } manager.removeLayer(0, false); } manager.removeNamedProperty(IlvMapLayerTreeProperty.NAME); manager.removeNamedProperty(IlvMapDataSourceProperty.NAME); manager.removeNamedProperty(IlvAreasOfInterestProperty.NAME); manager.removeNamedProperty(IlvMapStyleControllerProperty.NAME); manager.removeNamedProperty(IlvMapLabelerProperty.NAME); manager.removeNamedProperty(IlvMapAnnotationProperty.NAME); manager.removeNamedProperty(IlvMapTileGeneratorConstants.TILE_SIZE_PROPERTY); manager.removeNamedProperty(IlvMapTileGeneratorConstants.SCALE_LEVELS_PROPERTY); // remove the temporary files String dialogTitle = IlvMapUtil.getString(IvlFileManager.class, "IvlFileManager.TitleClearingDialog"); //$NON-NLS-1$ String dialogMessage = IlvMapUtil.getString(IvlFileManager.class, "IvlFileManager.ClearingMessageDialog"); //$NON-NLS-1$ final Frame frame = JOptionPane.getFrameForComponent(view); final JDialog clearDialog = new JDialog(frame, dialogTitle, true); clearDialog.setUndecorated(true); clearDialog.getContentPane().add(new JLabel(dialogMessage)); clearDialog.pack(); Point loc = new Point((int) (frame.getBounds().getCenterX() - clearDialog.getWidth() / 2.), (int) (frame.getBounds().getCenterY() - clearDialog.getHeight() / 2.)); clearDialog.setLocation(loc); clearDialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); clearDialog.setResizable(false); final Thread clearThread; clearThread = new Thread("ClearThread") { //$NON-NLS-1$ Override public void run() { IlvRasterTemporaryFileManager.removeAllFiles(); SwingUtilities.invokeLater(new Runnable() { Override public void run() { clearDialog.setVisible(false); } }); } }; clearDialog.getContentPane().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); clearThread.setPriority(Thread.MIN_PRIORITY); clearThread.start(); double t0 = System.currentTimeMillis(); while (clearThread.isAlive() && System.currentTimeMillis() < t0 + 1000) { try { Thread.sleep(250); } catch (InterruptedException e) { // empty } } if (clearThread.isAlive()) { clearDialog.setVisible(true); } } model.clearAllObjects(); // clear remaining file mappings IlvMapUtil.freeMemoryNow(null); } static Window getWindowForComponent(Component parentComponent) throws HeadlessException { if (parentComponent == null) return null; if (parentComponent instanceof Frame || parentComponent instanceof Dialog) return (Window) parentComponent; return getWindowForComponent(parentComponent.getParent()); } /** * Action listener that clears a manager. */ public static class ClearManagerActionListener implements ActionListener { private IlvManagerView view; private BaseDemo demo; /** * Creates a clear listener for the specified view. * * @param demo * @param view */ public ClearManagerActionListener(BaseDemo demo, IlvManagerView view) { this.view = view; this.demo = demo; } /** * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ Override public void actionPerformed(ActionEvent e) { // JV-1725 if (askSave(demo, view) == JOptionPane.CANCEL_OPTION) { return; } // stopping threads if (demo instanceof MapBuilder) { MapBuilder mb = (MapBuilder) demo; ImportAction[] importActions = mb.getAllImportActions(); for (int i = 0; i < importActions.length; i++) { importActions[i].getStopButton().stopAllThreads(); } } clearManager(view, true); demo.getCoordinateSystemEditorPanel().setCoordinateSystem(null); // fix // for // JV-1558 view.fitTransformerToContent(); view.getManager().reDraw(); if (demo != null) { demo.setCurrentFile(null); SwingUtilities.invokeLater(new Runnable() { Override public void run() { demo.setModified(false); } }); } } } /** * Action listener that saves an ivl file. */ public static class SaveIvlActionListener implements ActionListener { final BaseDemo demo; private final IlvManagerView view; private boolean saved; JFileChooser fileChooser; final boolean useDemoCurrentFile; JCheckBox mmode = new JCheckBox(IlvMapUtil.getString(IvlFileManager.class, "IvlFileManager.ModeToggleLabel")); //$NON-NLS-1$ JCheckBox bmode = new JCheckBox(IlvMapUtil.getString(IvlFileManager.class, "IvlFileManager.BinaryModeToggleLabel")); //$NON-NLS-1$ /** * @return Returns the view. */ IlvManagerView getView() { return view; } /** * @param saved * The saved to set. */ void setSaved(boolean saved) { this.saved = saved; } /** * @return Returns the saved. */ public boolean isSaved() { return saved; } /** * Creates a save listener for the specified demo. * * @param demo * application registered. * @param useDemoCurrentFile * indicates if saving should use the demo last opened filename. */ public SaveIvlActionListener(BaseDemo demo, boolean useDemoCurrentFile) { this.demo = demo; this.view = demo.getView(); this.useDemoCurrentFile = useDemoCurrentFile; } /** * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ boolean binary; /** * @inheritDoc */ Override public void actionPerformed(ActionEvent e) { try { saved = false; String ilvFilenameTemp = null; boolean themeOnly = getView().getManager() .getNamedProperty(IlvMapOutputStream.CONTENTS_NOT_SAVED_PROPERTY_NAME) != null; if (useDemoCurrentFile) { ilvFilenameTemp = demo.getCurrentFile(); } if (ilvFilenameTemp == null) { mmode.setSelected(themeOnly); bmode.setSelected(binary); if (fileChooser == null) { fileChooser = makeFileChooser(); JPanel accessory = new JPanel(); accessory.setLayout(new IlvVerticalFlowLayout()); accessory.add(mmode); accessory.add(bmode); fileChooser.setAccessory(accessory); } int result = fileChooser.showSaveDialog(view); if (result != JFileChooser.APPROVE_OPTION) { return; } File selected = fileChooser.getSelectedFile(); // long time = System.currentTimeMillis(); ilvFilenameTemp = selected.getPath(); themeOnly = mmode.isSelected(); binary = bmode.isSelected(); } int ans = JOptionPane.YES_OPTION; // JV-4849 final String imgFilename; int len = IlvMapOutputStream.getFileSuffix().length(); if (!ilvFilenameTemp.substring(ilvFilenameTemp.length() - len) .equalsIgnoreCase(IlvMapOutputStream.getFileSuffix())) { imgFilename = ilvFilenameTemp + IlvMapOutputStream.getImageFileSuffix(); ilvFilenameTemp = ilvFilenameTemp + IlvMapOutputStream.getFileSuffix(); } else { imgFilename = ilvFilenameTemp.substring(0, ilvFilenameTemp.length() - len) + IlvMapOutputStream.getImageFileSuffix(); } if (!useDemoCurrentFile && new File(ilvFilenameTemp).exists()) { ans = JOptionPane.showConfirmDialog(view, IlvMapUtil.getString(IvlFileManager.class, "IvlFileManager.MessageConfirmOverwrite"), //$NON-NLS-1$ IlvMapUtil.getString(IvlFileManager.class, "IvlFileManager.TitleConfirmOverwrite"), //$NON-NLS-1$ JOptionPane.YES_NO_CANCEL_OPTION); } if (ans == JOptionPane.YES_OPTION) { final String ilvFilename = ilvFilenameTemp; final boolean writeObj = !themeOnly; String dialogTitle = IlvMapUtil.getString(IvlFileManager.class, "IvlFileManager.TitleSavingDialog"); //$NON-NLS-1$ String dialogMessage = IlvMapUtil.getString(IvlFileManager.class, "IvlFileManager.SavingMessageDialog"); //$NON-NLS-1$ final Frame frame = JOptionPane.getFrameForComponent(view); JLabel label = new JLabel(dialogMessage); label.setHorizontalAlignment(SwingConstants.CENTER); final JOptionPane optionPane = new JOptionPane(label, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_OPTION, null, new String[] { UIManager.getString("OptionPane.cancelButtonText") }); //$NON-NLS-1$ optionPane.setBorder(new EmptyBorder(10, 10, 10, 10)); final JDialog saveDialog = new JDialog(frame, dialogTitle, true); Point loc = new Point((int) (frame.getBounds().getCenterX() - saveDialog.getWidth() / 2.), (int) (frame.getBounds().getCenterY() - saveDialog.getHeight() / 2.)); saveDialog.setLocation(loc); // saveDialog.setUndecorated(true); // saveDialog.setLayout(new BorderLayout()); saveDialog.getContentPane().add(optionPane); saveDialog.pack(); saveDialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); saveDialog.setResizable(false); final IlvMapOutputStream mapOut = new IlvMapOutputStream(ilvFilename, binary); mapOut.setWritingObjects(writeObj); // save the visible area (Since JViews 8.7) IlvAreaOfInterest aoe = IlvJAreaOfInterestPanel.createLocationFromView(getView(), 0, false); IlvSingleValueNamedProperty aoep = new IlvSingleValueNamedProperty(LAST_AREA, aoe); getView().getManager().setNamedProperty(aoep); // end final Thread writeThread = new Thread("WriteThread") { //$NON-NLS-1$ Override public void run() { boolean deleteFiles = false; try { // Wait a bit before actually saving (refresh pb(?)) Thread.sleep(500); mapOut.write(getView().getManager()); // } catch (IOException e1) { // was interrupted during write deleteFiles = true; mapOut.setWritingObjects(false); try { mapOut.closeImageStream(); } catch (IOException exx) { exx.printStackTrace(); } } catch (InterruptedException e2) { // was interrupted during sleep } catch (Exception e3) { e3.printStackTrace(); new IlvExceptionMessage(e3, null); } finally { try { mapOut.flush(); mapOut.close(); } catch (IOException e4) { // ignore. } if (deleteFiles) { new File(ilvFilename).delete(); new File(imgFilename).delete(); } } setSaved(true); SwingUtilities.invokeLater(new Runnable() { Override public void run() { demo.setModified(false); } }); demo.setCurrentFile(ilvFilename); if (saveDialog.isVisible()) { saveDialog.dispose(); } } }; saveDialog.getContentPane().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); optionPane.addPropertyChangeListener(new PropertyChangeListener() { Override public void propertyChange(PropertyChangeEvent ev) { String prop = ev.getPropertyName(); if (saveDialog.isVisible() && (ev.getSource() == optionPane) && (prop.equals(JOptionPane.VALUE_PROPERTY))) { try { // ivlFos.close(); mapOut.close(); } catch (Exception e6) { new IlvExceptionMessage(e6, null); } saveDialog.setVisible(false); } } }); writeThread.start(); saveDialog.setVisible(true); } } catch (IOException e1) { new IlvExceptionMessage(e1, null); } } } }