All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.electric.tool.user.User Maven / Gradle / Ivy

/* -*- tab-width: 4 -*-
 *
 * Electric(tm) VLSI Design System
 *
 * File: User.java
 *
 * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
 *
 * Electric(tm) is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Electric(tm) is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Electric(tm); see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, Mass 02111-1307, USA.
 */
package com.sun.electric.tool.user;

import com.sun.electric.StartupPrefs;
import com.sun.electric.database.IdMapper;
import com.sun.electric.database.Snapshot;
import com.sun.electric.database.hierarchy.Cell;
import com.sun.electric.database.hierarchy.EDatabase;
import com.sun.electric.database.hierarchy.Library;
import com.sun.electric.database.id.CellId;
import com.sun.electric.database.id.IdManager;
import com.sun.electric.database.id.LibId;
import com.sun.electric.database.prototype.NodeProto;
import com.sun.electric.database.prototype.PortProto;
import com.sun.electric.database.text.Pref;
import com.sun.electric.database.text.Setting;
import com.sun.electric.database.text.TextUtils;
import com.sun.electric.database.topology.NodeInst;
import com.sun.electric.database.variable.TextDescriptor;
import com.sun.electric.database.variable.VarContext;
import com.sun.electric.database.variable.Variable;
import com.sun.electric.technology.ArcProto;
import com.sun.electric.technology.PrimitiveNode;
import com.sun.electric.technology.PrimitivePort;
import com.sun.electric.technology.Technology;
import com.sun.electric.technology.Xml;
import com.sun.electric.technology.technologies.Generic;
import com.sun.electric.tool.AbstractUserInterface;
import com.sun.electric.tool.Job;
import com.sun.electric.tool.Listener;
import com.sun.electric.tool.ToolSettings;
import com.sun.electric.tool.user.redisplay.VectorCache;
import com.sun.electric.tool.user.ui.EditWindow;
import com.sun.electric.tool.user.ui.TechPalette;
import com.sun.electric.tool.user.ui.TopLevel;
import com.sun.electric.tool.user.ui.WindowContent;
import com.sun.electric.tool.user.ui.WindowFrame;
import com.sun.electric.util.math.EDimension;

import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.geom.Rectangle2D;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import javax.swing.SwingUtilities;

/**
 * This is the User Interface tool.
 */
public class User extends Listener
{
	// ---------------------- private and protected methods -----------------

	/** the User Interface tool. */		private static User tool = new User();
	/** key of Variable holding cell frame information. */				public static final Variable.Key FRAME_SIZE = Variable.newKey("FACET_schematic_page_size");
	/** key of Variable holding cell company name. */					public static final Variable.Key FRAME_COMPANY_NAME = Variable.newKey("USER_drawing_company_name");
	/** key of Variable holding cell designer name. */					public static final Variable.Key FRAME_DESIGNER_NAME = Variable.newKey("USER_drawing_designer_name");
	/** key of Variable holding user who last changed the cell. */		public static final Variable.Key FRAME_LAST_CHANGED_BY = Variable.newKey("USER_drawing_last_changed_by");
	/** key of Variable holding cell project name. */					public static final Variable.Key FRAME_PROJECT_NAME = Variable.newKey("USER_drawing_project_name");

	private ArcProto currentArcProto = null;
    private Technology currentTech = null;
    private Map preferredContactPortProtoMap = new HashMap();
    private Map> equivalentPortProtoMap = new HashMap>();

	/**
	 * The constructor sets up the User tool.
	 */
	private User()
	{
		super("user");
	}

	/**
	 * Method to initialize the User Interface tool.
	 */
	public void init()
	{
		// the user interface tool is always on
		setOn();
		setIncremental();

//		if (Job.getRunMode() != Job.Mode.CLIENT)
//			Clipboard.clear(); // To initialize clipboard Cell
	}

	/**
	 * Method to retrieve the singleton associated with the User tool.
	 * @return the User tool.
	 */
	public static User getUserTool() { return tool; }

   /**
	 * Handles database changes of a Job.
	 * @param oldSnapshot database snapshot before Job.
	 * @param newSnapshot database snapshot after Job and constraint propagation.
	 * @param undoRedo true if Job was Undo/Redo job.
	 */
	public void endBatch(Snapshot oldSnapshot, Snapshot newSnapshot, boolean undoRedo) {
		for(Iterator wit = WindowFrame.getWindows(); wit.hasNext(); )
		{
			WindowFrame wf = wit.next();
			WindowContent content = wf.getContent();
			if (!(content instanceof EditWindow)) continue;
			Cell winCell = content.getCell();
			if (winCell == null) continue;
			EditWindow wnd = (EditWindow)content;
			if (!winCell.isLinked())
				wnd.setCell(null, null, null);
		}
        if (newSnapshot.environment != IdManager.stdIdManager.getInitialEnvironment()) {
            EditWindow.invokeRenderJob();
        }
//		// Mark cells for redraw
//		HashSet marked = new HashSet();
//		for (CellId cellId: newSnapshot.getChangedCells(oldSnapshot)) {
//			CellBackup newBackup = newSnapshot.getCell(cellId);
//			CellBackup oldBackup = oldSnapshot.getCell(cellId);
//			ERectangle newBounds = newSnapshot.getCellBounds(cellId);
//			ERectangle oldBounds = oldSnapshot.getCellBounds(cellId);
//			if (newBackup != oldBackup || newBounds != oldBounds) {
//				if (newBackup == null) continue; // What to do with deleted cells ??
//				Cell cell = Cell.inCurrentThread(cellId);
//				if (cell == null) continue; // This might be a desynchronization between GUI thread and delete???
//				markCellForRedrawRecursively(cell, marked);
////				VectorDrawing.cellChanged(cell);
//				EditWindow.forceRedraw(cell);
//			}
//		}
//		for(Iterator wit = WindowFrame.getWindows(); wit.hasNext(); )
//		{
//			WindowFrame wf = wit.next();
//			WindowContent content = wf.getContent();
//			if (!(content instanceof EditWindow)) continue;
//			Cell winCell = content.getCell();
//			if (winCell == null) continue;
//			EditWindow wnd = (EditWindow)content;
//			if (!winCell.isLinked()) {
//				wnd.setCell(null, null, null);
//			} else if (marked.contains(winCell)) {
//				wnd.fullRepaint();
//			}
//		}
	}

	/**
	 * Reloading or renaming libraries has the side affect that any EditWindows
	 * containing cells that were reloaded now point to old, unlinked
	 * cells instead of the new ones. This method checks for this state
	 * and fixes it.
	 * @param idMapper mapping of Library/Cell/Export ids, null if the library was renamed.
	 */
	public static void fixStaleCellReferences(IdMapper idMapper) {
		if (idMapper == null) return;
        AbstractUserInterface ui = Job.getExtendedUserInterface();
        EDatabase database = ui.getDatabase();
        LibId curLibId = ui.getCurrentLibraryId();
        if (curLibId != null && idMapper.get(curLibId) != curLibId)
            ui.setCurrentLibrary(database.getLib(idMapper.get(curLibId)));
		for (Iterator it = WindowFrame.getWindows(); it.hasNext(); ) {
			WindowFrame frame = it.next();
            WindowContent wnd = frame.getContent();
            Cell cell = wnd.getCell();
            if (cell == null) continue;
            if (!cell.isLinked()) {
                CellId cellId = idMapper.get(cell.getId());
                Cell newCell = database.getCell(cellId);
                if (newCell == null) continue;
                wnd.setCell(newCell, VarContext.globalContext, null);
            }
		}
	}

	/************************** TRACKING CHANGES TO CELLS **************************/

	private static Map changedWindowRects = new HashMap();

	/**
	 * Method to tell which area of a window has been changed.
	 * @param wnd the EditWindow in question.
	 * @return the area (in database coordinates) that have been modified and demand redisplay.
	 */
	public static Rectangle2D getChangedInWindow(EditWindow wnd)
	{
		Rectangle2D changedArea = changedWindowRects.get(wnd);
		return changedArea;
	}

	/**
	 * Method to reset the area of a window that has been changed.
	 * Call this after redisplaying that area so that nothing is queued for redraw.
	 * @param wnd the EditWindow in question.
	 */
	public static void clearChangedInWindow(EditWindow wnd)
	{
		changedWindowRects.remove(wnd);
	}

	/**
	 * Method called when a technology's parameters change.
	 * All cells that use the technology must be recached.
	 */
	public static void technologyChanged()
	{
		VectorCache.theCache.clearCache();
		EditWindow.clearSubCellCache();
        WindowFrame.updateTechnologyLists();
	}

	/****************************** MISCELLANEOUS FUNCTIONS ******************************/

	/**
	 * Method to return the "current" PrimitivePort per a given pair of arcs, as maintained by the user interface.
	 * @return the "current" PrimitivePort, as maintained by the user interface.
	 */
    public PrimitivePort getPreferredContactPortProto(ArcProto key1, ArcProto key2)
    {
        Technology tech = key1.getTechnology();
        if (currentTech != tech)
        {
            // need to initialize the data
            uploadCurrentData(tech, tech.getFactoryMenuPalette());
        }
        String key = key1.getName() + "@" + key2.getName();
        PrimitivePort np = preferredContactPortProtoMap.get(key);
        if (np != null) return np; // found
        // trying the other combination
        key = key2.getName() + "@" + key1.getName();
        return preferredContactPortProtoMap.get(key);
    }

    public List getPrimitivePortConnectedToArc(ArcProto ap)
    {
        List list = new ArrayList();
        String name = ap.getName();

        // Look if ArcProto name is contained in any key of the contact map. It might not be very efficient.
        for (String key : preferredContactPortProtoMap.keySet())
        {
            if (!key.contains(name)) continue; // not a close match

            // Using tokenizer as a method to distinguish metal-1 from metal-10
            StringTokenizer t = new StringTokenizer(key, ", @", false);
            while (t.hasMoreTokens())
            {
                String str = t.nextToken();
                if (str.equals(name))
                {
                    PrimitivePort p = preferredContactPortProtoMap.get(key);
                    if (p != null)
                        list.add(p);
                    break;
                }
            }
        }
        // not valid for pure layer nodes and well arcs at least
//        if (Job.getDebug() && currentTech.isLayout())
//            assert(!list.isEmpty());
        return list;
    }

    private Map contactNodeProtoMap = new HashMap();

    private Pref getContactNodePref(Technology tech, String mainContactName)
    {
    	Pref thisEntry = contactNodeProtoMap.get(mainContactName);
    	if (thisEntry == null)
    	{
    		thisEntry = Pref.makeStringPref("ComponentMenuEntryFor" + mainContactName + "In" + tech.getTechName(),
    			tool.prefs, mainContactName);
    		contactNodeProtoMap.put(mainContactName, thisEntry);
    	}
    	return thisEntry;
    }

    /**
     * Method to return the current contact in the component menu when an entry has multiple choices.
     * @param tech the technology being displayed in the component menu.
     * @param mainContactName the name of the "main" (first) contact in the list.
     * @return the name of the component that is "current".
     */
    public String getCurrentContactNodeProto(Technology tech, String mainContactName)
    {
    	Pref thisEntry = getContactNodePref(tech, mainContactName);
        // update preferred contact map
        PrimitiveNode pn = tech.findNodeProto(thisEntry.getString());
        if (pn != null) {
            updatePrimitiveNodeConnections(pn);
        }
        return thisEntry.getString();
    }

    /**
     * Method to set the current contact in the component menu when an entry has multiple choices.
     * @param tech the technology being displayed in the component menu.
     * @param mainContactName the name of the "main" (first) contact in the list.
     * @param obj the current entry that should be the displayed choice.
     */
    public void setCurrentContactNodeProto(Technology tech, String mainContactName, Object obj)
    {
        NodeProto np;
        if (obj instanceof NodeProto)
            np = (NodeProto)obj;
        else if (obj instanceof NodeInst)
            np = ((NodeInst)obj).getProto();
        else if (obj instanceof Xml.PrimitiveNode)
            np = currentTech.findNodeProto(((Xml.PrimitiveNode)obj).name);
        else if (obj instanceof Xml.MenuNodeInst)
            np = currentTech.findNodeProto(((Xml.MenuNodeInst)obj).protoName);
        else
            return; // not the valid object

        // remember the setting
        if (mainContactName != null)
        {
	    	Pref thisEntry = getContactNodePref(tech, mainContactName);
	    	thisEntry.setString(TechPalette.getItemName(tech, obj, true));
        }

    	if (!(np instanceof PrimitiveNode)) return;
    	updatePrimitiveNodeConnections((PrimitiveNode)np);
    }

    private void updatePrimitiveNodeConnections(PrimitiveNode pn)
    {
        if (pn.isNotUsed()) return;
        if (!pn.getFunction().isContact()) return;
        int numPorts = pn.getNumPorts();
        assert(numPorts == 1); // basic assumption for now.
        for (int j = 0; j < numPorts; j++)
        {
        	PrimitivePort pp = pn.getPort(j);
            List list = getArcNamesSorted(pp);
            for (int i = 1; i < list.size(); i++)
            {
            	for(int k=0; k it = tech.getNodes(); it.hasNext(); )
        	updatePrimitiveNodeConnections(it.next());

        // Loading current elements from the XML information if available
//        Xml.MenuPalette menuPalette = Job.getUserInterface().getXmlPalette(tech);
//        int numColumns = menuPalette.numColumns;
        for (int i = 0; i < menuPalette.menuBoxes.size(); i++)
        {
            List menuBoxList = menuPalette.menuBoxes.get(i);
            if (menuBoxList == null || menuBoxList.isEmpty()) continue;
            setCurrentContactNodeProto(tech, null, menuBoxList.get(0));
        }
    }

    /**
     * Method to set equivalent PortProto in a given technology. Used by wiring tool and set by TechPalette.
     * @param obj
     */
    public void setEquivalentPortProto(Object obj)
    {
        NodeProto np;
        if (obj instanceof NodeProto)
            np = (NodeProto)obj;
        else if (obj instanceof NodeInst)
            np = ((NodeInst)obj).getProto();
        else
            return; // not the valid object
        if (!(np instanceof PrimitiveNode))
            return;

        PrimitiveNode pn = (PrimitiveNode)np;
        if (pn.isNotUsed()) return;

        if (!pn.getFunction().isContact()) return; // only for contacts

        int numPorts = np.getNumPorts();
        assert(numPorts == 1); // basic assumption for now.
        PortProto pp = pn.getPort(0);
        if (pp instanceof PrimitivePort)
        {
            PrimitivePort p = (PrimitivePort)pp;
            List list = getArcNamesSorted(p);
            // adding to list of equivalent ports
            String key = getKeyFromList(list); // lets see what we get
            List l = equivalentPortProtoMap.get(key);
            if (l == null)
            {
                l = new ArrayList();
                equivalentPortProtoMap.put(key, l);
            }
            l.add(p);
        }
    }

    /**
     * Method to provide list of arc names per PrimitivePort. Used in equivalent functions.
     * It doesn't include Generic arc protos.
     * @param p
     * @return Sorted list contained the arc names
     */
    private static List getArcNamesSorted(PrimitivePort p)
    {
        ArcProto[] arcs = p.getConnections();
        List list = new ArrayList(arcs.length);
        // removing the generic arcs
        for (int i = 0; i < arcs.length; i++)
        {
            ArcProto ap = arcs[i];
            if (ap.getTechnology() == Generic.tech()) continue;
            list.add(ap.getName());
        }
//        assert(list.size() > 0); // basic assumption for now
        // Sort list so it could be used for equivalent ports
        Collections.sort(list);
        return list;
    }

    private static String getKeyFromList(List list)
    {
        String key = "";
        for (String s : list)
        {
            key += "@" + s;
        }
        return key;
    }

    /**
     * Method to provide list of equivalent ports based on the arc protos associated to it.
     * @param p the Port to examine for equivalence.
     * @return a List of equivalent ports.
     */
    public List getEquivalentPorts(PrimitivePort p)
    {
        List list = getArcNamesSorted(p);
        return equivalentPortProtoMap.get(getKeyFromList(list));
    }

    /**
	 * Method to return the "current" ArcProto, as maintained by the user interface.
	 * The current ArcProto is highlighted with a bolder red border in the component menu on the left.
	 * @return the "current" ArcProto, as maintained by the user interface.
	 */
	public ArcProto getCurrentArcProto() { return currentArcProto; }

	/**
	 * Method to set the "current" ArcProto but only temporarily.
	 * This does not update the display in the component menu, and it is expected that
	 * the call will be reset to the "true current" ArcProto soon.
	 * This is used to force the routing planners to use the correct arc.
	 * @param ap the new "current" ArcProto.
	 */
	public void setCurrentArcProtoTemporarily(ArcProto ap)
	{
		currentArcProto = ap;
	}

	/**
	 * Method to set the "current" ArcProto, as maintained by the user interface.
	 * The current ArcProto is highlighted with a bolder red border in the component menu on the left.
	 * @param ap the new "current" ArcProto.
	 */
	public void setCurrentArcProto(ArcProto ap)
	{
		currentArcProto = ap;
		WindowFrame wf = WindowFrame.getCurrentWindowFrame(false);
		if (wf != null) wf.getPaletteTab().arcProtoChanged();
	}

	private static AudioClip clickSound = null;
	private static boolean hasSound = true;

	public static void playSound()
	{
		if (!hasSound) return;

		if (clickSound == null)
		{
			// first time: see if there is a sound card
			try
			{
				hasSound = javax.sound.sampled.AudioSystem.getMixerInfo().length > 0;
				if (!hasSound) return;
			}
			catch (Throwable t)
			{
				hasSound = false;
				return;
			}

			// initialize the click sound
			URL url = Resources.getURLResource(TopLevel.class, "Click.wav");
			if (url == null) { hasSound = false;   return; }
			clickSound = Applet.newAudioClip(url);
		}

		// play the sound
		clickSound.play();
	}

	/**
	 * Method to switch libraries and handle technology editing details.
	 */
	public static void setCurrentLibrary(Library lib)
	{
        assert SwingUtilities.isEventDispatchThread();
        Job.getExtendedUserInterface().setCurrentLibrary(lib);
	}

	/****************************** PROJECT PREFERENCES *****************************************/

	/**
	 * Method to get default technique in Tech Palette.
	 * The default is "mocmos".
	 * @return the default technology to use in Tech Palette
	 */
	public static String getDefaultTechnology() { return getDefaultTechnologySetting().getString(); }
	/**
	 * Returns project preference to tell default technique in Tech Palette.
	 * @return project preference to tell default technique in Tech Palette.
	 */
	public static Setting getDefaultTechnologySetting() { return ToolSettings.getDefaultTechnologySetting(); }

	/**
	 * Method to choose the layout Technology to use when schematics are found.
	 * This is important in Spice deck generation (for example) because the Spice primitives may
	 * say "2x3" on them, but a real technology (such as "mocmos") must be found to convert these pure
	 * numbers to real spacings for the deck.
	 * The default is the MOSIS CMOS technology.
	 * @return the Technology to use when schematics are found.
	 */
	public static Technology getSchematicTechnology()
	{
		String t = getSchematicTechnologySetting().getString();
		Technology tech = Technology.findTechnology(t);
		if (tech == null) return Technology.getMocmosTechnology();
		return tech;
	}
	/**
	 * Returns project preference to tell the layout Technology to use when schematics are found.
	 * This is important in Spice deck generation (for example) because the Spice primitives may
	 * say "2x3" on them, but a real technology (such as "mocmos") must be found to convert these pure
	 * numbers to real spacings for the deck.
	 * @return project preference to tell the Technology to use when schematics are found.
	 */
	public static Setting getSchematicTechnologySetting() { return ToolSettings.getSchematicTechnologySetting(); }

	/**
	 * Method to choose the layout Technology to use when schematics are found, by default.
	 * @return the Technology to use when schematics are found, by default.
	 */
	public static Technology getFactorySchematicTechnology()
	{
		String t = (String)getSchematicTechnologySetting().getFactoryValue();
		Technology tech = Technology.findTechnology(t);
		if (tech == null) return Technology.getMocmosTechnology();
		return tech;
	}

	/**
	 * Method to tell whether to include the date and Electric version in output files.
	 * The default is "true".
	 * @return true if the system should include the date and Electric version in output files.
	 */
	public static boolean isIncludeDateAndVersionInOutput() { return getIncludeDateAndVersionInOutputSetting().getBoolean(); }
	/**
	 * Returns project preference to tell whether to include the date and Electric version in output files.
	 * @return project preference to tell whether to include the date and Electric version in output files.
	 */
	public static Setting getIncludeDateAndVersionInOutputSetting() { return ToolSettings.getIncludeDateAndVersionInOutputSetting(); }

	/**
	 * Method to tell whether the process is a PSubstrate process. If true, it will ignore the pwell spacing rule.
	 * The default is "true".
	 * @return true if the process is PSubstrate
	 */
	public static Setting getPSubstrateProcessLayoutTechnologySetting() {return ToolSettings.getPSubstrateProcessLayoutTechnologySetting(); }
	public static boolean isPSubstrateProcessLayoutTechnology() {return getPSubstrateProcessLayoutTechnologySetting().getBoolean();}

	/**
	 * Returns project preference with additional technologies.
	 * @return project preference with additional technologies.
	 */
	public static Setting getSoftTechnologiesSetting() { return ToolSettings.getSoftTechnologiesSetting(); }

	/****************************** ICON GENERATION PREFERENCES ******************************/

	private static Pref cacheIconGenInputSide = Pref.makeIntPref("IconGenInputSide", tool.prefs, 0);
	/**
	 * Method to tell where Input ports should go on generated icons.
	 * @return information about where Input ports should go on generated icons.
	 * 0: left (the default)   1: right   2: top   3: bottom
	 */
	public static int getIconGenInputSide() { return cacheIconGenInputSide.getInt(); }
	/**
	 * Method to set where Input ports should go on generated icons.
	 * @param side information about where Input ports should go on generated icons.
	 * 0: left   1: right   2: top   3: bottom
	 */
	public static void setIconGenInputSide(int side) { cacheIconGenInputSide.setInt(side); }
	/**
	 * Method to tell where Input ports should go on generated icons, by default.
	 * @return information about where Input ports should go on generated icons, by default.
	 * 0: left   1: right   2: top   3: bottom
	 */
	public static int getFactoryIconGenInputSide() { return cacheIconGenInputSide.getIntFactoryValue(); }

	private static Pref cacheIconGenOutputSide = Pref.makeIntPref("IconGenOutputSide", tool.prefs, 1);
	/**
	 * Method to tell where Output ports should go on generated icons.
	 * @return information about where Output ports should go on generated icons.
	 * 0: left   1: right (the default)   2: top   3: bottom
	 */
	public static int getIconGenOutputSide() { return cacheIconGenOutputSide.getInt(); }
	/**
	 * Method to set where Output ports should go on generated icons.
	 * @param side information about where Output ports should go on generated icons.
	 * 0: left   1: right (the default)   2: top   3: bottom
	 */
	public static void setIconGenOutputSide(int side) { cacheIconGenOutputSide.setInt(side); }
	/**
	 * Method to tell where Output ports should go on generated icons, by default.
	 * @return information about where Output ports should go on generated icons, by default.
	 * 0: left   1: right   2: top   3: bottom
	 */
	public static int getFactoryIconGenOutputSide() { return cacheIconGenOutputSide.getIntFactoryValue(); }

	private static Pref cacheIconGenBidirSide = Pref.makeIntPref("IconGenBidirSide", tool.prefs, 2);
	/**
	 * Method to tell where Bidirectional ports should go on generated icons.
	 * @return information about where Bidirectional ports should go on generated icons.
	 * 0: left   1: right   2: top (the default)   3: bottom
	 */
	public static int getIconGenBidirSide() { return cacheIconGenBidirSide.getInt(); }
	/**
	 * Method to set where Bidirectional ports should go on generated icons.
	 * @param side information about where Bidirectional ports should go on generated icons.
	 * 0: left   1: right   2: top (the default)   3: bottom
	 */
	public static void setIconGenBidirSide(int side) { cacheIconGenBidirSide.setInt(side); }
	/**
	 * Method to tell where Bidirectional ports should go on generated icons, by default.
	 * @return information about where Bidirectional ports should go on generated icons, by default.
	 * 0: left   1: right   2: top   3: bottom
	 */
	public static int getFactoryIconGenBidirSide() { return cacheIconGenBidirSide.getIntFactoryValue(); }

	private static Pref cacheIconGenPowerSide = Pref.makeIntPref("IconGenPowerSide", tool.prefs, 3);
	/**
	 * Method to tell where Power ports should go on generated icons.
	 * @return information about where Power ports should go on generated icons.
	 * 0: left   1: right   2: top   3: bottom (the default)
	 */
	public static int getIconGenPowerSide() { return cacheIconGenPowerSide.getInt(); }
	/**
	 * Method to set where Power ports should go on generated icons.
	 * @param side information about where Power ports should go on generated icons.
	 * 0: left   1: right   2: top   3: bottom (the default)
	 */
	public static void setIconGenPowerSide(int side) { cacheIconGenPowerSide.setInt(side); }
	/**
	 * Method to tell where Power ports should go on generated icons, by default.
	 * @return information about where Power ports should go on generated icons, by default.
	 * 0: left   1: right   2: top   3: bottom
	 */
	public static int getFactoryIconGenPowerSide() { return cacheIconGenPowerSide.getIntFactoryValue(); }

	private static Pref cacheIconGenGroundSide = Pref.makeIntPref("IconGenGroundSide", tool.prefs, 3);
	/**
	 * Method to tell where Ground ports should go on generated icons.
	 * @return information about where Ground ports should go on generated icons.
	 * 0: left   1: right   2: top   3: bottom (the default)
	 */
	public static int getIconGenGroundSide() { return cacheIconGenGroundSide.getInt(); }
	/**
	 * Method to set where Ground ports should go on generated icons.
	 * @param side information about where Ground ports should go on generated icons.
	 * 0: left   1: right   2: top   3: bottom (the default)
	 */
	public static void setIconGenGroundSide(int side) { cacheIconGenGroundSide.setInt(side); }
	/**
	 * Method to tell where Ground ports should go on generated icons, by default.
	 * @return information about where Ground ports should go on generated icons, by default.
	 * 0: left   1: right   2: top   3: bottom
	 */
	public static int getFactoryIconGenGroundSide() { return cacheIconGenGroundSide.getIntFactoryValue(); }

	private static Pref cacheIconGenClockSide = Pref.makeIntPref("IconGenClockSide", tool.prefs, 0);
	/**
	 * Method to tell where Clock ports should go on generated icons.
	 * @return information about where Clock ports should go on generated icons.
	 * 0: left (the default)   1: right   2: top   3: bottom
	 */
	public static int getIconGenClockSide() { return cacheIconGenClockSide.getInt(); }
	/**
	 * Method to set where Clock ports should go on generated icons.
	 * @param side information about where Clock ports should go on generated icons.
	 * 0: left (the default)   1: right   2: top   3: bottom
	 */
	public static void setIconGenClockSide(int side) { cacheIconGenClockSide.setInt(side); }
	/**
	 * Method to tell where Clock ports should go on generated icons, by default.
	 * @return information about where Clock ports should go on generated icons, by default.
	 * 0: left   1: right   2: top   3: bottom
	 */
	public static int getFactoryIconGenClockSide() { return cacheIconGenClockSide.getIntFactoryValue(); }

	private static Pref cacheIconGenTopRot = Pref.makeIntPref("IconGenTopRot", tool.prefs, 0);
	/**
	 * Method to tell what angle Top ports should go on generated icons.
	 * This applies only when ports are placed by "location", not "characteristic".
	 * @return information about what angle Top ports should go on generated icons.
	 * 0: normal   1: rotate 90 degrees   2: rotate 180 degrees   3: rotate 270 degrees
	 */
	public static int getIconGenTopRot() { return cacheIconGenTopRot.getInt(); }
	/**
	 * Method to set what angle Top ports should go on generated icons.
	 * This applies only when ports are placed by "location", not "characteristic".
	 * @param rot information about what angle Top ports should go on generated icons.
	 * 0: normal   1: rotate 90 degrees   2: rotate 180 degrees   3: rotate 270 degrees
	 */
	public static void setIconGenTopRot(int rot) { cacheIconGenTopRot.setInt(rot); }
	/**
	 * Method to tell what angle Top ports should go on generated icons, by default.
	 * This applies only when ports are placed by "location", not "characteristic".
	 * @return information about what angle Top ports should go on generated icons, by default.
	 * 0: normal   1: rotate 90 degrees   2: rotate 180 degrees   3: rotate 270 degrees
	 */
	public static int getFactoryIconGenTopRot() { return cacheIconGenTopRot.getIntFactoryValue(); }

	private static Pref cacheIconGenBottomRot = Pref.makeIntPref("IconGenBottomRot", tool.prefs, 0);
	/**
	 * Method to tell what angle Bottom ports should go on generated icons.
	 * This applies only when ports are placed by "location", not "characteristic".
	 * @return information about what angle Bottom ports should go on generated icons.
	 * 0: normal   1: rotate 90 degrees   2: rotate 180 degrees   3: rotate 270 degrees
	 */
	public static int getIconGenBottomRot() { return cacheIconGenBottomRot.getInt(); }
	/**
	 * Method to set what angle Bottom ports should go on generated icons.
	 * This applies only when ports are placed by "location", not "characteristic".
	 * @param rot information about what angle Bottom ports should go on generated icons.
	 * 0: normal   1: rotate 90 degrees   2: rotate 180 degrees   3: rotate 270 degrees
	 */
	public static void setIconGenBottomRot(int rot) { cacheIconGenBottomRot.setInt(rot); }
	/**
	 * Method to tell what angle Bottom ports should go on generated icons, by default.
	 * This applies only when ports are placed by "location", not "characteristic".
	 * @return information about what angle Bottom ports should go on generated icons, by default.
	 * 0: normal   1: rotate 90 degrees   2: rotate 180 degrees   3: rotate 270 degrees
	 */
	public static int getFactoryIconGenBottomRot() { return cacheIconGenBottomRot.getIntFactoryValue(); }

	private static Pref cacheIconGenLeftRot = Pref.makeIntPref("IconGenLeftRot", tool.prefs, 0);
	/**
	 * Method to tell what angle Left ports should go on generated icons.
	 * This applies only when ports are placed by "location", not "characteristic".
	 * @return information about what angle Left ports should go on generated icons.
	 * 0: normal   1: rotate 90 degrees   2: rotate 180 degrees   3: rotate 270 degrees
	 */
	public static int getIconGenLeftRot() { return cacheIconGenLeftRot.getInt(); }
	/**
	 * Method to set what angle Left ports should go on generated icons.
	 * This applies only when ports are placed by "location", not "characteristic".
	 * @param rot information about what angle Left ports should go on generated icons.
	 * 0: normal   1: rotate 90 degrees   2: rotate 180 degrees   3: rotate 270 degrees
	 */
	public static void setIconGenLeftRot(int rot) { cacheIconGenLeftRot.setInt(rot); }
	/**
	 * Method to tell what angle Left ports should go on generated icons, by default.
	 * This applies only when ports are placed by "location", not "characteristic".
	 * @return information about what angle Left ports should go on generated icons, by default.
	 * 0: normal   1: rotate 90 degrees   2: rotate 180 degrees   3: rotate 270 degrees
	 */
	public static int getFactoryIconGenLeftRot() { return cacheIconGenLeftRot.getIntFactoryValue(); }

	private static Pref cacheIconGenRightRot = Pref.makeIntPref("IconGenRightRot", tool.prefs, 0);
	/**
	 * Method to tell what angle Right ports should go on generated icons.
	 * This applies only when ports are placed by "location", not "characteristic".
	 * @return information about what angle Right ports should go on generated icons.
	 * 0: normal   1: rotate 90 degrees   2: rotate 180 degrees   3: rotate 270 degrees
	 */
	public static int getIconGenRightRot() { return cacheIconGenRightRot.getInt(); }
	/**
	 * Method to set what angle Right ports should go on generated icons.
	 * This applies only when ports are placed by "location", not "characteristic".
	 * @param rot information about what angle Right ports should go on generated icons.
	 * 0: normal   1: rotate 90 degrees   2: rotate 180 degrees   3: rotate 270 degrees
	 */
	public static void setIconGenRightRot(int rot) { cacheIconGenRightRot.setInt(rot); }
	/**
	 * Method to tell what angle Right ports should go on generated icons, by default.
	 * This applies only when ports are placed by "location", not "characteristic".
	 * @return information about what angle Right ports should go on generated icons, by default.
	 * 0: normal   1: rotate 90 degrees   2: rotate 180 degrees   3: rotate 270 degrees
	 */
	public static int getFactoryIconGenRightRot() { return cacheIconGenRightRot.getIntFactoryValue(); }

	private static Pref cacheIconGenTopSkip = Pref.makeBooleanPref("IconGenTopSkip", tool.prefs, false);
	/**
	 * Method to tell whether ports should not be placed on the Top of the generated icons.
	 * This applies only when ports are placed by "location", not "characteristic".
	 * @return true if ports should not be placed on the Top of the generated icons.
	 */
	public static boolean isIconGenTopSkip() { return cacheIconGenTopSkip.getBoolean(); }
	/**
	 * Method to set whether ports should not be placed on the Top of the generated icons.
	 * This applies only when ports are placed by "location", not "characteristic".
	 * @param s true if ports should not be placed on the Top of the generated icons.
	 */
	public static void setIconGenTopSkip(boolean s) { cacheIconGenTopSkip.setBoolean(s); }
	/**
	 * Method to tell whether ports should not be placed on the Top of the generated icons, by default.
	 * This applies only when ports are placed by "location", not "characteristic".
	 * @return true if ports should not be placed on the Top of the generated icons, by default.
	 */
	public static boolean isFactoryIconGenTopSkip() { return cacheIconGenTopSkip.getBooleanFactoryValue(); }

	private static Pref cacheIconGenBottomSkip = Pref.makeBooleanPref("IconGenBottomSkip", tool.prefs, false);
	/**
	 * Method to tell whether ports should not be placed on the Bottom of the generated icons.
	 * This applies only when ports are placed by "location", not "characteristic".
	 * @return true if ports should not be placed on the Bottom of the generated icons.
	 */
	public static boolean isIconGenBottomSkip() { return cacheIconGenBottomSkip.getBoolean(); }
	/**
	 * Method to set whether ports should not be placed on the Bottom of the generated icons.
	 * This applies only when ports are placed by "location", not "characteristic".
	 * @param s true if ports should not be placed on the Bottom of the generated icons.
	 */
	public static void setIconGenBottomSkip(boolean s) { cacheIconGenBottomSkip.setBoolean(s); }
	/**
	 * Method to tell whether ports should not be placed on the Bottom of the generated icons, by default.
	 * This applies only when ports are placed by "location", not "characteristic".
	 * @return true if ports should not be placed on the Bottom of the generated icons, by default.
	 */
	public static boolean isFactoryIconGenBottomSkip() { return cacheIconGenBottomSkip.getBooleanFactoryValue(); }

	private static Pref cacheIconGenLeftSkip = Pref.makeBooleanPref("IconGenLeftSkip", tool.prefs, false);
	/**
	 * Method to tell whether ports should not be placed on the Left of the generated icons.
	 * This applies only when ports are placed by "location", not "characteristic".
	 * @return true if ports should not be placed on the Left of the generated icons.
	 */
	public static boolean isIconGenLeftSkip() { return cacheIconGenLeftSkip.getBoolean(); }
	/**
	 * Method to set whether ports should not be placed on the Left of the generated icons.
	 * This applies only when ports are placed by "location", not "characteristic".
	 * @param s true if ports should not be placed on the Left of the generated icons.
	 */
	public static void setIconGenLeftSkip(boolean s) { cacheIconGenLeftSkip.setBoolean(s); }
	/**
	 * Method to tell whether ports should not be placed on the Left of the generated icons, by default.
	 * This applies only when ports are placed by "location", not "characteristic".
	 * @return true if ports should not be placed on the Left of the generated icons, by default.
	 */
	public static boolean isFactoryIconGenLeftSkip() { return cacheIconGenLeftSkip.getBooleanFactoryValue(); }

	private static Pref cacheIconGenRightSkip = Pref.makeBooleanPref("IconGenRightSkip", tool.prefs, false);
	/**
	 * Method to tell whether ports should not be placed on the Right of the generated icons.
	 * This applies only when ports are placed by "location", not "characteristic".
	 * @return true if ports should not be placed on the Right of the generated icons.
	 */
	public static boolean isIconGenRightSkip() { return cacheIconGenRightSkip.getBoolean(); }
	/**
	 * Method to set whether ports should not be placed on the Right of the generated icons.
	 * This applies only when ports are placed by "location", not "characteristic".
	 * @param s true if ports should not be placed on the Right of the generated icons.
	 */
	public static void setIconGenRightSkip(boolean s) { cacheIconGenRightSkip.setBoolean(s); }
	/**
	 * Method to tell whether ports should not be placed on the Right of the generated icons, by default.
	 * This applies only when ports are placed by "location", not "characteristic".
	 * @return true if ports should not be placed on the Right of the generated icons, by default.
	 */
	public static boolean isFactoryIconGenRightSkip() { return cacheIconGenRightSkip.getBooleanFactoryValue(); }

	/****************************** PORT AND EXPORT PREFERENCES ******************************/

	/**
	 * Method to tell how to display ports.
	 * @return how to display ports.
	 * 0: full port names (the default).
	 * 1: short port names (stopping at the first nonalphabetic character).
	 * 2: ports drawn as crosses.
	 */
	public static int getPortDisplayLevel() { return UserInterfaceMain.getGraphicsPreferences().portDisplayLevel; }
	/**
	 * Method to tell how to display exports.
	 * @return how to display exports.
	 * 0: full export names (the default).
	 * 1: short export names (stopping at the first nonalphabetic character).
	 * 2: exports drawn as crosses.
	 */
	public static int getExportDisplayLevel() { return UserInterfaceMain.getGraphicsPreferences().exportDisplayLevel; }

	private static Pref cacheMoveNodeWithExport = Pref.makeBooleanPref("MoveNodeWithExport", tool.prefs, false);
	/**
	 * Method to tell whether to move a node when its export name moves.
	 * The default is "false", which means that the export text can move independently.
	 * @return true to move a node when its export name moves.
	 */
	public static boolean isMoveNodeWithExport() { return cacheMoveNodeWithExport.getBoolean(); }
	/**
	 * Method to set whether to move a node when its export name moves.
	 * @param on true to move a node when its export name moves.
	 */
	public static void setMoveNodeWithExport(boolean on) { cacheMoveNodeWithExport.setBoolean(on); }
	/**
	 * Method to tell whether to move a node when its export name moves, by default.
	 * @return true to move a node when its export name moves, by default.
	 */
	public static boolean isFactoryMoveNodeWithExport() { return cacheMoveNodeWithExport.getBooleanFactoryValue(); }

	/****************************** SELECTION PREFERENCES ******************************/

	private static Pref cacheEasySelectionOfCellInstances = Pref.makeBooleanPref("EasySelectionOfCellInstances", tool.prefs, true);
	/**
	 * Method to tell whether cell instances are all be easy-to-select.
	 * The default is "true".
	 * @return true if cell instances are all be easy-to-select.
	 */
	public static boolean isEasySelectionOfCellInstances() { return cacheEasySelectionOfCellInstances.getBoolean(); }
	/**
	 * Method to set whether cell instances are all be easy-to-select.
	 * @param on true if cell instances are all to be easy-to-select.
	 */
	public static void setEasySelectionOfCellInstances(boolean on) { cacheEasySelectionOfCellInstances.setBoolean(on); }
	/**
	 * Method to tell whether cell instances are all be easy-to-select by default.
	 * @return true if cell instances are all be easy-to-select by default.
	 */
	public static boolean isFactoryEasySelectionOfCellInstances() { return cacheEasySelectionOfCellInstances.getBooleanFactoryValue(); }

	private static Pref cacheDraggingMustEncloseObjects = Pref.makeBooleanPref("DraggingMustEncloseObjects", tool.prefs, false);
	/**
	 * Method to tell whether dragging a selection rectangle must completely enclose objects in order to select them.
	 * The default is "false", which means that the selection rectangle need only touch an object in order to select it.
	 * @return true if dragging a selection rectangle must completely enclose objects in order to select them.
	 */
	public static boolean isDraggingMustEncloseObjects() { return cacheDraggingMustEncloseObjects.getBoolean(); }
	/**
	 * Method to set whether dragging a selection rectangle must completely enclose objects in order to select them.
	 * @param on true if dragging a selection rectangle must completely enclose objects in order to select them.
	 */
	public static void setDraggingMustEncloseObjects(boolean on) { cacheDraggingMustEncloseObjects.setBoolean(on); }
	/**
	 * Method to tell whether dragging a selection rectangle must completely enclose objects in order to select them, by default.
	 * @return true if dragging a selection rectangle must completely enclose objects in order to select them, by default.
	 */
	public static boolean isFactoryDraggingMustEncloseObjects() { return cacheDraggingMustEncloseObjects.getBooleanFactoryValue(); }

	private static Pref cacheMouseOverHighlighting = Pref.makeBooleanPref("UseMouseOverHighlighting", tool.prefs, true);
	/**
	 * Method to tell whether dragging a selection rectangle must completely enclose objects in order to select them.
	 * The default is "false", which means that the selection rectangle need only touch an object in order to select it.
	 * @return true if dragging a selection rectangle must completely enclose objects in order to select them.
	 */
	public static boolean isMouseOverHighlightingEnabled() { return cacheMouseOverHighlighting.getBoolean(); }
	/**
	 * Method to set whether dragging a selection rectangle must completely enclose objects in order to select them.
	 * @param on true if dragging a selection rectangle must completely enclose objects in order to select them.
	 */
	public static void setMouseOverHighlightingEnabled(boolean on) { cacheMouseOverHighlighting.setBoolean(on); }
	/**
	 * Method to tell whether dragging a selection rectangle must completely enclose objects in order to select them, by default.
	 * @return true if dragging a selection rectangle must completely enclose objects in order to select them, by default.
	 */
	public static boolean isFactoryMouseOverHighlightingEnabled() { return cacheMouseOverHighlighting.getBooleanFactoryValue(); }

	private static Pref cacheHighlightConnectedObjects = Pref.makeBooleanPref("HighlightConnectedObjects", tool.prefs, true);
	/**
	 * Method to set whether to highlight objects connected to the selected object
	 * @return true to highlight objects connected to the selected object, false otherwise
	 */
	public static boolean isHighlightConnectedObjects() { return cacheHighlightConnectedObjects.getBoolean(); }
	/**
	 * Method to get whether to highlight objects connected to the selected object
	 * @param on true to highlight objects connected to the selected object
	 */
	public static void setHighlightConnectedObjects(boolean on) { cacheHighlightConnectedObjects.setBoolean(on); }
	/**
	 * Method to set whether to highlight objects connected to the selected object, by default.
	 * @return true to highlight objects connected to the selected object by default, false otherwise
	 */
	public static boolean isFactoryHighlightConnectedObjects() { return cacheHighlightConnectedObjects.getBooleanFactoryValue(); }

	private static Pref cacheHighlightInvisibleObjects = Pref.makeBooleanPref("HighlightInvisibleObjects", tool.prefs, false);
	/**
	 * Method to set whether to highlight objects whose layers are all invisible.
	 * @return true to highlight objects whose layers are all invisible.
	 */
	public static boolean isHighlightInvisibleObjects() { return cacheHighlightInvisibleObjects.getBoolean(); }
	/**
	 * Method to get whether to highlight objects whose layers are all invisible.
	 * @param on true to highlight objects whose layers are all invisible.
	 */
	public static void setHighlightInvisibleObjects(boolean on) { cacheHighlightInvisibleObjects.setBoolean(on); }
	/**
	 * Method to set whether to highlight objects whose layers are all invisible, by default.
	 * @return true to highlight objects whose layers are all invisible by default.
	 */
	public static boolean isFactoryHighlightInvisibleObjects() { return cacheHighlightInvisibleObjects.getBooleanFactoryValue(); }

	private static Pref cacheRoutingMode = Pref.makeBooleanPref("RoutingMode", tool.prefs, false);
	/**
	 * Method to set whether the "click/zoom/wire" mode is a "routing" mode.
	 * Routing mode disallows changes to cell instances and also to topology changes.
	 * @return true if the "click/zoom/wire" mode is a "routing" mode.
	 */
	public static boolean isRoutingMode() { return cacheRoutingMode.getBoolean(); }
	/**
	 * Method to get whether whether the "click/zoom/wire" mode is a "routing" mode.
	 * @param on true if the "click/zoom/wire" mode is a "routing" mode.
	 */
	public static void setRoutingMode(boolean on) { cacheRoutingMode.setBoolean(on); }
	/**
	 * Method to set whether whether the "click/zoom/wire" mode is a "routing" mode, by default.
	 * @return true if the "click/zoom/wire" mode is a "routing" mode, by default.
	 */
	public static boolean isFactoryRoutingMode() { return cacheRoutingMode.getBooleanFactoryValue(); }

	/****************************** GRID AND ALIGNMENT PREFERENCES ******************************/

	private static Pref cacheDefGridXSpacing = Pref.makeDoublePref("DefGridXSpacing", tool.prefs, 1);
	/**
	 * Method to return the default spacing of grid dots in the X direction.
	 * The default is 1.
	 * @return the default spacing of grid dots in the X direction.
	 */
	public static double getDefGridXSpacing() { return cacheDefGridXSpacing.getDouble(); }
	/**
	 * Method to set the default spacing of grid dots in the X direction.
	 * @param dist the default spacing of grid dots in the X direction.
	 */
	public static void setDefGridXSpacing(double dist) { cacheDefGridXSpacing.setDouble(dist); }
	/**
	 * Method to return the default spacing of grid dots in the X direction (factory setting).
	 * @return the default spacing of grid dots in the X direction (factory setting).
	 */
	public static double getFactoryDefGridXSpacing() { return cacheDefGridXSpacing.getDoubleFactoryValue(); }

	private static Pref cacheDefGridYSpacing = Pref.makeDoublePref("DefGridYSpacing", tool.prefs, 1);
	/**
	 * Method to return the default spacing of grid dots in the Y direction.
	 * The default is 1.
	 * @return the default spacing of grid dots in the Y direction.
	 */
	public static double getDefGridYSpacing() { return cacheDefGridYSpacing.getDouble(); }
	/**
	 * Method to set the default spacing of grid dots in the Y direction.
	 * @param dist the default spacing of grid dots in the Y direction.
	 */
	public static void setDefGridYSpacing(double dist) { cacheDefGridYSpacing.setDouble(dist); }
	/**
	 * Method to return the default spacing of grid dots in the Y direction (factory setting).
	 * @return the default spacing of grid dots in the Y direction (factory setting).
	 */
	public static double getFactoryDefGridYSpacing() { return cacheDefGridYSpacing.getDoubleFactoryValue(); }

	private static Pref cacheDefGridXBoldFrequency = Pref.makeIntPref("DefGridXBoldFrequency", tool.prefs, 10);
	/**
	 * Method to return the default frequency of bold grid dots in the X direction.
	 * The default is 10.
	 * @return the default frequency of bold grid dots in the X direction.
	 */
	public static int getDefGridXBoldFrequency() { return cacheDefGridXBoldFrequency.getInt(); }
	/**
	 * Method to set the default frequency of bold grid dots in the X direction.
	 * @param dist the default frequency of bold grid dots in the X direction.
	 */
	public static void setDefGridXBoldFrequency(int dist) { cacheDefGridXBoldFrequency.setInt(dist); }
	/**
	 * Method to return the default frequency of bold grid dots in the X direction (factory setting).
	 * @return the default frequency of bold grid dots in the X direction (factory setting).
	 */
	public static int getFactoryDefGridXBoldFrequency() { return cacheDefGridXBoldFrequency.getIntFactoryValue(); }

	private static Pref cacheDefGridYBoldFrequency = Pref.makeIntPref("DefGridYBoldFrequency", tool.prefs, 10);
	/**
	 * Method to return the default frequency of bold grid dots in the Y direction.
	 * The default is 10.
	 * @return the default frequency of bold grid dots in the Y direction.
	 */
	public static int getDefGridYBoldFrequency() { return cacheDefGridYBoldFrequency.getInt(); }
	/**
	 * Method to set the default frequency of bold grid dots in the Y direction.
	 * @param dist the default frequency of bold grid dots in the Y direction.
	 */
	public static void setDefGridYBoldFrequency(int dist) { cacheDefGridYBoldFrequency.setInt(dist); }
	/**
	 * Method to return the default frequency of bold grid dots in the Y direction (factory setting).
	 * @return the default frequency of bold grid dots in the Y direction (factory setting).
	 */
	public static int getFactoryDefGridYBoldFrequency() { return cacheDefGridYBoldFrequency.getIntFactoryValue(); }

	private static Pref cacheGridAlignMeasurementCursor = Pref.makeBooleanPref("GridAlignMeasurementCursor", tool.prefs, false);
	/**
	 * Method to tell whether the "Measurement" mode snaps the cursor to grid-aligned positions.
	 * The default is false.
	 * @return true if "Measurement" mode snaps the cursor to grid-aligned positions.
	 */
	public static boolean isGridAlignMeasurementCursor() { return cacheGridAlignMeasurementCursor.getBoolean(); }
	/**
	 * Method to set whether the "Measurement" mode snaps the cursor to grid-aligned positions.
	 * @param dist true if "Measurement" mode snaps the cursor to grid-aligned positions.
	 */
	public static void setGridAlignMeasurementCursor(boolean dist) { cacheGridAlignMeasurementCursor.setBoolean(dist); }
	/**
	 * Method to tell whether the "Measurement" mode snaps the cursor to grid-aligned positions, by default.
	 * @return true if "Measurement" mode snaps the cursor to grid-aligned positions, by default.
	 */
	public static boolean isFactoryGridAlignMeasurementCursor() { return cacheGridAlignMeasurementCursor.getBooleanFactoryValue(); }

	/**
	 * Method to return the default alignment of objects to the grid.
	 * The default is (1,1), meaning that placement and movement should land on whole grid units.
	 * @return the default alignment of objects to the grid.
	 */
	public static EDimension getAlignmentToGrid() {
        return UserInterfaceMain.getEditingPreferences().getAlignmentToGrid();
    }

	/**
	 * Method to return index of the current alignment.
	 * @return the index of the current alignment.
	 */
	public static int getAlignmentToGridIndex() {
        return UserInterfaceMain.getEditingPreferences().getAlignmentToGridIndex();
    }

	/**
	 * Method to return an array of five grid alignment values.
	 * @return an array of five grid alignment values.
	 */
	public static EDimension[] getAlignmentToGridVector() {
        return UserInterfaceMain.getEditingPreferences().getAlignmentToGridVector();
	}

    /**
	 * Method to set the default alignment of objects to the grid.
	 * @param dist the array of grid alignment values.
	 * @param current the index in the array that is the current grid alignment.
	 */
	public static void setAlignmentToGridVector(EDimension[] dist, int current)
	{
        assert SwingUtilities.isEventDispatchThread();
        UserInterfaceMain.setEditingPreferences(UserInterfaceMain.getEditingPreferences().withAlignment(dist, current));
	}

	private static Pref cacheShowGridAxes = Pref.makeBooleanPref("ShowGridAxes", tool.prefs, false);
	/**
	 * Method to return true if grid axes are shown.
	 * Grid axes are solid lines passing through the origin.
	 * The default is false.
	 * @return true if grid axes are shown.
	 */
	public static boolean isGridAxesShown() { return cacheShowGridAxes.getBoolean(); }
	/**
	 * Method to set if grid axes are shown.
	 * Grid axes are solid lines passing through the origin.
	 * @param s true if grid axes are shown.
	 */
	public static void setGridAxesShown(boolean s) { cacheShowGridAxes.setBoolean(s); }
	/**
	 * Method to return true if grid axes are shown, by default.
	 * Grid axes are solid lines passing through the origin.
	 * @return true if grid axes are shown, by default.
	 */
	public static boolean isFactoryGridAxesShown() { return cacheShowGridAxes.getBooleanFactoryValue(); }

	/****************************** TEXT PREFERENCES ******************************/

	/**
	 * Method to tell whether to draw text of particular text type.
	 * The default is "true".
     * @param textType specified text type
	 * @return true if the system should text of specified type.
	 */
    public static boolean isTextVisibilityOn(TextDescriptor.TextType textType) {
        return UserInterfaceMain.getGraphicsPreferences().isTextVisibilityOn(textType);
    }

	/**
	 * Method to tell whether to draw text that resides on nodes.
	 * This text includes the node name and any parameters or attributes on it.
	 * The default is "true".
	 * @return true if the system should draw text that resides on nodes.
	 */
	public static boolean isTextVisibilityOnNode() { return isTextVisibilityOn(TextDescriptor.TextType.NODE); }
	/**
	 * Method to tell whether to draw text that resides on arcs.
	 * This text includes the arc name and any parameters or attributes on it.
	 * The default is "true".
	 * @return true if the system should draw text that resides on arcs.
	 */
	public static boolean isTextVisibilityOnArc() { return isTextVisibilityOn(TextDescriptor.TextType.ARC); }
	/**
	 * Method to tell whether to draw text that resides on ports.
	 * This text includes the port name and any parameters or attributes on it.
	 * The default is "true".
	 * @return true if the system should draw text that resides on ports.
	 */
	public static boolean isTextVisibilityOnPort() { return isTextVisibilityOn(TextDescriptor.TextType.PORT); }
	/**
	 * Method to tell whether to draw text that resides on exports.
	 * This text includes the export name and any parameters or attributes on it.
	 * The default is "true".
	 * @return true if the system should draw text that resides on exports.
	 */
	public static boolean isTextVisibilityOnExport() { return isTextVisibilityOn(TextDescriptor.TextType.EXPORT); }
	/**
	 * Method to tell whether to draw text annotation text.
	 * Annotation text is not attached to any node or arc, but appears to move freely about the cell.
	 * In implementation, they are displayable Variables on Generic:invisible-pin nodes.
	 * The default is "true".
	 * @return true if the system should draw annotation text.
	 */
	public static boolean isTextVisibilityOnAnnotation() { return isTextVisibilityOn(TextDescriptor.TextType.ANNOTATION); }
	/**
	 * Method to tell whether to draw the name of on cell instances.
	 * The default is "true".
	 * @return true if the system should draw the name of on cell instances.
	 */
	public static boolean isTextVisibilityOnInstance() { return isTextVisibilityOn(TextDescriptor.TextType.INSTANCE); }
	/**
	 * Method to tell whether to draw text that resides on the cell.
	 * This includes the current cell's parameters or attributes (for example, spice templates).
	 * The default is "true".
	 * @return true if the system should draw text that resides on the cell.
	 */
	public static boolean isTextVisibilityOnCell() { return isTextVisibilityOn(TextDescriptor.TextType.CELL); }

	/**
	 * Method to get the default font to use on the display.
	 * The default is "SansSerif".
	 * @return the default font to use on the display.
	 */
	public static String getDefaultFont() { return UserInterfaceMain.getGraphicsPreferences().defaultFont; }
	/**
	 * Method to get the factory default font to use on the display.
	 * @return the factory default font to use on the display.
	 */
	public static String getFactoryDefaultFont() { return GraphicsPreferences.FACTORY_DEFAULT_FONT; }

	private static Pref cacheDefaultTextCellFont = Pref.makeStringPref("DefaultTextCellFont", tool.prefs, "SansSerif");
	/**
	 * Method to get the default font to use when editing textual cells.
	 * The default is "SansSerif".
	 * @return the default font to use when editing textual cells.
	 */
	public static String getDefaultTextCellFont() { return cacheDefaultTextCellFont.getString(); }
	/**
	 * Method to set the default font to use when editing textual cells.
	 * @param f the default font to use when editing textual cells.
	 */
	public static void setDefaultTextCellFont(String f) { cacheDefaultTextCellFont.setString(f); }
	/**
	 * Method to get the factory default font to use when editing textual cells.
	 * @return the factory default font to use when editing textual cells.
	 */
	public static String getFactoryDefaultTextCellFont() { return cacheDefaultTextCellFont.getStringFactoryValue(); }

	private static Pref cacheDefaultTextCellSize = Pref.makeIntPref("DefaultTextCellSize", tool.prefs, 12);
	/**
	 * Method to tell the size of text in textual cells.
	 * The default is "12".
	 * @return the size of text in textual cells.
	 */
	public static int getDefaultTextCellSize() { return cacheDefaultTextCellSize.getInt(); }
	/**
	 * Method to set the size of text in textual cells.
	 * @param s the size of text in textual cells.
	 */
	public static void setDefaultTextCellSize(int s) { cacheDefaultTextCellSize.setInt(s); }
	/**
	 * Method to tell the size of text in textual cells, by default.
	 * @return the size of text in textual cells, by default.
	 */
	public static int getFactoryDefaultTextCellSize() { return cacheDefaultTextCellSize.getIntFactoryValue(); }

	private static Pref cacheGlobalTextScale = Pref.makeDoublePref("TextGlobalScale", tool.prefs, 1);
	/**
	 * Method to tell the default global text scale factor.
	 * This factor is the initial text scaling factor for new windows and
	 * enlarges or reduces all displayed text.
	 * The default is "1".
	 * @return the default global text scale factor.
	 */
	public static double getGlobalTextScale() { return cacheGlobalTextScale.getDouble(); }
	/**
	 * Method to set the default global text scale factor.
	 * This factor is the initial text scaling factor for new windows and
	 * enlarges or reduces all displayed text.
	 * @param s the default global text scale.
	 */
	public static void setGlobalTextScale(double s) { cacheGlobalTextScale.setDouble(s); }
	/**
	 * Method to tell the factory default global text scale factor.
	 * This factor is the initial text scaling factor for new windows and
	 * enlarges or reduces all displayed text.
	 * @return the factory default global text scale factor.
	 */
	public static double getFactoryGlobalTextScale() { return cacheGlobalTextScale.getDoubleFactoryValue(); }

	private static Pref cacheDefaultTextExternalEditor = Pref.makeStringPref("DefaultTextExternalEditor", tool.prefs, "");
	/**
	 * Method to get the program to invoke when externally editing textual cells.
	 * The default is blank.
	 * @return the program to invoke when externally editing textual cells.
	 */
	public static String getDefaultTextExternalEditor() { return cacheDefaultTextExternalEditor.getString(); }
	/**
	 * Method to set the program to invoke when externally editing textual cells.
	 * @param e the program to invoke when externally editing textual cells.
	 */
	public static void setDefaultTextExternalEditor(String e) { cacheDefaultTextExternalEditor.setString(e); }
	/**
	 * Method to get the program to invoke when externally editing textual cells, by default.
	 * @return the program to invoke when externally editing textual cells, by default.
	 */
	public static String getFactoryDefaultTextExternalEditor() { return cacheDefaultTextExternalEditor.getStringFactoryValue(); }

	/****************************** FRAME PREFERENCES ******************************/

	private static Pref cacheFrameCompanyName = Pref.makeStringPref("FrameCompanyName", tool.prefs, "");
	/**
	 * Method to return the company name to use in schematic frames.
	 * The company information sits in a block in the lower-right corner.
	 * The default is "".
	 * @return the company name to use in schematic frames.
	 */
	public static String getFrameCompanyName() { return cacheFrameCompanyName.getString(); }
	/**
	 * Method to set the company name to use in schematic frames.
	 * The company information sits in a block in the lower-right corner.
	 * @param c the company name to use in schematic frames.
	 */
	public static void setFrameCompanyName(String c) { cacheFrameCompanyName.setString(c); }
	/**
	 * Method to return the company name to use in schematic frames, by default.
	 * The company information sits in a block in the lower-right corner.
	 * @return the company name to use in schematic frames, by default.
	 */
	public static String getFactoryFrameCompanyName() { return cacheFrameCompanyName.getStringFactoryValue(); }

	private static Pref cacheFrameDesignerName = Pref.makeStringPref("FrameDesignerName", tool.prefs, "");
	/**
	 * Method to return the designer name to use in schematic frames.
	 * The designer information sits in a block in the lower-right corner.
	 * The default is "".
	 * @return the designer name to use in schematic frames.
	 */
	public static String getFrameDesignerName() { return cacheFrameDesignerName.getString(); }
	/**
	 * Method to set the designer name to use in schematic frames.
	 * The designer information sits in a block in the lower-right corner.
	 * @param c the designer name to use in schematic frames.
	 */
	public static void setFrameDesignerName(String c) { cacheFrameDesignerName.setString(c); }
	/**
	 * Method to return the designer name to use in schematic frames, by default.
	 * The designer information sits in a block in the lower-right corner.
	 * @return the designer name to use in schematic frames, by default.
	 */
	public static String getFactoryFrameDesignerName() { return cacheFrameDesignerName.getStringFactoryValue(); }

	private static Pref cacheFrameProjectName = Pref.makeStringPref("FrameProjectName", tool.prefs, "");
	/**
	 * Method to return the project name to use in schematic frames.
	 * The project information sits in a block in the lower-right corner.
	 * The default is "".
	 * @return the project name to use in schematic frames.
	 */
	public static String getFrameProjectName() { return cacheFrameProjectName.getString(); }
	/**
	 * Method to set the project name to use in schematic frames.
	 * The project information sits in a block in the lower-right corner.
	 * @param c the project name to use in schematic frames.
	 */
	public static void setFrameProjectName(String c) { cacheFrameProjectName.setString(c); }
	/**
	 * Method to return the project name to use in schematic frames, by default.
	 * The project information sits in a block in the lower-right corner.
	 * @return the project name to use in schematic frames, by default.
	 */
	public static String getFactoryFrameProjectName() { return cacheFrameProjectName.getStringFactoryValue(); }

	/****************************** COLOR PREFERENCES ******************************/

	public enum ColorPrefType {
        /** color of the background on the display. The default is "light gray". */
        BACKGROUND("Background",                    Color.LIGHT_GRAY),
        /** color of the grid on the display. The default is "black". */
        GRID("Grid",                                Color.BLACK),
        /** color of the measurement ruler on the display. The default is "white". */
        MEASUREMENT("Measurement",                  Color.WHITE),
        /** color of the highlight on the display. The default is "white". */
        HIGHLIGHT("Highlight",                      Color.WHITE),
        NODE_HIGHLIGHT("NodeHighlight",             Color.BLUE),
        /** color of the highlight on the display. The default is "white". */
        MOUSEOVER_HIGHLIGHT("MouseOverHighlight",   new Color(51,255,255)),
        /** color of the port highlight on the display. The default is "yellow". */
		PORT_HIGHLIGHT("PortHighlight",             Color.YELLOW),
        /** color of the text on the display. The default is "black". */
        TEXT("Text",                                Color.BLACK),
        /** color of the instance outlines on the display. The default is "black". */
        INSTANCE("InstanceOutline",                 Color.BLACK),
        /**  color of the border around cells drawn "down in place". The default is "red". */
        DOWNINPLACEBORDER("DownInPlaceBorder",      Color.RED),
        /** color of the waveform window background. The default is "black". */
		WAVE_BACKGROUND("WaveformBackground",       Color.BLACK),
        /** color of the waveform window foreground. This includes lines and text. The default is "white". */
        WAVE_FOREGROUND("WaveformForeground",       Color.WHITE),
        /** color of the traces in waveform windows. Applies only when not a "multistate" display, which uses many colors.
         * The default is "red".
         */
        WAVE_STIMULI("WaveformStimuli",             Color.RED),
        /** color of waveform window traces that have "off" strength. The default is "blue". */
        WAVE_OFF_STRENGTH("WaveformStrengthOff",    Color.BLUE),
        /** color of waveform window traces that have "node" strength. The default is "green". */
		WAVE_NODE_STRENGTH("WaveformStrengthNode",  Color.GREEN),
        /** color of waveform window traces that have "gate" strength. The default is "magenta". */
        WAVE_GATE_STRENGTH("WaveformStrengthGate",  Color.MAGENTA),
        /** color of waveform window traces that have "power" strength. The default is "light gray". */
        WAVE_POWER_STRENGTH("WaveformStrengthPower",Color.LIGHT_GRAY),
        /** color of cross-probe traces from the waveform window that are "low".
         * These are lines drawn on the schematic or layout to correspond with the value in the waveform window.
         * The default is "blue".
         */
        WAVE_CROSS_LOW("WaveformCrossProbeLow",     Color.BLUE),
        /** color of cross-probe traces from the waveform window that are "high".
         * These are lines drawn on the schematic or layout to correspond with the value in the waveform window.
         * The default is "green".
         */
		WAVE_CROSS_HIGH("WaveformCrossProbeHigh",   Color.GREEN),
        /** color of cross-probe traces from the waveform window that are "undefined".
         * These are lines drawn on the schematic or layout to correspond with the value in the waveform window.
         * The default is "black".
         */
        WAVE_CROSS_UNDEF("WaveformCrossProbeX",     Color.BLACK),
        /** color of cross-probe traces from the waveform window that are "floating".
         * These are lines drawn on the schematic or layout to correspond with the value in the waveform window.
         * The default is "light_grey".
         */
        WAVE_CROSS_FLOAT("WaveformCrossProbeZ",     Color.LIGHT_GRAY),

        /** color of the cell instance on the 3D display. The default is "gray". */
        INSTANCE_3D("3DColorInstanceCell", Color.GRAY),
        /** color of the highlighted instance on the 3D display. The default is "gray". */
        HIGHLIGHT_3D("3DColorHighlighted", Color.GRAY),
        /** the ambiental color on the 3D display. The default is "gray". */
        AMBIENT_3D("3DColorAmbient", Color.GRAY),
        /** color of the axis X on the 3D display. The default is "red". */
        AXIS_X_3D("3DColorAxisX", Color.RED),
        /** color of the axis X on the 3D display. The default is "blue". */
        AXIS_Y_3D("3DColorAxisY", Color.BLUE),
        /** color of the axis X on the 3D display. The default is "green". */
        AXIS_Z_3D("3DColorAxisZ", Color.GREEN),
        /** color of directional light on the 3D display. The default is "gray". */
        DIRECTIONAL_LIGHT_3D("3DColorDirectionalLight", Color.GRAY);

        private final String prefKey;
        private final Color factoryDefault;

        public String getPrefKey() { return prefKey; }
        public Color getFactoryDefaultColor() { return factoryDefault; }

        private ColorPrefType(String prefKey, Color factoryDefault) {
            this.prefKey = "Color" + prefKey;
            this.factoryDefault = factoryDefault;
        }
    }

	/**
	 * Method to get the color of a given special layer on the display.
	 * @param pref the special layer in question.
	 * @return color of the special layer.
	 */
	public static int getColor(ColorPrefType pref) {return UserInterfaceMain.getGraphicsPreferences().getColor(pref).getRGB() & GraphicsPreferences.RGB_MASK;}

	/**
	 * Method to set the color of a given special layer
	 * @param pref the special layer to change.
	 * @param color new color for that special layer.
	 */
	public static void setColor(ColorPrefType pref, int color)
	{
        UserInterfaceMain.setGraphicsPreferences(UserInterfaceMain.getGraphicsPreferences().withColor(pref, new Color(color)));
	}

	/**
	 * Method to reset to the factory color of a given special layer
	 * @param pref the special layer to reset.
	 */
	public static void resetFactoryColor(ColorPrefType pref)
	{
        UserInterfaceMain.setGraphicsPreferences(UserInterfaceMain.getGraphicsPreferences().withColor(pref, pref.getFactoryDefaultColor()));
	}

	/****************************** UNITS PREFERENCES ******************************/

	private static Pref cacheDistanceUnits = Pref.makeIntServerPref("DistanceUnit", tool.prefs, -1);
	/**
	 * Method to get current distance units.
	 * The default is "scalable units".
	 * @return the current distance units.
	 * Returns null to use scalable units.
	 */
	public static TextUtils.UnitScale getDistanceUnits()
	{
		int unitIndex = cacheDistanceUnits.getInt();
		if (unitIndex < 0) return null;
		return TextUtils.UnitScale.findFromIndex(unitIndex);
	}
	/**
	 * Method to set the current distance units.
	 * @param us the current distance units (null to use scalable units).
	 */
	public static void setDistanceUnits(TextUtils.UnitScale us)
	{
		int unitIndex = -1;
		if (us != null) unitIndex = us.getIndex();
		cacheDistanceUnits.setInt(unitIndex);
	}
	/**
	 * Method to get default distance units.
	 * @return the default distance units.
	 * Returns null to use scalable units.
	 */
	public static TextUtils.UnitScale getFactoryDistanceUnits()
	{
		int unitIndex = cacheDistanceUnits.getIntFactoryValue();
		if (unitIndex < 0) return null;
		return TextUtils.UnitScale.findFromIndex(unitIndex);
	}

	private static Pref cacheResistanceUnits = Pref.makeIntPref("ResistanceUnits", tool.prefs, TextUtils.UnitScale.NONE.getIndex());
	/**
	 * Method to get current resistance units.
	 * The default is "ohms".
	 * @return the current resistance units.
	 */
	public static TextUtils.UnitScale getResistanceUnits()
	{
		return TextUtils.UnitScale.findFromIndex(cacheResistanceUnits.getInt());
	}
	/**
	 * Method to set the current resistance units.
	 * @param us the current resistance units.
	 */
	public static void setResistanceUnits(TextUtils.UnitScale us)
	{
		cacheResistanceUnits.setInt(us.getIndex());
	}
	/**
	 * Method to get default resistance units.
	 * @return the default resistance units.
	 */
	public static TextUtils.UnitScale getFactoryResistanceUnits()
	{
		return TextUtils.UnitScale.findFromIndex(cacheResistanceUnits.getIntFactoryValue());
	}

	private static Pref cacheCapacitanceUnits = Pref.makeIntPref("CapacitanceUnits", tool.prefs, TextUtils.UnitScale.PICO.getIndex());
	/**
	 * Method to get current capacitance units.
	 * The default is "picofarads".
	 * @return the current capacitance units.
	 */
	public static TextUtils.UnitScale getCapacitanceUnits()
	{
		return TextUtils.UnitScale.findFromIndex(cacheCapacitanceUnits.getInt());
	}
	/**
	 * Method to set the current capacitance units.
	 * @param us the current capacitance units.
	 */
	public static void setCapacitanceUnits(TextUtils.UnitScale us)
	{
		cacheCapacitanceUnits.setInt(us.getIndex());
	}
	/**
	 * Method to get default capacitance units.
	 * @return the default capacitance units.
	 */
	public static TextUtils.UnitScale getFactoryCapacitanceUnits()
	{
		return TextUtils.UnitScale.findFromIndex(cacheCapacitanceUnits.getIntFactoryValue());
	}

	private static Pref cacheInductanceUnits = Pref.makeIntPref("InductanceUnits", tool.prefs, TextUtils.UnitScale.NANO.getIndex());
	/**
	 * Method to get current inductance units.
	 * The default is "nanohenrys".
	 * @return the current inductance units.
	 */
	public static TextUtils.UnitScale getInductanceUnits()
	{
		return TextUtils.UnitScale.findFromIndex(cacheInductanceUnits.getInt());
	}
	/**
	 * Method to set the current inductance units.
	 * @param us the current inductance units.
	 */
	public static void setInductanceUnits(TextUtils.UnitScale us)
	{
		cacheInductanceUnits.setInt(us.getIndex());
	}
	/**
	 * Method to get default inductance units.
	 * @return the default inductance units.
	 */
	public static TextUtils.UnitScale getFactoryInductanceUnits()
	{
		return TextUtils.UnitScale.findFromIndex(cacheInductanceUnits.getIntFactoryValue());
	}

	private static Pref cacheAmperageUnits = Pref.makeIntPref("AmperageUnits", tool.prefs, TextUtils.UnitScale.MILLI.getIndex());
	/**
	 * Method to get current amperage (current) units.
	 * The default is "milliamps".
	 * @return the current amperage (current) units.
	 */
	public static TextUtils.UnitScale getAmperageUnits()
	{
		return TextUtils.UnitScale.findFromIndex(cacheAmperageUnits.getInt());
	}
	/**
	 * Method to set the current amperage (current) units.
	 * @param us the current amperage (current) units.
	 */
	public static void setAmperageUnits(TextUtils.UnitScale us)
	{
		cacheAmperageUnits.setInt(us.getIndex());
	}
	/**
	 * Method to get default amperage (current) units.
	 * @return the default amperage (current) units.
	 */
	public static TextUtils.UnitScale getFactoryAmperageUnits()
	{
		return TextUtils.UnitScale.findFromIndex(cacheAmperageUnits.getIntFactoryValue());
	}

	private static Pref cacheVoltageUnits = Pref.makeIntPref("VoltageUnits", tool.prefs, TextUtils.UnitScale.NONE.getIndex());
	/**
	 * Method to get current voltage units.
	 * The default is "volts".
	 * @return the current voltage) units.
	 */
	public static TextUtils.UnitScale getVoltageUnits()
	{
		return TextUtils.UnitScale.findFromIndex(cacheVoltageUnits.getInt());
	}
	/**
	 * Method to set the current voltage units.
	 * @param us the current voltage units.
	 */
	public static void setVoltageUnits(TextUtils.UnitScale us)
	{
		cacheVoltageUnits.setInt(us.getIndex());
	}
	/**
	 * Method to get default voltage units.
	 * @return the default voltage) units.
	 */
	public static TextUtils.UnitScale getFactoryVoltageUnits()
	{
		return TextUtils.UnitScale.findFromIndex(cacheVoltageUnits.getIntFactoryValue());
	}

	private static Pref cacheTimeUnits = Pref.makeIntPref("TimeUnits", tool.prefs, TextUtils.UnitScale.NONE.getIndex());
	/**
	 * Method to get current time units.
	 * The default is "seconds".
	 * @return the current time units.
	 */
	public static TextUtils.UnitScale getTimeUnits()
	{
		return TextUtils.UnitScale.findFromIndex(cacheTimeUnits.getInt());
	}
	/**
	 * Method to set the current time units.
	 * @param us the current time units.
	 */
	public static void setTimeUnits(TextUtils.UnitScale us)
	{
		cacheTimeUnits.setInt(us.getIndex());
	}
	/**
	 * Method to get default time units.
	 * @return the default time units.
	 */
	public static TextUtils.UnitScale getFactoryTimeUnits()
	{
		return TextUtils.UnitScale.findFromIndex(cacheTimeUnits.getIntFactoryValue());
	}

	/****************************** MISCELLANEOUS PREFERENCES ******************************/

	private static Pref cacheWorkingDirectory = Pref.makeStringPref("WorkingDirectory", tool.prefs, java.lang.System.getProperty("user.dir"));
	/**
	 * Method to get the path of the current working directory.
	 * The default is the Java "user directory".
	 * @return the path of the current working directory.
	 */
	public static String getWorkingDirectory() { return cacheWorkingDirectory.getString(); }

	/**
	 * Method to set the path of the current working directory.
	 * @param dir the path of the current working directory.
	 */
	public static void setWorkingDirectory(String dir) { cacheWorkingDirectory.setString(dir); }

    /** Root path to the regression directory */
	private static Pref cacheRegressionPath = Pref.makeStringPref("Regression Path", User.getUserTool().prefs, "");
	/**
	 * Method to get the path of the regression tests directory.
	 * The default is a String with invalid path.
	 * @return the path of the regression tests directory.
	 */
	public static String getRegressionPath()
	{
		return cacheRegressionPath.getString();
	}

	/**
	 * Method to set the path of the regression tests directory.
	 * @param s the path of the regression tests directory.
	 */
	public static void setRegressionPath(String s)
	{
		cacheRegressionPath.setString(s);
	}

	private static Pref cacheRecentlyOpenedLibraries = Pref.makeStringPref("RecentlyOpenedLibraries", tool.prefs, "");

	/**
	 * Get an array of File paths to recently opened libraries. These should be
	 * libraries the user opened, and not contain reference libraries opened as a
	 * result of a user opening a library.
	 * @return a list of file paths to libraries (without extension - no delib or jelib)
	 */
	public static String [] getRecentlyOpenedLibraries() {
		String libs = cacheRecentlyOpenedLibraries.getString();
		if (libs.equals("")) return new String[0];
		return libs.split("\n");
	}

	/**
	 * Add a file path (no extension) to a list of recently opened libraries.
	 * This should not include reference libraries opened as a side-affect of
	 * opening a library.
	 * @param s the file path to a library
	 */
	public static void addRecentlyOpenedLibrary(String s) {
		int maxLength = 16;
		String [] libs = getRecentlyOpenedLibraries();
		StringBuffer buf = new StringBuffer();
		buf.append(s);
		for (int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy