001 /*
002 * Copyright 2002-2006 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005 * use this file except in compliance with the License. You may obtain a copy of
006 * the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013 * License for the specific language governing permissions and limitations under
014 * the License.
015 */
016 package org.springframework.richclient.dialog.support;
017
018 import java.awt.BorderLayout;
019 import java.beans.PropertyChangeEvent;
020 import java.beans.PropertyChangeListener;
021
022 import javax.swing.JComponent;
023 import javax.swing.JPanel;
024 import javax.swing.JSeparator;
025
026 import org.springframework.richclient.command.ActionCommand;
027 import org.springframework.richclient.command.CommandGroup;
028 import org.springframework.richclient.core.Guarded;
029 import org.springframework.richclient.core.Message;
030 import org.springframework.richclient.dialog.DialogPage;
031 import org.springframework.richclient.dialog.Messagable;
032 import org.springframework.richclient.dialog.TitlePane;
033 import org.springframework.richclient.dialog.TitledPageApplicationDialog;
034 import org.springframework.richclient.util.GuiStandardUtils;
035
036 /**
037 * Useful methods for working with {@link DialogPage}s. These methods make it easier to
038 * place dialog pages in arbitrary containers, wire in message listeners, wire actions
039 * to the page complete status, etc.
040 * <p>
041 * These helpers can be used to quickly construct a standard layout (like that found in
042 * the {@link TitledPageApplicationDialog}, or you can use these methods to construct the
043 * various components (title area and button bar) and then lay things out as you like.
044 * <p>
045 * The standard layout is obtained using the
046 * {@link #createStandardView(DialogPage, ActionCommand, ActionCommand)} or
047 * {@link #createStandardView(DialogPage, Object[])} methods. To create the pieces and do
048 * the layout independently, use {@link #createTitlePane(DialogPage)} to get the title
049 * pane and wire your OK command into the page complete status using
050 * {@link #adaptPageCompletetoGuarded(DialogPage, Guarded)}. If you don't want to use the
051 * standard title pane, you can easily arrange for the messages coming from the dialog
052 * page to be sent to a {@link Messagable} of your choice using
053 * {@link #addMessageMonitor(DialogPage, Messagable)}.
054 *
055 * @author Larry Streepy
056 *
057 */
058 public class DialogPageUtils {
059
060 /**
061 * Create a standard {@link TitlePane} wired to receive messages from the given dialog
062 * page. The title pane will also be configured from the dialog page's title and icon.
063 *
064 * @param dialogPage to process
065 */
066 public static TitlePane createTitlePane( DialogPage dialogPage ) {
067 TitlePane titlePane = new TitlePane();
068 titlePane.setTitle(dialogPage.getTitle());
069 titlePane.setImage(dialogPage.getImage());
070 addMessageMonitor(dialogPage, titlePane);
071
072 return titlePane;
073 }
074
075 /**
076 * Construct a complete standard layout for a dialog page. This is a panel with the
077 * title/message area at the top, the dialog page control in the center, and the
078 * command button bar (using the provided ok and cancel commands) on the bottom. The
079 * finishCommand provided will automatically be wired into the page complete status of
080 * the dialog page.
081 *
082 * @param dialogPage to process
083 * @param okCommand Action command to wire into dialogPage's page complete status
084 * @param cancelCommand to add to the command button bar
085 * @return created component
086 * @see #createTitlePane(DialogPage)
087 * @see #adaptPageCompletetoGuarded(DialogPage, Guarded)
088 */
089 public static JComponent createStandardView( DialogPage dialogPage, ActionCommand okCommand,
090 ActionCommand cancelCommand ) {
091 adaptPageCompletetoGuarded(dialogPage, okCommand);
092 return createStandardView(dialogPage, new Object[] { okCommand, cancelCommand });
093 }
094
095 /**
096 * Construct a complete standard layout for a dialog page. This is a panel with the
097 * title/message area at the top, the dialog page control in the center, and the
098 * command button bar (using the provided group of commands) on the bottom. You should
099 * have already wired any commands to the page complete status as needed.
100 *
101 * @param dialogPage to process
102 * @param commandGroupMembers Array of commands to place in the button bar
103 * @return created component
104 * @see #createTitlePane(DialogPage)
105 * @see #adaptPageCompletetoGuarded(DialogPage, Guarded)
106 */
107 public static JComponent createStandardView( DialogPage dialogPage, Object[] commandGroupMembers ) {
108 JPanel viewPanel = new JPanel(new BorderLayout());
109
110 JPanel titlePaneContainer = new JPanel(new BorderLayout());
111 titlePaneContainer.add(createTitlePane(dialogPage).getControl());
112 titlePaneContainer.add(new JSeparator(), BorderLayout.SOUTH);
113 viewPanel.add(titlePaneContainer, BorderLayout.NORTH);
114
115 JComponent pageControl = dialogPage.getControl();
116 GuiStandardUtils.attachDialogBorder(pageControl);
117 viewPanel.add(pageControl);
118
119 viewPanel.add(createButtonBar(commandGroupMembers), BorderLayout.SOUTH);
120
121 return viewPanel;
122 }
123
124 /**
125 * Return a standardized row of command buttons.
126 *
127 * @param groupMembers
128 * @return button bar
129 */
130 public static JComponent createButtonBar( Object[] groupMembers ) {
131 CommandGroup dialogCommandGroup = CommandGroup.createCommandGroup(null, groupMembers);
132 JComponent buttonBar = dialogCommandGroup.createButtonBar();
133 GuiStandardUtils.attachDialogBorder(buttonBar);
134 return buttonBar;
135 }
136
137 /**
138 * Add a message monitor. Each monitor will have its
139 * {@link Messagable#setMessage(Message)} method called whenever the MESSAGE property
140 * on the dialog page changes.
141 *
142 * @param dialogPage to monitor
143 * @param monitor to add
144 */
145 public static void addMessageMonitor( DialogPage dialogPage, Messagable monitor ) {
146 dialogPage.addPropertyChangeListener(Messagable.MESSAGE_PROPERTY, new MessageHandler(monitor));
147 }
148
149 /**
150 * Create an adapter that will monitor the page complete status of the dialog page and
151 * adapt it to operations on the provided Guarded object. If the page is complete,
152 * then the guarded object will be enabled. If this page is not complete, then the
153 * guarded object will be disabled.
154 *
155 * @param dialogPage to monitor
156 * @param guarded object to adapt
157 */
158 public static void adaptPageCompletetoGuarded( DialogPage dialogPage, Guarded guarded ) {
159 dialogPage.addPropertyChangeListener(DialogPage.PAGE_COMPLETE_PROPERTY, new PageCompleteAdapter(guarded));
160 }
161
162 /**
163 * Internal class to handle the PAGE_COMPLETE property changes in the dialog page and
164 * adapt them to operations on a Guarded object.
165 */
166 protected static class PageCompleteAdapter implements PropertyChangeListener {
167 private Guarded guarded;
168
169 /**
170 * Construct a handler on the given guarded object.
171 *
172 * @param guarded object to manage
173 */
174 protected PageCompleteAdapter( Guarded guarded ) {
175 this.guarded = guarded;
176 }
177
178 /**
179 * Handle a change in the page complete state of the dialog page
180 *
181 * @param e
182 */
183 public void propertyChange( PropertyChangeEvent e ) {
184 if( DialogPage.PAGE_COMPLETE_PROPERTY.equals(e.getPropertyName()) ) {
185 guarded.setEnabled(((Boolean) e.getNewValue()).booleanValue());
186 }
187 }
188 }
189
190 /**
191 * Internal class to handle the MESSAGE_PROPERTY property changes in a dialog page.
192 */
193 private static class MessageHandler implements PropertyChangeListener {
194 private Messagable monitor;
195
196 /**
197 * Construct a handler on the given message monitor.
198 *
199 * @param monitor to send messages to
200 */
201 public MessageHandler( Messagable monitor ) {
202 this.monitor = monitor;
203 }
204
205 /**
206 * Handle a change in the message or page complete state of the dialog page.
207 *
208 * @param e
209 */
210 public void propertyChange( PropertyChangeEvent e ) {
211 if( Messagable.MESSAGE_PROPERTY.equals(e.getPropertyName()) ) {
212 monitor.setMessage((Message) e.getNewValue());
213 }
214 }
215 }
216 }