// This file is part of Penn TotalRecall <http://memory.psych.upenn.edu/TotalRecall>.
//
// TotalRecall 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, version 3 only.
//
// TotalRecall 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 TotalRecall. If not, see <http://www.gnu.org/licenses/>.
package components.preferences;
import info.MyColors;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.TitledBorder;
/**
* A <code>JPanel</code> that will display a preference chooser of some kind to the user.
*
* <p>This inheritance strategy is used to minimize the amount of code that needs to be written for a new preference chooser, and to maximize consistency between preference choosers.
* Spacing relative to the containing <code>PreferencesFrame</code> is taken care of here, and spacing is taken care of in <code>PreferencesFrame</code>.
* An <code>AbstractPreferenceDisplay</code> will always take up all the space it can inside the <code>PreferencesFrame</code>, and is guaranteed at least its preferred size.
* However, inheritors do need to take care of the resizing behavior of their <i>internal</i> components.
*
* <p>When writing a new <code>AbstractPreferenceDisplay</code>, don't forget to consider case in which the relevant preference doesn't exist in the {@link java.util.prefs.Preferences} yet (first run).
* By the time the chooser is realized the preference must already be written to the <code>Preferences</code> object, or {@link #isChanged()} will not behave correctly.
* Inheritors should not consume VK_ESCAPE presses, as this keystroke is used by the <code>PreferencesFrame</code>.
*
* <p>All preferences in this program should exclusively use <code>Preferences</code> object in {@link info.UserPrefs#prefs}, a user-specific preferences object.
* System-wise preferences objects are not used as they require administrator access for persistence in some platforms.
*
* @author Yuvi Masory
*
* @see PreferencesFrame
*/
public abstract class AbstractPreferenceDisplay extends JPanel {
/**
* Initializes some aspects of a new concrete <code>AbstractPreferenceDisplay</code> including spacing/layout and displayed title.
*
* @param prefName The name of the preference being chosen
*/
protected AbstractPreferenceDisplay(String prefName) {
setOpaque(true);
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
// outside invisible border for spacing
Border outsideBorder = BorderFactory.createEmptyBorder(3, 5, 5, 3);
// middle visible titled border
Border blackline = BorderFactory.createLineBorder(MyColors.unfocusedColor);
TitledBorder middleBorder = BorderFactory.createTitledBorder(blackline, prefName + ":");
middleBorder.setTitleJustification(TitledBorder.LEADING);
// inside invisible border for spacing
Border insideBorder = BorderFactory.createEmptyBorder(5, 10, 10, 5);
// combine the three borders into one compound border
CompoundBorder insideCompoundBorder = BorderFactory.createCompoundBorder(middleBorder, insideBorder);
CompoundBorder border = BorderFactory.createCompoundBorder(outsideBorder, insideCompoundBorder);
setBorder(border);
}
/**
* Saves the preference the user has entered to the programs persistent <code>Preferences</code> object.
*
* @return <code>true</code> if the preference was successfully set
* @throws BadPreferenceException If the preference the user has entered is badly formatted or unreasonable
*/
protected abstract boolean save() throws BadPreferenceException;
/**
* Determines whether the the user has altered the displayed preference from the one saved in the program's <code>Preferences</code> object.
*
* @return <code>true</code> iff the preference currently being graphically displayed is not the stored one
*/
protected abstract boolean isChanged();
/**
* Restores the graphically displayed preference to the one that is currently stored in the program's <code>Preferences</code> object.
*/
protected abstract void graphicallyRevert();
/**
* Restores both the saved value in the program's <code>Preferences</code> object, AND the graphically entered preference, the the factory default.
*/
protected abstract void restoreDefault();
}