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 }