📄 optionsdialog.java
字号:
/*
* 02/27/2004
*
* OptionsDialog.java - Generic dialog for displaying options you can change in
* an application, similar to those found in many Microsoft Windows apps.
* Copyright (C) 2004 Robert Futrell
* email@address.com
* www.website.com
*
* 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 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.fife.ui;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ResourceBundle;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.JTextComponent;
import javax.swing.tree.*;
import org.fife.RTreeSelectionModel;
/**
* An options dialog similar to those found in many Microsoft Windows
* applications. An <code>OptionsDialog</code> contains a list on its left-hand
* side containing options categories; clicking on a category displays all
* options related to that category.<p>
*
* Using this class along with <code>org.fife.ui.OptionsDialogPanel</code> will
* provide you with a framework for creating an Options dialog with error
* checking and instant-Apply functionality.<p>
*
* This is an abstract class and should be overridden to suit your program's
* needs as follows:
*
* <ul>
* <li>The {@link #initialize} method should be overridden to initialize all
* options panels in this chooser.</li>
* <li>The {@link #doApplyImpl} method should be overridden to "apply" any
* changes the user has specified by playing with the options panels.</li>
* </ul>
*
* @see org.fife.ui.OptionsDialogPanel
*
* @author Robert Futrell
* @version 0.7
*/
public abstract class OptionsDialog extends JDialog implements ActionListener,
TreeSelectionListener, PropertyChangeListener {
/**
* The panels the use can display.
*/
private OptionsDialogPanel[] optionsPanels;
private JTree optionTree;
private DefaultTreeModel treeModel;
private DefaultMutableTreeNode root;
private JScrollPane optionTreeScrollPane;
private RButton okButton;
private RButton applyButton;
private RButton cancelButton;
private JPanel currentOptionPanel;
private CardLayout currentOptionPanelLayout;
/*****************************************************************************/
/**
* Creates a new options dialog with no options panels.
*
* @param owner The parent of this dialog.
*/
public OptionsDialog(Frame owner) {
this(owner, new OptionsDialogPanel[0]);
}
/*****************************************************************************/
/**
* Creates a new options dialog with the specified array of option
* panels.
*
* @param owner The parent of this dialog.
* @param optionsPanels The option panels to add to this options dialog.
* Note that this array MUST have at least one panel in it;
* otherwise, this constructor will throw a
* <code>NullPointerException</code>.
* @see OptionsDialogPanel
*/
public OptionsDialog(Frame owner, OptionsDialogPanel[] optionsPanels) {
super(owner);
ResourceBundle msg = ResourceBundle.getBundle("org.fife.ui.UI");
// Create the options tree and its scroll pane.
root = new DefaultMutableTreeNode(msg.getString("Options"));
treeModel = new DefaultTreeModel(root);
optionTree = new JTree(treeModel) {
public void updateUI() {
super.updateUI();
// Must set new cell renderer each time lnf changes as
// DefaultTreeCellRenderer is "buggy" in that it caches
// colors, fonts, icons, etc.
DefaultTreeCellRenderer r = new DefaultTreeCellRenderer();
r.setLeafIcon(null);
r.setOpenIcon(null);
r.setClosedIcon(null);
setCellRenderer(r);
}
};
optionTree.setSelectionModel(new RTreeSelectionModel());
optionTree.setShowsRootHandles(true);
optionTree.setRootVisible(false);
optionTree.addTreeSelectionListener(this);
optionTreeScrollPane = new RScrollPane(optionTree);
optionTreeScrollPane.setVerticalScrollBarPolicy(
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
JPanel indexPanel = new JPanel(new GridLayout(1,1));
indexPanel.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
indexPanel.add(optionTreeScrollPane);
// Create a panel to hold the current options panel.
currentOptionPanel = new JPanel();
currentOptionPanelLayout = new CardLayout();
currentOptionPanel.setLayout(currentOptionPanelLayout);
setOptionsPanels(optionsPanels);
// Create a panel with buttons.
JPanel buttonPanel = new JPanel();
buttonPanel.setBorder(new BevelDividerBorder(SwingConstants.TOP, 15));
JPanel temp = new JPanel(new GridLayout(1,3, 5,0));
okButton = new RButton(msg.getString("OK"));
okButton.setActionCommand("OK");
okButton.addActionListener(this);
cancelButton = new RButton(msg.getString("Cancel"));
cancelButton.setActionCommand("Cancel");
cancelButton.addActionListener(this);
applyButton = new RButton(msg.getString("Apply"));
applyButton.setActionCommand("Apply");
applyButton.addActionListener(this);
applyButton.setEnabled(false); // Until they make a change.
temp.add(okButton);
temp.add(cancelButton);
temp.add(applyButton);
buttonPanel.add(temp);
// Create a panel containing the two above panels.
JPanel rightPanel = new JPanel();
rightPanel.setLayout(new BorderLayout());
rightPanel.add(currentOptionPanel);
rightPanel.add(buttonPanel, BorderLayout.SOUTH);
// Put everything into a neat little package.
JPanel contentPane = new JPanel();
contentPane.setLayout(new BorderLayout());
contentPane.setBorder(UIUtilities.getEmpty5Border());
contentPane.add(indexPanel, BorderLayout.WEST);
contentPane.add(rightPanel);
setContentPane(contentPane);
getRootPane().setDefaultButton(okButton);
setTitle(msg.getString("Options"));
setModal(true);
pack();
// Make the Escape key hide the dialog.
JRootPane rootPane = getRootPane();
InputMap inputMap = rootPane.getInputMap(
JComponent.WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = rootPane.getActionMap();
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "OnEsc");
actionMap.put("OnEsc", new AbstractAction() {
public void actionPerformed(ActionEvent e) {
cancelButton.doClick();
}
}
);
}
/*****************************************************************************/
/**
* Listens for action events in this dialog.
*/
public void actionPerformed(ActionEvent e) {
String actionCommand = e.getActionCommand();
if (actionCommand.equals("Cancel")) {
this.setVisible(false);
}
else if (actionCommand.equals("OK")) {
boolean result = doApply((Frame)getParent());
if (result==true)
this.setVisible(false);
}
else if (actionCommand.equals("Apply")) {
doApply((Frame)getParent());
}
}
/*****************************************************************************/
/**
* Adds an options panel to this options dialog.
*
* @param panel The options panel to add.
*/
protected void addOptionPanel(OptionsDialogPanel panel) {
panel.addPropertyChangeListener(this);
TitledPanel tp = new TitledPanel(panel.getName(),
panel, TitledPanel.LINE_BORDER);
tp.setBorder(UIUtilities.getEmpty5Border());
tp.setIcon(panel.getIcon());
currentOptionPanel.add(tp, panel.getName());
}
/**
* Automatically called when the user clicks the "Apply" button and when
* the user first clicks the "OK" button before the dialog goes away.
* This method first loops through all of the options panels and calls
* <code>ensureValidInputs</code> on each; then it calls
* <code>doApplyImpl</code> (which you should have overridden to
* make the changes a reality). If all inputs were valid, then the
* Apply button is disabled and the "unsaved changes" flag for all Options
* panels is cleared.
*
* @param owner The parent frame that was specified in the constructor.
* @return <code>true</code> if all options checked out okay and the apply
* was successful; <code>false</code> if at least one option
* wasn't valid (and thus the Options dialog needs to stay up).
*/
public final boolean doApply(Frame owner) {
// Ensure that all of the changes specified are valid. If one isn't,
// scold the user, shift focus to it and bail out.
int numPanels = optionsPanels.length;
for (int i=0; i<numPanels; i++) {
OptionsDialogPanel.OptionsPanelCheckResult result =
optionsPanels[i].ensureValidInputs();
if (result!=null) {
setVisibleOptionPanel(i);
// As an added bonus, if it's a text field, (which it
// usually (always?) will be), select the text so they
// can easily delete it.
if (result.component instanceof JTextComponent)
((JTextComponent)result.component).selectAll();
result.component.requestFocusInWindow();
JOptionPane.showMessageDialog(this, result.errorMessage,
"Error", JOptionPane.ERROR_MESSAGE);
return false;
}
}
// Actually apply the changes, disable the "Apply" button, clear
// the "Unsaved changes" flags of all options panels, and
// we're done!
doApplyImpl(owner);
setApplyButtonEnabled(false);
for (int i=0; i<numPanels; i++)
optionsPanels[i].setUnsavedChanges(false);
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -