Java tutorial
/* * FindBugs - Find Bugs in Java programs * Copyright (C) 2006, University of Maryland * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307, USA */ package edu.umd.cs.findbugs.gui2; import java.awt.Frame; import java.awt.Rectangle; import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.prefs.BackingStoreException; import java.util.prefs.Preferences; import org.apache.commons.lang.StringUtils; import edu.umd.cs.findbugs.Plugin; import edu.umd.cs.findbugs.PluginException; import edu.umd.cs.findbugs.SystemProperties; /** * Saves all the stuff that should be saved for each run, like recent projects, * previous comments, the current docking layout and the sort order * * For project related things, look in ProjectSettings * * @author Dan * */ /* * GUISaveState uses the Preferences API, don't look for a file anywhere, there * isn't one, well... there might be, but its all system dependent where it is * and how its stored */ public class GUISaveState { private static GUISaveState instance; private static final String SORTERTABLELENGTH = "Sorter Length"; private static final String PREVCOMMENTSSIZE = "Previous Comments Size"; private static final String DOCKINGLAYOUT = "Docking Layout"; private static final String FRAME_BOUNDS = "Frame Bounds"; private static final String EXTENDED_WINDOW_STATE = "ExtendedWindowState"; static final int MAXNUMRECENTPROJECTS = 10; private static final Sortables[] DEFAULT_COLUMN_HEADERS = new Sortables[] { Sortables.CATEGORY, Sortables.BUGCODE, Sortables.TYPE, Sortables.DIVIDER, Sortables.BUG_RANK }; private static final String[] RECENTPROJECTKEYS = new String[MAXNUMRECENTPROJECTS]; private static final int MAXNUMPREVCOMMENTS = 10; private static final String[] COMMENTKEYS = new String[MAXNUMPREVCOMMENTS]; private static final String NUMPROJECTS = "NumberOfProjectsToLoad"; private static final String STARTERDIRECTORY = "Starter Directory"; private static final String SPLIT_MAIN = "MainSplit"; private static final String SPLIT_TREE_COMMENTS = "TreeCommentsSplit"; private static final String SPLIT_TOP = "TopSplit"; private static final String SPLIT_SUMMARY_NEW = "SummarySplitNew"; private static final String TAB_SIZE = "TabSize"; private static final String FONT_SIZE = "FontSize"; private static final String PACKAGE_PREFIX_SEGEMENTS = "PackagePrefixSegments"; private static final String ENABLED_PLUGINS = "EnabledPlugins"; private static final String DISABLED_PLUGINS = "DisabledPlugins"; private static final String CUSTOM_PLUGINS = "CustomPlugins"; static { for (int x = 0; x < RECENTPROJECTKEYS.length; x++) { RECENTPROJECTKEYS[x] = "Project" + x; } for (int x = 0; x < COMMENTKEYS.length; x++) { COMMENTKEYS[x] = "Comment" + x; } } private int splitMain; private int splitTreeComments; private int splitTop; private int splitSummary; private File starterDirectoryForLoadBugs; /** * List of previous comments by the user. */ private LinkedList<String> previousComments; private boolean useDefault = false; private SorterTableColumnModel starterTable; private Sortables[] sortColumns; private ArrayList<File> recentFiles; // private ArrayList<File> recentAnalyses; private byte[] dockingLayout; private Rectangle frameBounds; /** For Windows mainly - whether the window was maximized or not */ private int extendedWindowState; private int tabSize; // Tab size in the source code display. private float fontSize; // Font size of entire GUI. private int packagePrefixSegments; private List<String> enabledPlugins = new ArrayList<String>(); private List<String> disabledPlugins = new ArrayList<String>(); private final LinkedHashSet<URI> customPlugins = new LinkedHashSet<URI>(); private static String[] generateSorterKeys(int numSorters) { String[] result = new String[numSorters]; for (int x = 0; x < result.length; x++) { result[x] = "Sorter" + x; } return result; } public static synchronized GUISaveState getInstance() { if (instance == null) { instance = new GUISaveState(); } return instance; } public static void loadInstance() { GUISaveState newInstance = new GUISaveState(); newInstance.recentFiles = new ArrayList<File>(); Preferences p = Preferences.userNodeForPackage(GUISaveState.class); newInstance.tabSize = p.getInt(TAB_SIZE, 4); newInstance.fontSize = p.getFloat(FONT_SIZE, 12.0f); newInstance.starterDirectoryForLoadBugs = new File( p.get(GUISaveState.STARTERDIRECTORY, SystemProperties.getProperty("user.dir"))); int prevCommentsSize = p.getInt(GUISaveState.PREVCOMMENTSSIZE, 0); for (int x = 0; x < prevCommentsSize; x++) { String comment = p.get(GUISaveState.COMMENTKEYS[x], ""); newInstance.previousComments.add(comment); } int size = Math.min(MAXNUMRECENTPROJECTS, p.getInt(GUISaveState.NUMPROJECTS, 0)); for (int x = 0; x < size; x++) { newInstance.addRecentFile(new File(p.get(GUISaveState.RECENTPROJECTKEYS[x], ""))); } int sorterSize = p.getInt(GUISaveState.SORTERTABLELENGTH, -1); if (sorterSize != -1) { ArrayList<Sortables> sortColumns = new ArrayList<Sortables>(); String[] sortKeys = GUISaveState.generateSorterKeys(sorterSize); for (int x = 0; x < sorterSize; x++) { Sortables s = Sortables.getSortableByPrettyName(p.get(sortKeys[x], "*none*")); if (s == null) { if (MainFrame.GUI2_DEBUG) { System.err.println("Sort order was corrupted, using default sort order"); } newInstance.useDefault = true; break; } sortColumns.add(s); } if (!newInstance.useDefault) { // add in default columns Set<Sortables> missingSortColumns = new HashSet<Sortables>(Arrays.asList(DEFAULT_COLUMN_HEADERS)); missingSortColumns.removeAll(sortColumns); sortColumns.addAll(missingSortColumns); newInstance.sortColumns = sortColumns.toArray(new Sortables[sortColumns.size()]); } } else { newInstance.useDefault = true; } newInstance.dockingLayout = p.getByteArray(DOCKINGLAYOUT, new byte[0]); String boundsString = p.get(FRAME_BOUNDS, null); Rectangle r = new Rectangle(0, 0, 800, 650); if (boundsString != null) { String[] a = boundsString.split(",", 4); if (a.length > 0) { try { r.x = Math.max(0, Integer.parseInt(a[0])); } catch (NumberFormatException nfe) { assert true; } } if (a.length > 1) { try { r.y = Math.max(0, Integer.parseInt(a[1])); } catch (NumberFormatException nfe) { assert true; } } if (a.length > 2) { try { r.width = Math.max(40, Integer.parseInt(a[2])); } catch (NumberFormatException nfe) { assert true; } } if (a.length > 3) { try { r.height = Math.max(40, Integer.parseInt(a[3])); } catch (NumberFormatException nfe) { assert true; } } } newInstance.frameBounds = r; newInstance.extendedWindowState = p.getInt(EXTENDED_WINDOW_STATE, Frame.NORMAL); newInstance.splitMain = p.getInt(SPLIT_MAIN, 400); newInstance.splitSummary = p.getInt(SPLIT_SUMMARY_NEW, 400); newInstance.splitTop = p.getInt(SPLIT_TOP, -1); newInstance.splitTreeComments = p.getInt(SPLIT_TREE_COMMENTS, 250); newInstance.packagePrefixSegments = p.getInt(PACKAGE_PREFIX_SEGEMENTS, 3); String plugins = p.get(CUSTOM_PLUGINS, ""); if (plugins.length() > 0) { for (String s : plugins.split(" ")) { try { URI u = new URI(s); Plugin.addCustomPlugin(u); newInstance.customPlugins.add(u); } catch (PluginException e) { assert true; } catch (URISyntaxException e) { assert true; } } } String enabledPluginsString = p.get(ENABLED_PLUGINS, ""); String disabledPluginsString = p.get(DISABLED_PLUGINS, ""); newInstance.enabledPlugins = new ArrayList<String>(Arrays.asList(enabledPluginsString.split(","))); newInstance.disabledPlugins = new ArrayList<String>(Arrays.asList(disabledPluginsString.split(","))); instance = newInstance; } static void clear() { Preferences p = Preferences.userNodeForPackage(GUISaveState.class); try { p.clear(); } catch (BackingStoreException e) { Debug.println(e); } instance = new GUISaveState(); } private GUISaveState() { recentFiles = new ArrayList<File>(); previousComments = new LinkedList<String>(); } public int getTabSize() { return tabSize; } public void setTabSize(int tabSize) { this.tabSize = tabSize; } public int getPackagePrefixSegments() { return packagePrefixSegments; } public void setPackagePrefixSegments(int packagePrefixSegments) { this.packagePrefixSegments = packagePrefixSegments; } public byte[] getDockingLayout() { return dockingLayout; } public void setDockingLayout(byte[] dockingLayout) { this.dockingLayout = dockingLayout; } /** * This should be the method called to add a reused file for the recent * menu. */ public void fileReused(File f) { if (!recentFiles.contains(f)) { throw new IllegalStateException("Selected a recent project that doesn't exist?"); } else { recentFiles.remove(f); recentFiles.add(f); } } /** * This should be the method used to add a file for the recent menu. * * @param f */ public void addRecentFile(File f) { if (null != f) { recentFiles.add(f); } } /** * Returns the list of recent files. * * @return the list of recent files */ public ArrayList<File> getRecentFiles() { return recentFiles; } /** * Call to remove a file from the list. * * @param f */ public void fileNotFound(File f) { if (!recentFiles.contains(f)) { throw new IllegalStateException("Well no wonder it wasn't found, its not in the list."); } else { recentFiles.remove(f); } } /** * The file to start the loading of Bugs from. * * @return Returns the starterDirectoryForLoadBugs. */ public File getStarterDirectoryForLoadBugs() { return starterDirectoryForLoadBugs; } /** * @param f * The starterDirectoryForLoadBugs to set. */ public void setStarterDirectoryForLoadBugs(File f) { this.starterDirectoryForLoadBugs = f; } public void save() { Preferences p = Preferences.userNodeForPackage(GUISaveState.class); p.putInt(TAB_SIZE, tabSize); p.putFloat(FONT_SIZE, fontSize); try { p.put(STARTERDIRECTORY, starterDirectoryForLoadBugs.getCanonicalPath()); } catch (IOException e) { Debug.println(e); } int sorterLength = MainFrame.getInstance().getSorter().getColumnCount(); ArrayList<Sortables> sortables = MainFrame.getInstance().getSorter().getOrder(); p.putInt(GUISaveState.SORTERTABLELENGTH, sorterLength); String[] sorterKeys = GUISaveState.generateSorterKeys(sorterLength); for (int x = 0; x < sorterKeys.length; x++) { p.put(sorterKeys[x], sortables.get(x).prettyName); } p.putInt(GUISaveState.PREVCOMMENTSSIZE, previousComments.size()); for (int x = 0; x < previousComments.size(); x++) { String comment = previousComments.get(x); p.put(GUISaveState.COMMENTKEYS[x], comment); } int size = recentFiles.size(); while (recentFiles.size() > MAXNUMRECENTPROJECTS) { recentFiles.remove(0); } p.putInt(GUISaveState.NUMPROJECTS, Math.min(size, MAXNUMRECENTPROJECTS)); for (int x = 0; x < Math.min(size, MAXNUMRECENTPROJECTS); x++) { File file = recentFiles.get(x); p.put(GUISaveState.RECENTPROJECTKEYS[x], file.getAbsolutePath()); } p.putByteArray(DOCKINGLAYOUT, dockingLayout); p.put(FRAME_BOUNDS, frameBounds.x + "," + frameBounds.y + "," + frameBounds.width + "," + frameBounds.height); p.putInt(EXTENDED_WINDOW_STATE, extendedWindowState); p.putInt(SPLIT_MAIN, splitMain); p.putDouble(SPLIT_SUMMARY_NEW, splitSummary); p.putInt(SPLIT_TOP, splitTop); p.putInt(SPLIT_TREE_COMMENTS, splitTreeComments); p.putInt(PACKAGE_PREFIX_SEGEMENTS, packagePrefixSegments); p.put(ENABLED_PLUGINS, StringUtils.join(enabledPlugins, ',')); p.put(DISABLED_PLUGINS, StringUtils.join(disabledPlugins, ',')); p.put(CUSTOM_PLUGINS, StringUtils.join(customPlugins, ' ')); } /** * @return Returns the previousComments. */ public LinkedList<String> getPreviousComments() { return previousComments; } /** * @param previousComments * The previousComments to set. */ public void setPreviousComments(LinkedList<String> previousComments) { this.previousComments = previousComments; } /** * @return Returns the frame bounds Rectangle. */ public Rectangle getFrameBounds() { return frameBounds; } /** * @param frameBounds * The frame bourds Rectangle to set. */ public void setFrameBounds(Rectangle frameBounds) { this.frameBounds = frameBounds; } public int getExtendedWindowState() { return extendedWindowState; } public void setExtendedWindowState(int extendedWindowState) { this.extendedWindowState = extendedWindowState & ~Frame.ICONIFIED; // never save iconified state } /** * @return Returns the fontSize. */ public float getFontSize() { return fontSize; } /** * @param fontSize * The fontSize to set. */ public void setFontSize(float fontSize) { this.fontSize = fontSize; } /** * @return Returns the location of the main divider. */ public int getSplitMain() { return splitMain; } /** * @param splitMain * The location of the main divider to set. */ public void setSplitMain(int splitMain) { this.splitMain = splitMain; } /** * @return Returns the location of the summary divider. */ public int getSplitSummary() { return splitSummary; } /** * @param splitSummary * The location of the summar divider to set. */ public void setSplitSummary(int splitSummary) { this.splitSummary = splitSummary; } /** * @return Returns the location of the top divider. */ public int getSplitTop() { return splitTop; } /** * @param splitTop * The location of the top divider to set. */ public void setSplitTop(int splitTop) { this.splitTop = splitTop; } public void setPluginsEnabled(List<String> enabledPlugins, List<String> disabledPlugins) { this.enabledPlugins = new ArrayList<String>(enabledPlugins); this.disabledPlugins = new ArrayList<String>(disabledPlugins); } public void setPluginEnabled(String url) { this.enabledPlugins.add(url); } public List<String> getEnabledPlugins() { return enabledPlugins; } public Collection<URI> getCustomPlugins() { return customPlugins; } public boolean addCustomPlugin(URL u) { try { return customPlugins.add(u.toURI()); } catch (URISyntaxException e) { throw new IllegalArgumentException("Error converting to uri: " + u, e); } } public List<String> getDisabledPlugins() { return disabledPlugins; } public boolean removeCustomPlugin(URL pluginId) { try { return customPlugins.remove(pluginId.toURI()); } catch (URISyntaxException e) { throw new IllegalArgumentException("Error converting to uri: " + pluginId, e); } } SorterTableColumnModel getStarterTable() { if (starterTable != null) { return starterTable; } if (useDefault || sortColumns == null) { starterTable = new SorterTableColumnModel(GUISaveState.DEFAULT_COLUMN_HEADERS); } else { starterTable = new SorterTableColumnModel(sortColumns); } return starterTable; } }