// // @(#)GeneralPreferencePanel.java 4/2002 // // Copyright 2002-2004 Zachary DelProposto. All rights reserved. // Use is subject to license terms. // // // This program 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 2 of the License, or // (at your option) any later version. // // This program 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 this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // Or from http://www.gnu.org/ // package dip.gui.dialog.prefs; import dip.gui.ClientFrame; import dip.gui.OrderDisplayPanel; import dip.misc.SharedPrefs; import dip.misc.LRUCache; import dip.misc.Utils; import dip.gui.swing.XJFileChooser; import dip.gui.swing.AssocJComboBox; import dip.gui.map.MapRenderer2; // HIGLayout import cz.autel.dmi.HIGConstraints; import cz.autel.dmi.HIGLayout; // JDirectoryChooser import com.l2fprod.common.swing.JDirectoryChooser; import java.io.File; import java.util.Arrays; import java.util.ArrayList; import java.util.Set; import java.util.prefs.Preferences; import java.util.prefs.BackingStoreException; import java.text.Collator; import java.util.Iterator; import java.util.Map; import javax.swing.Box; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.JComboBox; import javax.swing.JSeparator; import java.awt.Component; import java.awt.FlowLayout; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; /** * General preferences. * <p> * Static methods are included to access (in a controlled manner) preference-controlled * functionality. * * */ public class GeneralPreferencePanel extends PreferencePanel { // constants public static final int BORDER = 10; // preference nodes keys public static final String NODE_SAVE_WINDOW_SETTINGS = "saveWindowSettings"; public static final String NODE_DEFAULT_GAME_DIR = "defaultGameDir"; public static final String NODE_SHOW_RESOLUTION_RESULTS = "showResolutionResults"; // recent files (w/o #) [if enabled] public static final String NODE_RECENT_FILE = "lastFile"; // window settings [if enabled] public static final String NODE_WINDOW_X = "windowX"; public static final String NODE_WINDOW_Y = "windowY"; public static final String NODE_WINDOW_WIDTH = "windowWidth"; public static final String NODE_WINDOW_HEIGHT = "windowHeight"; // order sort preference public static final String NODE_ORDER_SORTING = "orders.list.sorting"; public static final String NODE_ORDER_SORTING_REVERSE = "orders.list.sorting.reversed"; // boolean // map label preference public static final String NODE_MAP_LABEL_LEVEL = "map.label.level"; // # of recent files to save private static final int NUM_RECENT_FILES = 5; // LRU cache of files private static LRUCache fileCache = null; private static Collator collator = null; // UI Elements private JCheckBox saveWindowSettings; // save window settings (position, size) private JTextField saveDir; // default save-files directory private JButton browseSaveDir; // browse button for setting directory private JButton clearMRU; // clears most-recently-used file list private JCheckBox reverseSort; // reverse the order sort direction private AssocJComboBox orderSorting; // order sorting type private AssocJComboBox mapLabels; // map label level private JCheckBox showResolution; private ClientFrame cf = null; // UI text i18n constants private static final String TAB_NAME = "GPP.tabname"; private static final String GPP_SAVE_WINDOW_POS = "GPP.save_window_pos"; private static final String GPP_SAVE_DIR_TEXT = "GPP.save_dir_text"; private static final String GPP_SAVE_DIR_BUTTON = "GPP.save_dir_button"; private static final String GPP_SHOW_RESOLUTION_RESULTS = "GPP.show_resolution_results"; private static final String GPP_CLEAR_MRU_BUTTON = "GPP.clearmru.button"; private static final String GPP_CLEAR_MRU_TEXT = "GPP.clearmru.text"; private static final String GPP_MAP_LABEL_PREFIX = "GPP.map.label.level."; private static final String GPP_ORDER_SORT_PREFIX = "GPP.order.sort.type."; private static final String GPP_MAP_LABEL = "GPP.map.label.text"; private static final String GPP_MAP_LABEL_NOTE = "GPP.map.label.text.note"; private static final String GPP_ORDER_SORT_LABEL = "GPP.order.sort.label"; private static final String GPP_ORDER_SORT_DIRECTION = "GPP.order.sort.direction"; private static final String DIALOG_TITLE = "GPP.filedialog.title"; public GeneralPreferencePanel(final ClientFrame cf) { this.cf = cf; // create UI elements saveWindowSettings = new JCheckBox( Utils.getLocalString(GPP_SAVE_WINDOW_POS) ); showResolution = new JCheckBox( Utils.getLocalString(GPP_SHOW_RESOLUTION_RESULTS) ); saveDir = new JTextField(); saveDir.setEditable(false); browseSaveDir = new JButton( Utils.getLocalString(GPP_SAVE_DIR_BUTTON) ); browseSaveDir.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { directoryBrowse(); }// actionPerformed() }); clearMRU = new JButton( Utils.getLocalString(GPP_CLEAR_MRU_BUTTON) ); clearMRU.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { clearFileList(); cf.getClientMenu().updateRecentFiles(); }// actionPerformed() }); // setup associative arrays for comboboxes String[] arr = new String[] { MapRenderer2.VALUE_LABELS_NONE, MapRenderer2.VALUE_LABELS_BRIEF, MapRenderer2.VALUE_LABELS_FULL }; AssocJComboBox.AssociatedObj[] assocObjs = AssocJComboBox.AssociatedObj.createAssociatedObjects(arr, GPP_MAP_LABEL_PREFIX, MapRenderer2.VALUE_LABELS_NONE, true); mapLabels = new AssocJComboBox(assocObjs); // order sorting :: implement arr = new String[] { OrderDisplayPanel.SORT_POWER, OrderDisplayPanel.SORT_PROVINCE, OrderDisplayPanel.SORT_UNIT, OrderDisplayPanel.SORT_ORDER }; String[] arr2 = new String[] { Utils.getLocalString(OrderDisplayPanel.LABEL_SORT_POWER), Utils.getLocalString(OrderDisplayPanel.LABEL_SORT_PROVINCE), Utils.getLocalString(OrderDisplayPanel.LABEL_SORT_UNIT), Utils.getLocalString(OrderDisplayPanel.LABEL_SORT_ORDER) }; assocObjs = AssocJComboBox.AssociatedObj.createAssociatedObjects(arr, arr2, OrderDisplayPanel.SORT_POWER, true); orderSorting = new AssocJComboBox(assocObjs); reverseSort = new JCheckBox(Utils.getLocalString(GPP_ORDER_SORT_DIRECTION)); // update components getSettings(); // mini-panels JPanel clrPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); clrPanel.add( new JLabel(Utils.getLocalString(GPP_CLEAR_MRU_TEXT)) ); clrPanel.add(Box.createHorizontalStrut(5)); clrPanel.add(clearMRU); JPanel orderP = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); orderP.add( new JLabel(Utils.getLocalString(GPP_ORDER_SORT_LABEL)) ); orderP.add(Box.createHorizontalStrut(5)); orderP.add(orderSorting); orderP.add(Box.createHorizontalStrut(10)); orderP.add(reverseSort); JPanel mapP = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); mapP.add( new JLabel(Utils.getLocalString(GPP_MAP_LABEL)) ); mapP.add(Box.createHorizontalStrut(5)); mapP.add(mapLabels); // layout int h1[] = { BORDER, 0,8, 0,8, 0,8, 0,3,0,7, 36, // upto row 12 0,3,0,10, 0,8, 0, BORDER }; int w1[] = { BORDER, 10, 0, 5, 0, BORDER }; HIGLayout l1 = new HIGLayout(w1, h1); l1.setColumnWeight(3, 1); l1.setRowWeight(19, 1); setLayout(l1); HIGConstraints c = new HIGConstraints(); add(saveWindowSettings, c.rcwh(2,2,4,1,"l")); add(showResolution, c.rcwh(4,2,4,1,"l")); add(orderP, c.rcwh(6,2,4,1,"l")); add(mapP, c.rcwh(8,2,4,1,"l")); add(new JLabel(Utils.getLocalString(GPP_MAP_LABEL_NOTE)), c.rcwh(10,3,3,1,"ltb")); // separator bar (12) add(new JSeparator(), c.rcwh(12,2,4,1,"lr")); // save dir add(new JLabel( Utils.getLocalString(GPP_SAVE_DIR_TEXT) ), c.rcwh(13,2,4,1,"l")); add(saveDir, c.rcwh(15,3,1,1,"lr")); add(browseSaveDir, c.rcwh(15,5,1,1,"lrtb")); // clear MRU add(clrPanel, c.rcwh(17,2,4,1,"l")); }// GeneralPreferencePanel() private void directoryBrowse() { // setup JDirectoryChooser chooser = new JDirectoryChooser(); chooser.setMultiSelectionEnabled(false); // set directory String path = saveDir.getText(); if(!"".equals(path)) { chooser.setCurrentDirectory(new File(path)); } chooser.setDialogTitle(Utils.getLocalString(DIALOG_TITLE)); int choice = chooser.showDialog(cf, Utils.getLocalString(XJFileChooser.BTN_DIR_SELECT)); if(choice == JDirectoryChooser.APPROVE_OPTION) { saveDir.setText( chooser.getSelectedFile().getAbsolutePath() ); } }// directoryBrowse() public void apply() { Preferences prefs = SharedPrefs.getUserNode(); // apply settings prefs.putBoolean(NODE_SAVE_WINDOW_SETTINGS, saveWindowSettings.isSelected()); prefs.put(NODE_DEFAULT_GAME_DIR, saveDir.getText()); prefs.putBoolean(NODE_SHOW_RESOLUTION_RESULTS, showResolution.isSelected()); // map settings prefs.put(NODE_MAP_LABEL_LEVEL, (String) mapLabels.getSelectedValue()); // order settings prefs.putBoolean(NODE_ORDER_SORTING_REVERSE, reverseSort.isSelected()); prefs.put(NODE_ORDER_SORTING, (String) orderSorting.getSelectedValue()); try { prefs.flush(); } catch (BackingStoreException bse) {} }// apply() public void cancel() { // do nothing }// cancel() public void setDefault() { saveWindowSettings.setSelected(false); showResolution.setSelected(false); saveDir.setText(""); reverseSort.setSelected(false); orderSorting.reset(); mapLabels.reset(); }// applyDefault() public String getName() { return Utils.getLocalString(TAB_NAME); }// getName() private void getSettings() { Preferences prefs = SharedPrefs.getUserNode(); try { prefs.sync(); } catch (BackingStoreException bse) {} saveWindowSettings.setSelected(prefs.getBoolean(NODE_SAVE_WINDOW_SETTINGS, false)); showResolution.setSelected(prefs.getBoolean(NODE_SHOW_RESOLUTION_RESULTS, true)); saveDir.setText( prefs.get(NODE_DEFAULT_GAME_DIR, "") ); reverseSort.setSelected(prefs.getBoolean(NODE_ORDER_SORTING_REVERSE, false)); // get MapLabels setting final String mlSetting = MapRenderer2.parseLabelValue( prefs.get(NODE_MAP_LABEL_LEVEL, null), MapRenderer2.VALUE_LABELS_NONE); assert (mlSetting != null); mapLabels.setSelectedItem(mlSetting); // get order sorting setting final String osSetting = OrderDisplayPanel.parseSortValue( prefs.get(NODE_ORDER_SORTING, null), OrderDisplayPanel.SORT_PROVINCE); assert (mlSetting != null); orderSorting.setSelectedItem(osSetting); }// getSettings() /** * Get the Map label-level setting, as set by the User in * Preferences. Never returns null. */ public static String getMapLabelSetting() { Preferences prefs = SharedPrefs.getUserNode(); final String mlSetting = MapRenderer2.parseLabelValue(prefs.get(NODE_MAP_LABEL_LEVEL, null), MapRenderer2.VALUE_LABELS_NONE); assert (mlSetting != null); return mlSetting; }// getMapLabelSetting() /** * Get the order-sorting direction, as set by the user. * Returns <code>true</code> if sort direction is reversed. */ public static boolean getOrderSortReverse() { Preferences prefs = SharedPrefs.getUserNode(); return prefs.getBoolean(NODE_ORDER_SORTING_REVERSE, false); }// getOrderSortReverse() /** * Get the order-sorting mode, as set by the user. * Never returns null. */ public static String getOrderSortMode() { Preferences prefs = SharedPrefs.getUserNode(); final String osSetting = OrderDisplayPanel.parseSortValue( prefs.get(NODE_ORDER_SORTING, null), OrderDisplayPanel.SORT_PROVINCE); return osSetting; }// getOrderSortMode() public static void getWindowSettings(Component c) { Preferences prefs = SharedPrefs.getUserNode(); if( prefs.getBoolean(NODE_SAVE_WINDOW_SETTINGS, false) ) { int x = prefs.getInt(NODE_WINDOW_X, 50); int y = prefs.getInt(NODE_WINDOW_Y, 50 ); int w = prefs.getInt(NODE_WINDOW_WIDTH, 600); int h = prefs.getInt(NODE_WINDOW_HEIGHT, 400); c.setSize(w,h); c.setLocation(x,y); } else { c.setSize(Utils.getScreenSize(0.85f)); Utils.centerInScreen(c); } }// getWindowSettings() public static void saveWindowSettings(Component c) { Preferences prefs = SharedPrefs.getUserNode(); if( prefs.getBoolean(NODE_SAVE_WINDOW_SETTINGS, false) ) { prefs.putInt(NODE_WINDOW_X, c.getX()); prefs.putInt(NODE_WINDOW_Y, c.getY()); prefs.putInt(NODE_WINDOW_WIDTH, c.getWidth()); prefs.putInt(NODE_WINDOW_HEIGHT, c.getHeight()); } try { prefs.flush(); } catch (BackingStoreException bse) {} }// saveWindowSettings() // sort before returning; case insensitive // CALL THIS the first time public static String[] getRecentFileNamesFromPrefs() { if(fileCache == null) { // load from preferences Preferences prefs = SharedPrefs.getUserNode(); // get files ArrayList al = new ArrayList(NUM_RECENT_FILES); for(int i=0; i<NUM_RECENT_FILES; i++) { String s = prefs.get(NODE_RECENT_FILE+String.valueOf(i), ""); if(s != null && s.length() > 0) { // do NOT add file if it doesn't exist. File file = new File(s); if(file.exists()) { al.add( file ); } } } // add to cache & create a String of just the name fileCache = new LRUCache(NUM_RECENT_FILES); String[] s = new String[al.size()]; for(int i=0; i<al.size(); i++) { File file = (File) al.get(i); fileCache.put(file.getName(), file); s[i] = file.getName(); } // sort [note; should use CollationKey if sorting more items...] if(collator == null) { collator = Collator.getInstance(); collator.setStrength(Collator.PRIMARY); // ignore case } Arrays.sort(s, collator); return s; } return new String[0]; }// getRecentFileNamesFromPrefs() // this may return null!! public static File getFileFromName(String name) { if(fileCache != null) { return (File) fileCache.get(name); } return null; }// getFileFromName() // CALL THIS most of the time; use to update the names for the menu public static String[] getRecentFileNamesFromCache() { if(fileCache != null) { // load from cache; sort and check for file existence before returning ArrayList names = new ArrayList(NUM_RECENT_FILES); Iterator iter = fileCache.entrySet().iterator(); while(iter.hasNext()) { Map.Entry mapEntry = (Map.Entry) iter.next(); File file = (File) mapEntry.getValue(); if(file.exists()) { names.add( mapEntry.getKey() ); } } String[] fileNames = (String[]) names.toArray(new String[names.size()]); Arrays.sort(fileNames, collator); return fileNames; } return new String[0]; }// getRecentFilesNames() /** * This method updates the recent file name preferences. * <p> * It should be called every time a file is opened, and * every time "Save As" is called. * <p> * Don't forget to update menus as well, after calling this * method. */ public static void setRecentFileName(File file) { if(fileCache != null) { String name = file.getName(); if(fileCache.containsKey(name)) { fileCache.get(name); // update access order (if entry exists) } else { fileCache.put(name, file); } saveRecentFileNames(); } }// setRecentFileName() /** Clears the MRU file list. Does not update menu. */ public static void clearFileList() { if(fileCache != null) { fileCache.clear(); Preferences prefs = SharedPrefs.getUserNode(); for(int i=0; i<NUM_RECENT_FILES; i++) { prefs.remove( NODE_RECENT_FILE + String.valueOf(i) ); } try { prefs.flush(); } catch (BackingStoreException bse) {} } }// clearFileList() /** * Saves the recent file names * */ private static void saveRecentFileNames() { if(fileCache != null) { // get node Preferences prefs = SharedPrefs.getUserNode(); // use an iterator to preerve access-order. // save in reverse-order int idx = NUM_RECENT_FILES - 1; Iterator iter = fileCache.entrySet().iterator(); while(iter.hasNext()) { Map.Entry mapEntry = (Map.Entry) iter.next(); File file = (File) mapEntry.getValue(); prefs.put( (NODE_RECENT_FILE + String.valueOf(idx)), file.getPath() ); idx--; } // delete any empty entries. while(idx > 0) { prefs.remove( NODE_RECENT_FILE + String.valueOf(idx) ); idx--; } try { prefs.flush(); } catch (BackingStoreException bse) {} } }// saveRecentFileNames() /** Returns the default save-game directory, or an empty directory ("") if none. */ public static File getDefaultGameDir() { Preferences prefs = SharedPrefs.getUserNode(); return new File(prefs.get(NODE_DEFAULT_GAME_DIR, "")); }// getDefaultGameDir() /** Returns if we should automatically bring up the resolution results dialog */ public static boolean getShowResolutionResults() { return getSetting(NODE_SHOW_RESOLUTION_RESULTS, true); } /** Returns a given setting from preferences */ private static boolean getSetting(String key, boolean defaultValue) { Preferences prefs = SharedPrefs.getUserNode(); try { prefs.sync(); } catch (BackingStoreException bse) {} return prefs.getBoolean(key, defaultValue); }// getSetting() }// class GeneralPreferencePanel