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;
017    
018    import java.awt.Window;
019    import java.awt.event.ComponentAdapter;
020    import java.awt.event.ComponentEvent;
021    
022    import javax.swing.JComponent;
023    
024    import org.springframework.richclient.core.DefaultMessage;
025    import org.springframework.richclient.core.Message;
026    import org.springframework.util.Assert;
027    
028    /**
029     * Dialog for showing an message to the user. The severity of the message is used to
030     * determine the icon.
031     * <p>
032     * If the message text contains line feeds ('\n'), the message is split into different
033     * parts, and the first part is rendered in bold. This is to mimic the guidelines in
034     * http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGWindows/chapter_17_section_6.html#//apple_ref/doc/uid/20000957-20000961-BACFBACB
035     */
036    public class MessageDialog extends ApplicationDialog {
037    
038        private static final String OK_FACE_DESCRIPTOR_ID = "okCommand";
039    
040        private AlertMessageAreaPane messageAreaPane;
041    
042        private Message message;
043    
044        private float dialogScaleFactor = 0.55f;
045    
046        /** Minimum width for the dialog, in case the scale factor results in a tiny value. */
047        private int minimumWidth = 600;
048    
049        /**
050         * Constructs a new dialog.
051         *
052         * @param title the title
053         * @param message the message
054         */
055        public MessageDialog( String title, Message message ) {
056            this( title, null, message );
057        }
058    
059        /**
060         * Constructs a new dialog.
061         *
062         * @param title the title
063         * @param parent the parent window
064         * @param message the message
065         */
066        public MessageDialog( String title, Window parent, Message message ) {
067            super( title, parent );
068            setMessage( message );
069        }
070    
071        /**
072         * Constructs a new dialog, the message is converted to an information message
073         *
074         * @param title the title
075         * @param message the message text
076         */
077        public MessageDialog( String title, String message ) {
078            this( title, null, message );
079        }
080    
081        /**
082         * Constructs a new dialog, the message is converted to an information message
083         *
084         * @param title the title
085         * @param parent the parent window
086         * @param message the message text
087         */
088        public MessageDialog( String title, Window parent, String message ) {
089            super( title, parent );
090            setMessage( message );
091        }
092    
093        /**
094         * Set the message text, severity is info.
095         *
096         * @param text the message text
097         */
098        public void setMessage( String text ) {
099            setMessage( new DefaultMessage( text ) );
100        }
101    
102        /**
103         * Set the message.
104         *
105         * @param message the message
106         */
107        public void setMessage( Message message ) {
108            Assert.notNull( message, "The message is required" );
109            Assert.hasText( message.getMessage(), "The message text is required" );
110            this.message = message;
111        }
112    
113        /**
114         * Get the message
115         *
116         * @return message
117         */
118        public Message getMessage() {
119            return message;
120        }
121    
122        /**
123         * @see org.springframework.richclient.dialog.ApplicationDialog#getCancelCommandId()
124         */
125        protected String getCancelCommandId() {
126            return OK_FACE_DESCRIPTOR_ID;
127        }
128    
129        /**
130         * @see org.springframework.richclient.dialog.ApplicationDialog#registerDefaultCommand()
131         */
132        protected void registerDefaultCommand() {
133            registerCancelCommandAsDefault();
134        }
135    
136        /**
137         * @see org.springframework.richclient.dialog.ApplicationDialog#getCommandGroupMembers()
138         */
139        protected Object[] getCommandGroupMembers() {
140            return new Object[] { getCancelCommand() };
141        }
142    
143        /**
144         * @see org.springframework.richclient.dialog.ApplicationDialog#createDialogContentPane()
145         */
146        protected JComponent createDialogContentPane() {
147            this.messageAreaPane = new AlertMessageAreaPane();
148            this.messageAreaPane.setMessage( message );
149            return messageAreaPane.getControl();
150        }
151    
152        protected void disposeDialogContentPane() {
153            messageAreaPane = null;
154        }
155    
156        /**
157         * @see org.springframework.richclient.dialog.ApplicationDialog#onFinish()
158         */
159        protected final boolean onFinish() {
160            // final because it can never get called
161            return true;
162        }
163    
164        /**
165         * @see org.springframework.richclient.dialog.ApplicationDialog#onAboutToShow()
166         */
167        protected void onAboutToShow() {
168            int width = getDialog().getWidth();
169            float scale = getDialogScaleFactor();
170            int parentWidth = getDialog().getParent().getWidth();
171            if( width > parentWidth * scale ) {
172                final int messageAreaPaneHeight = messageAreaPane.getPreferredHeight();
173                width = (int) (parentWidth * scale);
174                if( width < getMinimumWidth() ) {
175                    width = getMinimumWidth();
176                }
177    
178                // adjust the width
179                getDialog().setSize( width, getDialog().getHeight() );
180    
181                // dirty hack, because messageAreaPane.getPreferredHeight() doesn't respond
182                // immediately to dialog resize when dialog is not visible
183                DialogSizeUpdater dialogSizeUpdater = new DialogSizeUpdater( messageAreaPaneHeight );
184                getDialog().addComponentListener( dialogSizeUpdater );
185            }
186            getDialog().setResizable( false );
187        }
188    
189        /**
190         * Get the scale factor for the dialog size (as compared to the parent window). The
191         * default returned here is 55% (.55).
192         *
193         * @return scale factor
194         */
195        public float getDialogScaleFactor() {
196            return dialogScaleFactor;
197        }
198    
199        /**
200         * Set the scale factory for the dialog size.
201         *
202         * @param dialogScaleFactor New dialog scale factor
203         */
204        public void setDialogScaleFactor( float dialogScaleFactor ) {
205            this.dialogScaleFactor = dialogScaleFactor;
206        }
207    
208        /**
209         * Get the minimum width for the dialog. This overrides the value calculated by the
210         * scale factor.
211         *
212         * @return minimum width
213         * @see #setDialogScaleFactor
214         */
215        public int getMinimumWidth() {
216            return minimumWidth;
217        }
218    
219        /**
220         * Set the minimum width for the dialog. This overrides the value calculated by the
221         * scale factor.
222         *
223         * @return minimum width
224         */
225        public void setMinimumWidth( int minimumWidth ) {
226            this.minimumWidth = minimumWidth;
227        }
228    
229        /**
230         * Inner class to handle setting the size of the dialog heigth when it is shown.
231         */
232        private class DialogSizeUpdater extends ComponentAdapter {
233            private final int height;
234    
235            private DialogSizeUpdater( int height ) {
236                super();
237                this.height = height;
238            }
239    
240            public void componentShown( ComponentEvent e ) {
241                // we must also change the height
242                int newHeight = getDialog().getHeight() + messageAreaPane.getPreferredHeight() - height;
243                getDialog().setSize( getDialog().getWidth(), newHeight );
244            }
245        }
246    }