//*********************************************************************************
// class jephem.gui.PreferencesDialog
// Software released under the General Public License (version 2 or later), available at
// http://www.gnu.org/copyleft/gpl.html
//*********************************************************************************
package jephem.gui;
import jephem.GlobalVar;
import jephem.tools.AstroPrefs;
import jephem.JEphemPrefs;
import jephem.astro.AstroContext;
import jephem.astro.solarsystem.SolarSystemConstants;
import jephem.astro.spacetime.SpaceConstants;
import jephem.astro.spacetime.UnitsConstants;
import jephem.util.Debug;
import tig.GeneralConstants;
import tig.TigBundle;
import tig.TigProperties;
import tig.Strings;
import tig.maths.Maths;
import tig.swing.SwingUtils;
import tig.swing.JTextField2;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import java.io.*;
/******************************************************************************
Modal dialog which permits to the user to choose the preferences of JEphem.
@author Thierry Graff
@history feb 20 2002 : creation.
@todo handle message if ressource bundles can't be loded
@todo put getTimeBundle and getSpaceBundle in GlobalVar ?
@todo handle message if LAF can't be changed
*********************************************************************************/
public class PreferencesDialog extends JDialog
implements GeneralConstants, SolarSystemConstants, SpaceConstants, UnitsConstants{
//=================================================================================
// INSTANCE VARIABLES
//=================================================================================
/** Variables expressing the current preferences. */
private int _lang;
/** content pane. */
private Container _contentPane;
/** Preferences tree. */
private JTree _prefTree;
/** The different option panes */
private JPanel _treePanel;
private JPanel _generalPanel;
private JPanel _astroPanel;
private JPanel _directoriesPanel;
private JPanel _keyboardShortcutsPanel;
private JPanel _curSelectedPanel;
/** Rigid areas to give the prefs panels a uniform size. */
private Component _horRigidArea;
private Component _verRigidArea;
/** GUI components */
// General panel
private JComboBox _cmbLAF;
private JButton _btnApplyLAF;
private JComboBox _cmbLang;
// Astro panel
private JComboBox _cmbAstroEngine;
private JTextField2 _txtPrecision;
// Dialog buttons
JButton _btnOK;
JButton _btnCancel;
//=================================================================================
// RESSOURCE BUNDLES (STATIC VARIABLES)
//=================================================================================
// ***** Ressource bundles. ******
private static TigBundle _myBundle, _galBundle, _astroBundle;
static{
_galBundle = GlobalVar.getBundle(GlobalVar.BUNDLE_GENERAL);
_astroBundle = GlobalVar.getBundle(GlobalVar.BUNDLE_ASTRO);
try{
_myBundle = new TigBundle(GlobalVar.getDirectory(GlobalVar.DIR_LANG) + FS + "PreferencesDialog.lang", GlobalVar.getLocale());
}
catch (IOException ioe){
Debug.traceError(ioe);
}
};
//=================================================================================
// CONSTANTS
//=================================================================================
// Strings displayed in the tree's node.
private static final String STR_GENERAL = _myBundle.getString("General");
private static final String STR_ASTRONOMY = _astroBundle.getString("Astronomy");
private static final String STR_DIRECTORIES = _myBundle.getString("Directories");
private static final String STR_KBD_SHORTCUTS = _myBundle.getString("KeyboardShortcuts");
// Constants useful for the tree cell renderer
private static final String imagePath = GlobalVar.getDirectory(GlobalVar.DIR_DATA) + FS + "gui" + FS;
private static final ImageIcon iconDirectories = new ImageIcon(imagePath + "iconSave16.gif");
private static final ImageIcon iconAstro = new ImageIcon(imagePath + "iconAstro16.gif");
private static final ImageIcon iconKeyboard = new ImageIcon(imagePath + "iconKeyboard16.gif");
//=================================================================================
// CONSTRUCTORS
//=================================================================================
/** Unique constructor */
public PreferencesDialog() throws Exception {
super(GlobalVar.getMainFrame(), _myBundle.getString("Dialog.Title"), true); //true because modal
_contentPane = this.getContentPane();
// ***** Tree pane *****
_treePanel = new JPanel();
DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(_myBundle.getString("Preferences"));
rootNode.add(new DefaultMutableTreeNode(STR_GENERAL));
rootNode.add(new DefaultMutableTreeNode(STR_ASTRONOMY));
rootNode.add(new DefaultMutableTreeNode(STR_DIRECTORIES));
rootNode.add(new DefaultMutableTreeNode(STR_KBD_SHORTCUTS));
_prefTree = new JTree(rootNode);
_prefTree.addTreeSelectionListener(new PrefTreeSelectionListener());
_prefTree.setCellRenderer(new PreferencesTreeCellRenderer());
_treePanel.add(_prefTree);
// ***** General panel *****
_generalPanel = new JPanel(new BorderLayout());
_generalPanel.setBorder(BorderFactory.createEtchedBorder());
// Look and feel
JPanel gp1 = new JPanel();
gp1.setLayout(new BoxLayout(gp1, BoxLayout.Y_AXIS));
// text, combo and button
JPanel gp1_1 = new JPanel(new FlowLayout(FlowLayout.LEFT));
gp1_1.add(new JLabel(_myBundle.getString("LookAndFeel")));
// WARNING : order in the combo MUST correspond to tig.swing.SwingUtils.LAF_XXX constants
_cmbLAF = new JComboBox(new String[]{_myBundle.getString("PlatformDefault"),
"Kunststoff",
"Macintosh",
"Metal",
"Motif",
"Windows"
});
gp1_1.add(_cmbLAF);
_btnApplyLAF = new JButton(_galBundle.getString("action.Apply"));
_btnApplyLAF.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae){
applyLAFChange();
}});
gp1_1.add(_btnApplyLAF);
// notes
JPanel gp1_2 = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));
gp1_2.add(new JLabel(_myBundle.getString("LAFNote1")));
JPanel gp1_3 = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));
gp1_3.add(new JLabel(_myBundle.getString("LAFNote2")));
// layout for look and feel
gp1.add(gp1_1);
gp1.add(gp1_2);
gp1.add(gp1_3);
// Language
JPanel gp2 = new JPanel(new FlowLayout(FlowLayout.LEFT));
gp2.add(new JLabel(_myBundle.getString("Language")));
_cmbLang = new JComboBox(new String[]{_myBundle.getString("Lang.EN"),
_myBundle.getString("Lang.FR")});
gp2.add(_cmbLang);
JPanel gp3 = new JPanel(new FlowLayout(FlowLayout.LEFT));
gp3.add(new JLabel(_myBundle.getString("LangNote")));
// General Panel layout
JPanel gp10 = new JPanel();
gp10.setLayout(new BoxLayout(gp10, BoxLayout.Y_AXIS));
gp10.add(gp1);
gp10.add(Box.createRigidArea(new Dimension(0,5)));
gp10.add(gp2);
gp10.add(gp3);
JPanel gp11 = new JPanel(new BorderLayout());
gp11.add(gp10, BorderLayout.NORTH);
_generalPanel.add(gp11);
// ***** Astro panel *****
_astroPanel = new JPanel();
_astroPanel.setBorder(BorderFactory.createEtchedBorder());
// Precision
JPanel ap1 = new JPanel(new FlowLayout(FlowLayout.LEFT));
ap1.add(new JLabel(_myBundle.getString("DefaultPrecision")));
_txtPrecision = new JTextField2(5);
ap1.add(_txtPrecision);
ap1.add(new JLabel(_astroBundle.getString("arcSeconds")));
// astro engine
JPanel ap2 = new JPanel(new FlowLayout(FlowLayout.LEFT));
ap2.add(new JLabel(_myBundle.getString("DefaultAstroEngine")));
_cmbAstroEngine = new JComboBox(new String[]{"JEphem", "Swiss Ephemeris"});
ap2.add(_cmbAstroEngine);
// Astro panel layout
// General Panel layout
JPanel ap10 = new JPanel();
ap10.setLayout(new BoxLayout(ap10, BoxLayout.Y_AXIS));
ap10.add(ap1);
ap10.add(ap2);
JPanel ap11 = new JPanel(new BorderLayout());
ap11.add(ap10, BorderLayout.NORTH);
_astroPanel.add(ap11);
// ***** Directories panel *****
_directoriesPanel = new JPanel();
_directoriesPanel.setBorder(BorderFactory.createEtchedBorder());
_directoriesPanel.add(new JButton("Directories"));
// ***** Keyboard shortcuts panel *****
_keyboardShortcutsPanel = new JPanel();
_keyboardShortcutsPanel.setBorder(BorderFactory.createEtchedBorder());
_keyboardShortcutsPanel.add(new JButton("Kbd shortcuts"));
// ***** Dialog button panel *****
JPanel buttonPanel = new JPanel(new BorderLayout());
JPanel bp1 = new JPanel(new GridLayout(1, 0, 5, 5));
_btnOK = new JButton(_galBundle.getString("action.OK"));
_btnOK.addActionListener(new OKListener());
bp1.add(_btnOK);
_btnCancel = new JButton(_galBundle.getString("action.Cancel"));
_btnCancel.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
dispose();
}});
bp1.add(_btnCancel);
buttonPanel.add(bp1, BorderLayout.EAST);
// ***** General Layout *****
_contentPane.setLayout(new BorderLayout(5, 5));
_contentPane.add(_treePanel, BorderLayout.WEST);
_contentPane.add(_generalPanel, BorderLayout.CENTER);
_contentPane.add(buttonPanel, BorderLayout.SOUTH);
_curSelectedPanel = _generalPanel;
resizePrefsPanels();
this.pack();
this.initFields();
}// end constructor
//=================================================================================
// PRIVATE METHODS
//=================================================================================
//******************* setPrefspanel ********************************
/** Called to change the prefs panel, when the tree selection changes. */
private void setPrefsPanel(JPanel newPanel){
if(newPanel != _curSelectedPanel){
_contentPane.remove(_curSelectedPanel);
_contentPane.add(newPanel, BorderLayout.CENTER);
_curSelectedPanel = newPanel;
resizePrefsPanels();
this.pack();
this.repaint();
}
}// end setPrefspanel
//******************* resizePrefsPanels ********************************
/** Resizes the prefs panels. */
private void resizePrefsPanels(){
if(_horRigidArea != null) _contentPane.remove(_horRigidArea);
if(_verRigidArea != null) _contentPane.remove(_verRigidArea);
// recompute the hor and ver rigid areas dimensions
int w1 = _generalPanel.getPreferredSize().width;
int w2 = _astroPanel.getPreferredSize().width;
int w3 = _directoriesPanel.getPreferredSize().width;
int w4 = _keyboardShortcutsPanel.getPreferredSize().width;
int w = Maths.max(new int[]{w1, w2, w3, w4}) + _prefTree.getPreferredSize().width
+ 2 * ((BorderLayout)(_contentPane.getLayout())).getHgap() + 20; // 20 for various forgotten gaps.
int h1 = _generalPanel.getPreferredSize().height;
int h2 = _astroPanel.getPreferredSize().height;
int h3 = _directoriesPanel.getPreferredSize().height;
int h4 = _keyboardShortcutsPanel.getPreferredSize().height;
int h = Maths.max(new int[]{h1, h2, h3, h4});
// resize tree
_prefTree.setPreferredSize(new Dimension(_prefTree.getPreferredSize().width, h));
h += 2 * ((BorderLayout)(_contentPane.getLayout())).getVgap();
_horRigidArea = Box.createRigidArea(new Dimension(w, 0));
_verRigidArea = Box.createRigidArea(new Dimension(0, h));
_contentPane.add(_horRigidArea, BorderLayout.NORTH);
_contentPane.add(_verRigidArea, BorderLayout.EAST);
}// end resizePrefsPanels
//******************* initFields ********************************
/** Called by the constructor to fill the fields from the previously stored preferences. */
private void initFields(){
JEphemPrefs jephemPrefs = GlobalVar.getJEphemPrefs();
AstroPrefs astroPrefs = GlobalVar.getAstroPrefs();
// init general panel fields
if (jephemPrefs.getProperty(JEphemPrefs.KEY_LANG).equals("en"))
_cmbLang.setSelectedIndex(0);
else
_cmbLang.setSelectedIndex(1);
int laf = TigProperties.getIntConstant(jephemPrefs.getProperty(JEphemPrefs.KEY_LAF), "tig.swing.SwingUtils");
_cmbLAF.setSelectedIndex(laf);
// init general panel fields
_txtPrecision.setText(astroPrefs.getProperty(AstroPrefs.KEY_PRECISION));
if(astroPrefs.getProperty(AstroPrefs.KEY_ASTRO_ENGINE).equals(AstroContext.JEPHEM))
_cmbAstroEngine.setSelectedIndex(0);
else
_cmbAstroEngine.setSelectedIndex(1);
}// end initFields
//******************* storePrefs ********************************
/** Called by OKListener to store the new values of the preferences. */
private void storePrefs(){
JEphemPrefs jephemPrefs = GlobalVar.getJEphemPrefs();
AstroPrefs astroPrefs = GlobalVar.getAstroPrefs();
// First, re-set the directories.
// store fields coming from general panel.
if(_cmbLang.getSelectedIndex() == 0) jephemPrefs.setProperty(JEphemPrefs.KEY_LANG, "en");
else jephemPrefs.setProperty(JEphemPrefs.KEY_LANG, "fr");
String[] lafConstantNames = {"LAF_SYSTEM", "LAF_KUNSTSTOFF", "LAF_MACINTOSH", "LAF_METAL", "LAF_MOTIF", "LAF_WINDOWS"};
jephemPrefs.setProperty(JEphemPrefs.KEY_LAF, lafConstantNames[_cmbLAF.getSelectedIndex()]);
// store fields coming from astro panel.
astroPrefs.setProperty(AstroPrefs.KEY_PRECISION, _txtPrecision.getText()); // validity check done before.
if(_cmbAstroEngine.getSelectedIndex() == 0) astroPrefs.setProperty(AstroPrefs.KEY_ASTRO_ENGINE, AstroContext.JEPHEM);
else astroPrefs.setProperty(AstroPrefs.KEY_ASTRO_ENGINE, AstroContext.SWISS_EPHEMERIS);
// Save the properties
jephemPrefs.store();
astroPrefs.store();
GlobalVar.reloadData();
}// end storePrefs
//******************* applyLAFChange ********************************
/** Called when 'ApplyLAF' or 'OK' buttons are pressed. */
public void applyLAFChange(){
try{
SwingUtils.setLookAndFeel(_cmbLAF.getSelectedIndex());
// update all the components
SwingUtilities.updateComponentTreeUI(GlobalVar.getMainFrame());
SwingUtilities.updateComponentTreeUI(PreferencesDialog.this); // performs general panel
SwingUtilities.updateComponentTreeUI(PreferencesDialog.this._astroPanel);
SwingUtilities.updateComponentTreeUI(PreferencesDialog.this._directoriesPanel);
SwingUtilities.updateComponentTreeUI(PreferencesDialog.this._keyboardShortcutsPanel);
PreferencesDialog.this.pack();
}
catch(Exception e){
// nothing done
}
} // end applyLAFChange
//=================================================================================
// INNER CLASSES
//=================================================================================
//*****************************************************************
/** Permits to change the displayed panel when the tree selection changes */
class PrefTreeSelectionListener implements TreeSelectionListener{
public void valueChanged(TreeSelectionEvent tse) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode)_prefTree.getLastSelectedPathComponent();
JPanel newPane = null;
//System.out.println("listener" + (String)node.getUserObject());
if(node.getUserObject().equals(STR_GENERAL)){
newPane = _generalPanel;
}
else if(node.getUserObject().equals(STR_ASTRONOMY)){
newPane = _astroPanel;
}
else if(node.getUserObject().equals(STR_DIRECTORIES)){
newPane = _directoriesPanel;
}
else if(node.getUserObject().equals(STR_KBD_SHORTCUTS)){
newPane = _keyboardShortcutsPanel;
}
else{
System.out.println("listener - no equality");
return; // useful when click on root node
}
PreferencesDialog.this.setPrefsPanel(newPane);
} // end actionPerformed
} // end class PrefTreeSelectionListener
/**********************************************************************************
Cell renderer for the tree of PreferencesDialog.
**********************************************************************************/
private class PreferencesTreeCellRenderer extends DefaultTreeCellRenderer{
public Component getTreeCellRendererComponent(JTree tree,
Object value,
boolean sel,
boolean expanded,
boolean leaf,
int row,
boolean hasFocus){
super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
if(leaf) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
String str = node.getUserObject().toString();
if(str.equals(STR_DIRECTORIES)) setIcon(iconDirectories);
else if(str.equals(STR_ASTRONOMY)) setIcon(iconAstro);
else if(str.equals(STR_KBD_SHORTCUTS)) setIcon(iconKeyboard);
//setToolTipText("This book is in the Tutorial series.");
// } else {
// //setToolTipText(null);
}
return this;
}// end getTreeCellRendererComponent()
}//end class PreferencesTreeCellRenderer
/**********************************************************************************
OKListener : contains all the verification and savings of the prefs.
**********************************************************************************/
class OKListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
// Check 'precision'
try{
double precision = Strings.parseDouble(_txtPrecision.getText());
}
catch(NumberFormatException nfe){
String warningMsg = _galBundle.getString("error.IncorectValueOfField") + " : ' "
+ _astroBundle.getString("Precision") + "'";
UtilsGUI.showWarningMessage(warningMsg);
PreferencesDialog.this.setPrefsPanel(_astroPanel);
_txtPrecision.requestFocus();
return;
}
PreferencesDialog.this.storePrefs();
PreferencesDialog.this.applyLAFChange();
PreferencesDialog.this.dispose();
} // end actionPerformed
} // end class OKListener
}// end class PreferencesDialog