001    /*
002     * Copyright 2002-2008 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.docking.vldocking;
017    
018    import java.io.BufferedOutputStream;
019    import java.io.File;
020    import java.io.FileOutputStream;
021    import java.io.IOException;
022    import java.util.HashMap;
023    import java.util.Map;
024    
025    import org.apache.commons.logging.Log;
026    import org.apache.commons.logging.LogFactory;
027    import org.springframework.richclient.application.Application;
028    import org.springframework.richclient.application.ApplicationPage;
029    import org.springframework.richclient.application.ApplicationPageFactory;
030    import org.springframework.richclient.application.ApplicationWindow;
031    import org.springframework.richclient.application.PageDescriptor;
032    import org.springframework.richclient.application.PageListener;
033    
034    import com.vlsolutions.swing.docking.DockingContext;
035    
036    /**
037     * <tt>ApplicationPageFactory</tt> that creates instances of <tt>VLDockingApplicationPage</tt>.
038     * 
039     * @author Rogan Dawes
040     */
041    public class VLDockingApplicationPageFactory implements ApplicationPageFactory {
042    
043        private static final Log logger = LogFactory.getLog(VLDockingApplicationPageFactory.class);
044    
045        private boolean reusePages;
046        private Map pageCache = new HashMap();
047    
048        /*
049         * (non-Javadoc)
050         * 
051         * @see org.springframework.richclient.application.ApplicationPageFactory#createApplicationPage(org.springframework.richclient.application.ApplicationWindow,
052         *      org.springframework.richclient.application.PageDescriptor)
053         */
054        public ApplicationPage createApplicationPage(ApplicationWindow window, PageDescriptor descriptor) {
055            if (reusePages) {
056                VLDockingApplicationPage page = findPage(window, descriptor);
057                if (page != null) {
058                    return page;
059                }
060            }
061            VLDockingApplicationPage page = new VLDockingApplicationPage(window, descriptor);
062            if (reusePages) {
063                cachePage(page);
064            }
065    
066            window.addPageListener(new PageListener() {
067                public void pageOpened(ApplicationPage page) {
068                    // nothing to do here
069                }
070    
071                public void pageClosed(ApplicationPage page) {
072                    VLDockingApplicationPage vlDockingApplicationPage = (VLDockingApplicationPage) page;
073                    saveDockingContext(vlDockingApplicationPage);
074                }
075            });
076    
077            return page;
078        }
079    
080        /**
081         * Saves the docking layout of a docking page fo the application
082         * 
083         * @param appWindow
084         *            The application window (needed to hook in for the docking context)
085         */
086        private void saveDockingContext(VLDockingApplicationPage dockingPage) {
087            DockingContext dockingContext = dockingPage.getDockingContext();
088    
089            // Page descriptor needed for config path
090            VLDockingPageDescriptor vlDockingPageDescriptor = (VLDockingPageDescriptor) Application.instance()
091                    .getApplicationContext().getBean(dockingPage.getId());
092    
093            // Write docking context to file
094            BufferedOutputStream buffOs = null;
095            try {
096                File desktopLayoutFile = vlDockingPageDescriptor.getInitialLayout().getFile();
097                checkForConfigPath(desktopLayoutFile);
098    
099                buffOs = new BufferedOutputStream(new FileOutputStream(desktopLayoutFile));
100                dockingContext.writeXML(buffOs);
101                buffOs.close();
102                logger.debug("Wrote docking context to config file " + desktopLayoutFile);
103    
104            }
105            catch (IOException e) {
106                logger.warn("Error writing VLDocking config", e);
107            }
108            finally {
109                try {
110                    buffOs.close();
111                }
112                catch (Exception e) {
113                }
114            }
115        }
116    
117        /**
118         * Creates the config directory, if it doesn't exist already
119         * 
120         * @param configFile
121         *            The file for which to create the path
122         */
123        private void checkForConfigPath(File configFile) {
124            String desktopLayoutFilePath = configFile.getAbsolutePath();
125            String configDirPath = desktopLayoutFilePath.substring(0, desktopLayoutFilePath.lastIndexOf(System
126                    .getProperty("file.separator")));
127            File configDir = new File(configDirPath);
128    
129            // create config dir if it does not exist
130            if (!configDir.exists()) {
131                configDir.mkdirs();
132                logger.debug("Newly created config directory");
133            }
134        }
135    
136        protected VLDockingApplicationPage findPage(ApplicationWindow window, PageDescriptor descriptor) {
137            Map pages = (Map) pageCache.get(window);
138            if (pages == null) {
139                return null;
140            }
141            
142            return (VLDockingApplicationPage) pages.get(descriptor.getId());
143        }
144    
145        protected void cachePage(VLDockingApplicationPage page) {
146            Map pages = (Map) pageCache.get(page.getWindow());
147            if (pages == null) {
148                pages = new HashMap();
149                pageCache.put(page.getWindow(), pages);
150            }
151            pages.put(page.getId(), page);
152        }
153    
154        /**
155         * @param reusePages
156         *            the reusePages to set
157         */
158        public void setReusePages(boolean reusePages) {
159            this.reusePages = reusePages;
160        }
161    }