001: /*
002: * @(#)StandardDialogPane.java 3/18/2005
003: *
004: * Copyright 2002 - 2005 JIDE Software Inc. All rights reserved.
005: */
006: package com.jidesoft.dialog;
007:
008: import com.jidesoft.swing.DelegateAction;
009:
010: import javax.swing.*;
011: import java.awt.*;
012: import java.awt.event.ActionEvent;
013: import java.awt.event.KeyEvent;
014:
015: /**
016: * StandardDialogPane is the content pane of StandardDialog. It can also be used
017: * when you want the template of StandardDialog but you don't want to use JDialog.
018: * <UL>
019: * <LI> Introduce laziness. The content will not be filled until
020: * pack() or show() be called.
021: * <LI> Default action and cancel action. User can set default
022: * action and cancel action of this dialog. By default, ENTER key
023: * will trigger the default action and ESC key will trigger the cancel action and set the dialog result to RESULT_CANCELLED.
024: * <LI> Divide the whole ContentPane of the dialog into three parts
025: * - content panel, button panel and banner panel. By default,
026: * they are added to CENTER, SOUTH and NORTH of a BorderLayout respectively.
027: * There isn't anything special about this. However if all your dialogs use
028: * this pattern, it will automatically make the user interface more consistent.
029: * </UL>
030: * <p/>
031: * This class is abstract. Subclasses need to implement createBannerPanel(),
032: * createButtonPanel() and createContentPanel()
033: * <p/>
034: * <code>StandardDialogPane</code> has lazy loading feature. So when you are done setup the page list,
035: * you need to call {@link #initComponents()} to initialize everything. This method will be called automatically
036: * if the dialog pane is added to StandardDialog.
037: */
038: abstract public class StandardDialogPane extends JPanel implements
039: ButtonNames {
040: private boolean _lazyConstructorCalled = false;
041:
042: protected JComponent _bannerPanel;
043: protected JComponent _contentPanel;
044: protected ButtonPanel _buttonPanel;
045:
046: private Action _defaultCancelAction;
047:
048: private Action _defaultAction;
049:
050: private Component _initFocusedComponent;
051: public final static String PROPERTY_CANCEL_ACTION = "defaultCancelAction";
052: public final static String PROPERTY_DEFAULT_ACTION = "defaultAction";
053:
054: public StandardDialogPane() throws HeadlessException {
055: }
056:
057: /**
058: * Get default cancel action. Default cancel action will be triggered when ESC is pressed.
059: *
060: * @return the default cancel action
061: */
062: public Action getDefaultCancelAction() {
063: return _defaultCancelAction;
064: }
065:
066: /**
067: * Set default cancel action. Default cancel action will be triggered when ESC is pressed.
068: *
069: * @param defaultCancelAction the default cancel action
070: */
071: public void setDefaultCancelAction(Action defaultCancelAction) {
072: Action oldAction = _defaultCancelAction;
073: _defaultCancelAction = defaultCancelAction;
074: firePropertyChange(PROPERTY_CANCEL_ACTION, oldAction,
075: _defaultCancelAction);
076: }
077:
078: /**
079: * Gets the default action. Default action will be trigger when ENTEY key is pressed.
080: *
081: * @return the default action.
082: */
083: public Action getDefaultAction() {
084: return _defaultAction;
085: }
086:
087: /**
088: * Sets the default action. Default action will be trigger when ENTEY key is pressed.
089: *
090: * @param defaultAction the default action.
091: */
092: public void setDefaultAction(Action defaultAction) {
093: Action oldAction = _defaultAction;
094: _defaultAction = defaultAction;
095: firePropertyChange(PROPERTY_DEFAULT_ACTION, oldAction,
096: _defaultAction);
097: }
098:
099: /**
100: * Call three createXxxPanel methods and layout them using BorderLayout.
101: * By default, banner panel, content panel and button panel are added to NORTH,
102: * CENTER and SOUTH of BorderLayout respectively.
103: * <p/>
104: * You can override this method if you want to layout them in another way.
105: */
106: public void initComponents() {
107: _buttonPanel = createButtonPanel();
108: _bannerPanel = createBannerPanel();
109: _contentPanel = createContentPanel();
110: layoutComponents(_bannerPanel, _contentPanel, _buttonPanel);
111: if (getRootPane() != null) {
112: if (getRootPane().getDefaultButton() != null) {
113: getRootPane().getDefaultButton().requestFocus();
114: }
115:
116: if (getDefaultCancelAction() != null) {
117: getRootPane().registerKeyboardAction(
118: new DelegateAction(getDefaultCancelAction()) {
119: @Override
120: public boolean delegateActionPerformed(
121: ActionEvent e) {
122: MenuElement[] selectedPath = MenuSelectionManager
123: .defaultManager()
124: .getSelectedPath();
125: if (selectedPath != null
126: && selectedPath.length > 0) {
127: MenuSelectionManager
128: .defaultManager()
129: .clearSelectedPath();
130: return true;
131: }
132: return false;
133: }
134: },
135: KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
136: JComponent.WHEN_IN_FOCUSED_WINDOW);
137: }
138: if (getDefaultAction() != null) {
139: getRootPane().registerKeyboardAction(
140: getDefaultAction(),
141: KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
142: JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
143: }
144: }
145: }
146:
147: /**
148: * Setups the layout for the three panels - banner panel, content panel and button panel.
149: * By default, we will use BorderLayout, put the content panel in the middle, banner panel on the top and
150: * button panel either right or bottom depending on its alignment.
151: * <p/>
152: * Subclass can override it to do your own layout. The three panels are the three parameters.
153: *
154: * @param bannerPanel
155: * @param contentPanel
156: * @param buttonPanel
157: */
158: protected void layoutComponents(Component bannerPanel,
159: Component contentPanel, ButtonPanel buttonPanel) {
160: setLayout(new BorderLayout());
161: if (bannerPanel != null) {
162: add(bannerPanel, BorderLayout.BEFORE_FIRST_LINE);
163: }
164: if (contentPanel != null) {
165: add(contentPanel, BorderLayout.CENTER);
166: }
167: if (buttonPanel != null) {
168: if (buttonPanel.getAlignment() == SwingConstants.LEFT
169: || buttonPanel.getAlignment() == SwingConstants.RIGHT
170: || buttonPanel.getAlignment() == SwingConstants.CENTER) {
171: add(buttonPanel, BorderLayout.AFTER_LAST_LINE);
172: } else {
173: add(buttonPanel, BorderLayout.AFTER_LINE_ENDS);
174: }
175: }
176: }
177:
178: /**
179: * Gets the initial focused component when dialog is shown.
180: *
181: * @return the initial focused component
182: */
183: public Component getInitFocusedComponent() {
184: return _initFocusedComponent;
185: }
186:
187: /**
188: * Sets the initial focused component when dialog is shown.
189: *
190: * @param initFocusedComponent
191: */
192: public void setInitFocusedComponent(Component initFocusedComponent) {
193: _initFocusedComponent = initFocusedComponent;
194: }
195:
196: /**
197: * Gets the banner panel created by createBannerPanel.
198: *
199: * @return the banner panel.
200: */
201: public JComponent getBannerPanel() {
202: return _bannerPanel;
203: }
204:
205: /**
206: * Gets the banner panel created by createContentPanel.
207: *
208: * @return the content panel.
209: */
210: public JComponent getContentPanel() {
211: return _contentPanel;
212: }
213:
214: /**
215: * Gets the banner panel created by createButtonPanel.
216: *
217: * @return the button panel.
218: */
219: public ButtonPanel getButtonPanel() {
220: return _buttonPanel;
221: }
222:
223: /**
224: * Subclasses should implement this method to create the banner panel.
225: * By default banner panel will appear on top of the dialog unless you
226: * override initComponent() method. Banner panel is really used to balance
227: * the layout of dialog to make the dialog looking good. However it can be used
228: * to show some help text. It is highly recommended to use our {@link BannerPanel}
229: * <p/>
230: * If subclass doesn't want to have a banner panel, just return null.
231: *
232: * @return the banner panel.
233: */
234: abstract public JComponent createBannerPanel();
235:
236: /**
237: * Subclasses should implement this method to create the content panel.
238: * This is the main panel of the dialog which will be added to the center
239: * of the dialog. Subclass should never return null.
240: *
241: * @return the content panel.
242: */
243: abstract public JComponent createContentPanel();
244:
245: /**
246: * Subclasses should implement this method to create the button panel.
247: * 90% of dialogs have buttons. It is highly recommended to use our {@link ButtonPanel}.
248: *
249: * @return the button panel.
250: * @see ButtonPanel
251: */
252: abstract public ButtonPanel createButtonPanel();
253: }
|