/** * ChangeOutputDirectory.java * * --Copyright notice-- * * Copyright (c) School of Geography, University of Leeds. * http://www.geog.leeds.ac.uk/ * This software is licensed under 'The Artistic License' which can be found at * the Open Source Initiative website at... * http://www.opensource.org/licenses/artistic-license.php * Please note that the optional Clause 8 does not apply to this code. * * The Standard Version source code, and associated documentation can be found at... * [online] http://www.ccg.leeds.ac.uk/software/ * * --End of Copyright notice-- * **/ package uk.ac.leeds.ccg.boundarytypeanalyst; import java.awt.*; import java.io.*; import java.util.Properties; import javax.swing.JFileChooser; import com.esri.arcgis.addins.desktop.Button; import com.esri.arcgis.beans.ui.ComponentFactory; import com.esri.arcgis.catalog.*; import com.esri.arcgis.catalogUI.GxDialog; import com.esri.arcgis.framework.IApplication; import com.esri.arcgis.interop.AutomationException; /** * ArcGIS button addin to change and store directories. * * @author Andrew Evans * @version 0.1 */ public class ChangeOutputDirectory extends Button { private File directory = null; private static ChangeOutputDirectory cod = null; private boolean firstUseThisTime = true; /** * Public constructor, but for Singleton. Do not use. * Note that unlike a usual singleton the constructor needs to * be public for ArcGIS to work its addIn magic. **/ public ChangeOutputDirectory() { cod = this; if (directory == null) { JFileChooser fd = new JFileChooser(); fd.setCurrentDirectory(directory); // FileChooser works out home directory. // Theoretically this can also be achieved from // a null file using getAbsolutePath, but I didn't have much luck with it. directory = fd.getCurrentDirectory(); } } /** * Singleton access method. **/ public static ChangeOutputDirectory getInstance() { return cod; } /** * Called when the button is clicked. Switches directories and calls BoundaryTypeAnalyst's writeProperties. * There is one potential bug. If the user enters a directory with the same name as the directory they * are in, the second part of the path is removed. onSelectionChanged code has been added to mitigate against * this but it currently doesn't seem to work. The use case is less common than the issue that required at * GxDialog to be used, ie the non-focus of JFileChoosers and their hiding behind the application. * Alternatives using ComponentFactory.getInstance().getMapFileChooser() don't seem to solve the * focus issue. * * @exception java.io.IOException if there are interop problems. * @exception com.esri.arcgis.interop.AutomationException if the component throws an ArcObjects exception. */ @Override public void onClick() throws IOException, AutomationException { // Set up a GxDialog, that just shows basic filesystem elements. // The anonymous class elements don't seem to work, but are left in // for later addition. GxDialog gxd = new GxDialog() { private boolean directoryEmpty = false; // Trying to set this outside failed. public void onSelectionChanged(IGxSelectionEventsOnSelectionChangedEvent theEvent) { IGxSelection selection = theEvent.getSelection(); try { if (selection.getCount() == 0) { setName(""); // If we've moved into the directory, wipe the name. directoryEmpty = true; } } catch (AutomationException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public boolean getDirectoryEmpty() {return directoryEmpty;} }; gxd.setAllowMultiSelect(false); gxd.setTitle("Select an output directory"); // Filter out all but filesystem types. GxFilterBasicTypes filter = new GxFilterBasicTypes(); int[] behaviour = {esriDoubleClickResult.esriDCRShowChildren}; filter.canChooseObject(new GxFolder(), behaviour); filter.canChooseObject(new GxFolderConnections(), behaviour); filter.canChooseObject(new GxShortcut(), behaviour); gxd.addFilter(filter, true); // Next line seems to be ignored in favour of last ArcCatalog directory. gxd.setStartingLocation(directory.getAbsoluteFile()); // Show dialog. gxd.doModalSave(0); // One problem is that there seems to be no way to get // the selected path including the name in the dialog text box. // This would be fine, but for the fact that a) the user can // select a directory and it appears in the textbox, making the // user assume it is part of the path; b) if they double-click on // a directory and enter it, the name remains in the text box, meaning // we can't just add the textbox to all. The code below trys to sort // this, and will fix it entirely if the onSelectionChanged code above starts working. IGxObject igxo = gxd.getFinalLocation(); String path = ""; if (gxd.getName().equals(igxo.getName())) { path = igxo.getFullName(); } else { if ((gxd.getName() == null) || gxd.getName().equals("")) { path = igxo.getFullName(); } else { path = igxo.getFullName() + File.separator + gxd.getName(); } } directory = new File(path); BoundaryTypeAnalyst.getInstance().writeProperties(); } /** * Gets the current directory. Calls BoundaryTypeAnalyst's readProperties if it is running for the first time. * If readProperties returns null, we stick with the currentDirectory, which is usually the home directory as * found in the constructor. * @return */ public File getDirectory() { if (firstUseThisTime) { BoundaryTypeAnalyst.getInstance().readProperties(); String directoryString = BoundaryTypeAnalyst.getInstance().getDirectoryString(); if (directoryString != null) { directory = new File (directoryString); } // Else leave as it is in constructor. firstUseThisTime = false; } return directory; } // End of class }