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.application.support; 017 018 import java.awt.BorderLayout; 019 import java.awt.event.WindowAdapter; 020 import java.awt.event.WindowEvent; 021 import java.awt.event.WindowFocusListener; 022 import java.util.Iterator; 023 024 import javax.swing.JComponent; 025 import javax.swing.JFrame; 026 import javax.swing.JMenuBar; 027 import javax.swing.WindowConstants; 028 029 import org.apache.commons.logging.Log; 030 import org.apache.commons.logging.LogFactory; 031 import org.springframework.context.ApplicationContext; 032 import org.springframework.richclient.application.Application; 033 import org.springframework.richclient.application.ApplicationPage; 034 import org.springframework.richclient.application.ApplicationPageFactory; 035 import org.springframework.richclient.application.ApplicationServices; 036 import org.springframework.richclient.application.ApplicationServicesLocator; 037 import org.springframework.richclient.application.ApplicationWindow; 038 import org.springframework.richclient.application.PageDescriptor; 039 import org.springframework.richclient.application.PageListener; 040 import org.springframework.richclient.application.ViewDescriptor; 041 import org.springframework.richclient.application.WindowManager; 042 import org.springframework.richclient.application.config.ApplicationLifecycleAdvisor; 043 import org.springframework.richclient.application.config.ApplicationWindowConfigurer; 044 import org.springframework.richclient.application.statusbar.StatusBar; 045 import org.springframework.richclient.command.CommandGroup; 046 import org.springframework.richclient.command.CommandManager; 047 import org.springframework.richclient.util.EventListenerListHelper; 048 import org.springframework.richclient.util.WindowUtils; 049 import org.springframework.util.Assert; 050 051 /** 052 * Abstract helper implementation for <code>ApplicationWindow</code>. 053 */ 054 public abstract class AbstractApplicationWindow implements ApplicationWindow, WindowFocusListener { 055 protected Log logger = LogFactory.getLog( getClass() ); 056 057 private final EventListenerListHelper pageListeners = new EventListenerListHelper( PageListener.class ); 058 059 private int number; 060 061 private ApplicationWindowCommandManager commandManager; 062 063 private CommandGroup menuBarCommandGroup; 064 065 private CommandGroup toolBarCommandGroup; 066 067 private StatusBar statusBar; 068 069 private ApplicationWindowConfigurer windowConfigurer; 070 071 private JFrame control; 072 073 private ApplicationPage currentPage; 074 075 private WindowManager windowManager; 076 077 public AbstractApplicationWindow() { 078 this( Application.instance().getWindowManager().size() ); 079 } 080 081 public AbstractApplicationWindow( int number ) { 082 this.number = number; 083 getAdvisor().setOpeningWindow( this ); 084 init(); 085 getAdvisor().onCommandsCreated( this ); 086 } 087 088 protected void init() { 089 this.commandManager = getAdvisor().createWindowCommandManager(); 090 this.menuBarCommandGroup = getAdvisor().getMenuBarCommandGroup(); 091 this.toolBarCommandGroup = getAdvisor().getToolBarCommandGroup(); 092 this.statusBar = getAdvisor().getStatusBar(); 093 } 094 095 public int getNumber() { 096 return number; 097 } 098 099 public ApplicationPage getPage() { 100 return currentPage; 101 } 102 103 protected ApplicationLifecycleAdvisor getAdvisor() { 104 return Application.instance().getLifecycleAdvisor(); 105 } 106 107 protected ApplicationServices getServices() { 108 return ApplicationServicesLocator.services(); 109 } 110 111 protected ApplicationWindowConfigurer getWindowConfigurer() { 112 if( windowConfigurer == null ) { 113 this.windowConfigurer = initWindowConfigurer(); 114 } 115 return windowConfigurer; 116 } 117 118 protected ApplicationWindowConfigurer initWindowConfigurer() { 119 return new DefaultApplicationWindowConfigurer( this ); 120 } 121 122 public CommandManager getCommandManager() { 123 return commandManager; 124 } 125 126 public Iterator getSharedCommands() { 127 return commandManager.getSharedCommands(); 128 } 129 130 public CommandGroup getMenuBar() { 131 return menuBarCommandGroup; 132 } 133 134 public CommandGroup getToolBar() { 135 return toolBarCommandGroup; 136 } 137 138 public StatusBar getStatusBar() { 139 return statusBar; 140 } 141 142 public void setWindowManager( WindowManager windowManager ) { 143 this.windowManager = windowManager; 144 } 145 146 /** 147 * Show the given page in this window. 148 * 149 * @param pageId the page to show, identified by id 150 * 151 * @throws IllegalArgumentException if pageId == null 152 */ 153 public void showPage( String pageId ) { 154 if( pageId == null ) 155 throw new IllegalArgumentException( "pageId == null" ); 156 157 if( getPage() == null || !getPage().getId().equals( pageId ) ) { 158 showPage( createPage( this, pageId ) ); 159 } else { 160 // asking for the same page, so ignore 161 } 162 } 163 164 public void showPage( PageDescriptor pageDescriptor ) { 165 Assert.notNull( pageDescriptor, "pageDescriptor == null" ); 166 167 if( getPage() == null || !getPage().getId().equals( pageDescriptor.getId() ) ) { 168 showPage( createPage( pageDescriptor ) ); 169 } else { 170 // asking for the same page, so ignore 171 } 172 } 173 174 /** 175 * Show the given page in this window. 176 * 177 * @param page the page to show 178 * 179 * @throws IllegalArgumentException if page == null 180 */ 181 public void showPage( ApplicationPage page ) { 182 if( page == null ) 183 throw new IllegalArgumentException( "page == null" ); 184 185 if( this.currentPage == null ) { 186 this.currentPage = page; 187 getAdvisor().onPreWindowOpen( getWindowConfigurer() ); 188 this.control = createNewWindowControl(); 189 this.control.addWindowFocusListener( this ); 190 initWindowControl( this.control ); 191 getAdvisor().onWindowCreated( this ); 192 setActivePage( page ); 193 this.control.setVisible( true ); 194 getAdvisor().onWindowOpened( this ); 195 } else { 196 if( !currentPage.getId().equals( page.getId() ) ) { 197 final ApplicationPage oldPage = this.currentPage; 198 this.currentPage = page; 199 setActivePage( page ); 200 pageListeners.fire( "pageClosed", oldPage ); 201 } else { 202 // asking for the same page, so ignore 203 } 204 } 205 pageListeners.fire( "pageOpened", this.currentPage ); 206 } 207 208 protected final ApplicationPage createPage( ApplicationWindow window, String pageDescriptorId ) { 209 PageDescriptor descriptor = getPageDescriptor( pageDescriptorId ); 210 return createPage( descriptor ); 211 } 212 213 /** 214 * Factory method for creating the page area managed by this window. Subclasses may 215 * override to return a custom page implementation. 216 * 217 * @param descriptor The page descriptor 218 * 219 * @return The window's page 220 */ 221 protected ApplicationPage createPage( PageDescriptor descriptor ) { 222 ApplicationPageFactory windowFactory = (ApplicationPageFactory) getServices().getService( 223 ApplicationPageFactory.class ); 224 return windowFactory.createApplicationPage( this, descriptor ); 225 } 226 227 protected PageDescriptor getPageDescriptor( String pageDescriptorId ) { 228 ApplicationContext ctx = Application.instance().getApplicationContext(); 229 Assert.state( ctx.containsBean( pageDescriptorId ), "Do not know about page or view descriptor with name '" 230 + pageDescriptorId + "' - check your context config" ); 231 Object desc = ctx.getBean( pageDescriptorId ); 232 if( desc instanceof PageDescriptor ) { 233 return (PageDescriptor) desc; 234 } else if( desc instanceof ViewDescriptor ) { 235 return new SingleViewPageDescriptor( (ViewDescriptor) desc ); 236 } else { 237 throw new IllegalArgumentException( "Page id '" + pageDescriptorId 238 + "' is not backed by an ApplicationPageDescriptor" ); 239 } 240 } 241 242 protected void initWindowControl( JFrame windowControl ) { 243 ApplicationWindowConfigurer configurer = getWindowConfigurer(); 244 applyStandardLayout( windowControl, configurer ); 245 prepareWindowForView( windowControl, configurer ); 246 } 247 248 protected void applyStandardLayout( JFrame windowControl, ApplicationWindowConfigurer configurer ) { 249 windowControl.setTitle( configurer.getTitle() ); 250 windowControl.setIconImage( configurer.getImage() ); 251 windowControl.setJMenuBar( createMenuBarControl() ); 252 windowControl.getContentPane().setLayout( new BorderLayout() ); 253 windowControl.getContentPane().add( createToolBarControl(), BorderLayout.NORTH ); 254 windowControl.getContentPane().add( createWindowContentPane() ); 255 windowControl.getContentPane().add( createStatusBarControl(), BorderLayout.SOUTH ); 256 } 257 258 /** 259 * Set the given <code>ApplicationPage</code> active (visible + selected if 260 * applicable) 261 * 262 * @param page the <code>ApplicationPage</code> 263 */ 264 protected abstract void setActivePage( ApplicationPage page ); 265 266 protected void prepareWindowForView( JFrame windowControl, ApplicationWindowConfigurer configurer ) { 267 windowControl.pack(); 268 windowControl.setSize( configurer.getInitialSize() ); 269 270 WindowUtils.centerOnScreen(windowControl); 271 } 272 273 protected JFrame createNewWindowControl() { 274 JFrame frame = new JFrame(); 275 frame.setDefaultCloseOperation( WindowConstants.DO_NOTHING_ON_CLOSE ); 276 WindowAdapter windowCloseHandler = new WindowAdapter() { 277 public void windowClosing( WindowEvent e ) { 278 close(); 279 } 280 }; 281 frame.addWindowListener( windowCloseHandler ); 282 return frame; 283 } 284 285 public JFrame getControl() { 286 return control; 287 } 288 289 public boolean isControlCreated() { 290 return control != null; 291 } 292 293 protected JMenuBar createMenuBarControl() { 294 JMenuBar menuBar = menuBarCommandGroup.createMenuBar(); 295 menuBarCommandGroup.setVisible( getWindowConfigurer().getShowMenuBar() ); 296 return menuBar; 297 } 298 299 protected JComponent createToolBarControl() { 300 JComponent toolBar = toolBarCommandGroup.createToolBar(); 301 toolBarCommandGroup.setVisible( getWindowConfigurer().getShowToolBar() ); 302 return toolBar; 303 } 304 305 protected JComponent createStatusBarControl() { 306 JComponent statusBarControl = statusBar.getControl(); 307 statusBarControl.setVisible( getWindowConfigurer().getShowStatusBar() ); 308 return statusBarControl; 309 } 310 311 public void addPageListener( PageListener listener ) { 312 this.pageListeners.add( listener ); 313 } 314 315 public void removePageListener( PageListener listener ) { 316 this.pageListeners.remove( listener ); 317 } 318 319 /** 320 * Close this window. First checks with the advisor by calling the 321 * {@link ApplicationLifecycleAdvisor#onPreWindowClose(ApplicationWindow)} 322 * method. Then tries to close it's currentPage. If both are successfull, 323 * the window will be disposed and removed from the {@link WindowManager}. 324 * 325 * @return boolean <code>true</code> if both, the advisor and the 326 * currentPage allow the closing action. 327 */ 328 public boolean close() { 329 boolean canClose = getAdvisor().onPreWindowClose( this ); 330 if( canClose ) { 331 // check if page can be closed 332 if( currentPage != null ) { 333 canClose = currentPage.close(); 334 // page cannot be closed, exit method and do not dispose 335 if (!canClose) 336 return canClose; 337 } 338 339 if( control != null ) { 340 control.dispose(); 341 control = null; 342 } 343 344 if( windowManager != null ) { 345 windowManager.remove( this ); 346 } 347 windowManager = null; 348 } 349 return canClose; 350 } 351 352 /** 353 * When gaining focus, set this window as the active one on it's manager. 354 */ 355 public void windowGainedFocus( WindowEvent e ) { 356 if( this.windowManager != null ) 357 this.windowManager.setActiveWindow( this ); 358 } 359 360 /** 361 * When losing focus no action is done. This way the last focussed window will stay 362 * listed as the activeWindow. 363 */ 364 public void windowLostFocus( WindowEvent e ) { 365 } 366 367 /** 368 * Implementors create the component that contains the contents of this window. 369 * 370 * @return the content pane 371 */ 372 protected abstract JComponent createWindowContentPane(); 373 }