| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| |
| package org.netbeans.core.windows; |
| |
| |
| |
| import java.awt.Dimension; |
| import java.awt.Frame; |
| import java.awt.GraphicsDevice; |
| import java.awt.GraphicsEnvironment; |
| import java.awt.Rectangle; |
| import java.awt.Toolkit; |
| import java.io.IOException; |
| import java.util.*; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| import org.netbeans.core.windows.persistence.*; |
| import org.openide.awt.ToolbarPool; |
| import org.openide.filesystems.FileObject; |
| import org.openide.util.Exceptions; |
| import org.openide.util.Utilities; |
| import org.openide.windows.*; |
| |
| |
| /** |
| * Class which handles loading, saving of window system and persistence events. |
| * |
| * @author Peter Zavadsky, Marek Slama |
| */ |
| final public class PersistenceHandler implements PersistenceObserver { |
| |
| // Persistence data |
| /** Maps mode config name to mode instance. */ |
| private final Map<String, ModeImpl> name2mode = new WeakHashMap<String, ModeImpl>(10); |
| /** Maps group config name to group instance. */ |
| private final Map<String, TopComponentGroupImpl> name2group = new WeakHashMap<String, TopComponentGroupImpl>(10); |
| |
| private static PersistenceHandler defaultInstance; |
| |
| private boolean loaded = false; |
| |
| /** Debugging flag. */ |
| private static final boolean DEBUG = Debug.isLoggable(PersistenceHandler.class); |
| |
| private final LazyLoader lazyLoader = new LazyLoader(); |
| |
| |
| /** Creates a new instance of PersistenceHanlder */ |
| private PersistenceHandler() { |
| } |
| |
| /** |
| * Clears cached data. |
| */ |
| public void clear() { |
| name2mode.clear(); |
| name2group.clear(); |
| TopComponentTracker.getDefault().clear(); |
| } |
| |
| public static synchronized PersistenceHandler getDefault() { |
| if(defaultInstance == null) { |
| defaultInstance = new PersistenceHandler(); |
| } |
| |
| return defaultInstance; |
| } |
| |
| // XXX helper method |
| public static boolean isTopComponentPersistentWhenClosed(TopComponent tc) { |
| return PersistenceManager.isTopComponentPersistentWhenClosed(tc); |
| } |
| |
| boolean isLoaded() { |
| return loaded; |
| } |
| |
| public void load() { |
| if(DEBUG) { |
| debugLog("## PersistenceHandler.load"); // NOI18N |
| } |
| |
| TopComponentTracker.getDefault().load(); |
| |
| WindowManagerConfig wmc = null; |
| try { |
| wmc = PersistenceManager.getDefault().loadWindowSystem(); |
| } catch (IOException exc) { |
| // Serious persistence problem -> try to reset |
| Exceptions.attachLocalizedMessage(exc, "Cannot load window system persistent data, user directory content is broken. Resetting to default layout..."); //NOI18N |
| Logger.getLogger(PersistenceHandler.class.getName()).log(Level.WARNING, null, exc); // NOI18N |
| // try to delete local winsys data and try once more |
| try { |
| FileObject rootFolder = PersistenceManager.getDefault().getRootLocalFolder(); |
| if (null != rootFolder) { |
| rootFolder.delete(); |
| wmc = PersistenceManager.getDefault().loadWindowSystem(); |
| } else { |
| Logger.getLogger(PersistenceHandler.class.getName()).log(Level.WARNING, "Cannot even get access to local winsys configuration, using internally predefined configuration."); // NOI18N |
| wmc = ConfigFactory.createDefaultConfig(); |
| } |
| } catch (IOException ioE) { |
| Exceptions.attachLocalizedMessage(ioE, "Cannot load even default layout, using internally predefined configuration."); //NOI18N |
| Logger.getLogger(PersistenceHandler.class.getName()).log(Level.WARNING, null, ioE); |
| wmc = ConfigFactory.createDefaultConfig(); |
| } |
| } |
| |
| ToolbarPool.getDefault().setPreferredIconSize(wmc.preferredToolbarIconSize); |
| |
| WindowManagerImpl wm = WindowManagerImpl.getInstance(); |
| if (wmc.tcIdViewList.length > 0) { |
| wm.setRecentViewList(wmc.tcIdViewList); |
| } else { |
| //No recent view list is saved, fill it by opened TopComponents |
| List<String> idList = new ArrayList<>(); |
| for (int i = 0; i < wmc.modes.length; i++) { |
| ModeConfig mc = wmc.modes[i]; |
| for (int j = 0; j < mc.tcRefConfigs.length; j++) { |
| //Only opened |
| if (mc.tcRefConfigs[j].opened) { |
| idList.add(mc.tcRefConfigs[j].tc_id); |
| } |
| } |
| } |
| wm.setRecentViewList(idList.toArray( new String[idList.size()])); |
| } |
| |
| wm.setEditorAreaConstraints(wmc.editorAreaConstraints); |
| wm.setEditorAreaState(wmc.editorAreaState); |
| |
| ModeImpl activeMode = null; |
| ModeImpl editorMaximizedMode = null; |
| ModeImpl viewMaximizedMode = null; |
| |
| // First create empty modes. |
| Map<ModeImpl, ModeConfig> mode2config = new HashMap<ModeImpl, ModeConfig>(); |
| |
| for (int i = 0; i < wmc.modes.length; i++) { |
| ModeConfig mc = (ModeConfig) wmc.modes[i]; |
| ModeImpl mode = getModeFromConfig(mc); |
| |
| mode2config.put(mode, mc); |
| |
| if(mc.name.equals(wmc.activeModeName)) { |
| activeMode = mode; |
| } |
| if(mc.name.equals(wmc.editorMaximizedModeName)) { |
| editorMaximizedMode = mode; |
| } else if(mc.name.equals(wmc.viewMaximizedModeName)) { |
| viewMaximizedMode = mode; |
| } |
| } |
| |
| TopComponentTracker tcTracker = TopComponentTracker.getDefault(); |
| TopComponent activeTopComponentOverride = null; |
| // Then fill them with TopComponents. |
| for(Iterator it = mode2config.keySet().iterator(); it.hasNext(); ) { |
| ModeImpl mode = (ModeImpl)it.next(); |
| ModeConfig mc = (ModeConfig)mode2config.get(mode); |
| initModeFromConfig(mode, mc, false); |
| initPreviousModes(mode, mc, mode2config); |
| |
| // Set selected TopComponent. |
| if(mc.selectedTopComponentID != null) { |
| mode.setUnloadedSelectedTopComponent(mc.selectedTopComponentID); |
| } |
| if(mc.previousSelectedTopComponentID != null) { |
| mode.setUnloadedPreviousSelectedTopComponent(mc.previousSelectedTopComponentID); |
| } |
| for( String tcId : mode.getTopComponentsIDs() ) { |
| tcTracker.add( tcId, mode ); |
| } |
| //some TopComponents want to be always active when the window system starts (e.g. welcome screen) |
| for( TopComponent tc : mode.getOpenedTopComponents() ) { |
| Object val = tc.getClientProperty( Constants.ACTIVATE_AT_STARTUP ); |
| if( null != val && val instanceof Boolean && ((Boolean)val).booleanValue() ) { |
| activeTopComponentOverride = tc; |
| break; |
| } |
| } |
| } |
| |
| //Initialize top component groups |
| for (int i = 0; i < wmc.groups.length; i++) { |
| GroupConfig groupCfg = wmc.groups[i]; |
| createTopComponentGroupFromConfig(groupCfg); |
| } |
| |
| // XXX #37188, 40237 Hot fix for the problem with initing active |
| // component (even it is not on screen yet). |
| if(activeMode != null) { |
| TopComponent active = activeMode.getSelectedTopComponent(); |
| if(active != null) { |
| WindowManagerImpl.getInstance().specialPersistenceCompShow(active); |
| } |
| } |
| // active mode can be null, Active mode info is stored in winsys config (system layer) and modes in |
| // project layer, that can cause out of synch state when switching projects... |
| // setting null is however considered a valid state. |
| wm.setActiveMode(activeMode); |
| wm.setEditorMaximizedMode(editorMaximizedMode); |
| wm.setViewMaximizedMode(viewMaximizedMode); |
| |
| Rectangle joinedBounds = computeBounds( |
| wmc.centeredHorizontallyJoined, |
| wmc.centeredVerticallyJoined, |
| wmc.xJoined, |
| wmc.yJoined, |
| wmc.widthJoined, |
| wmc.heightJoined, |
| wmc.relativeXJoined, |
| wmc.relativeYJoined, |
| wmc.relativeWidthJoined, |
| wmc.relativeHeightJoined); |
| if(joinedBounds != null) { |
| wm.setMainWindowBoundsJoined(joinedBounds); |
| } |
| // PENDING else { ...some default value? |
| |
| Rectangle separatedBounds = computeBounds( |
| wmc.centeredHorizontallySeparated, |
| wmc.centeredVerticallySeparated, |
| wmc.xSeparated, |
| wmc.ySeparated, |
| wmc.widthSeparated, |
| wmc.heightSeparated, |
| wmc.relativeXSeparated, |
| wmc.relativeYSeparated, |
| wmc.relativeWidthSeparated, |
| wmc.relativeHeightSeparated); |
| if(separatedBounds != null) { |
| wm.setMainWindowBoundsSeparated(separatedBounds); |
| } |
| // PENDING else { ...some default value? |
| |
| wm.setMainWindowFrameStateJoined(wmc.mainWindowFrameStateJoined); |
| wm.setMainWindowFrameStateSeparated(wmc.mainWindowFrameStateSeparated); |
| |
| Rectangle absBounds = wmc.editorAreaBounds == null ? new Rectangle() : wmc.editorAreaBounds; |
| Rectangle relBounds = wmc.editorAreaRelativeBounds == null ? new Rectangle() : wmc.editorAreaRelativeBounds; |
| Rectangle bounds = computeBounds(false, false, |
| absBounds.x, |
| absBounds.y, |
| absBounds.width, |
| absBounds.height, |
| relBounds.x / 100.0F, |
| relBounds.y / 100.0F, |
| relBounds.width / 100.0F, |
| relBounds.height / 100.0F); |
| wm.setEditorAreaBounds(bounds); |
| wm.setEditorAreaFrameState(wmc.editorAreaFrameState); |
| wm.setToolbarConfigName(wmc.toolbarConfiguration); |
| if( null != activeTopComponentOverride ) |
| activeTopComponentOverride.requestActive(); |
| |
| loaded = true; |
| } |
| |
| |
| /** Implements <code>WindowSystem</code> interface method. */ |
| public synchronized void save() { |
| if( !loaded ) |
| return; //nothing to save |
| if(DEBUG) { |
| debugLog("## PersistenceHandler.save"); // NOI18N |
| } |
| TopComponentTracker.getDefault().save(); |
| |
| ToolbarPool.getDefault().waitFinished(); |
| WindowManagerConfig wmc = getConfig(); |
| PersistenceManager.getDefault().saveWindowSystem(wmc); |
| } |
| |
| private ModeImpl getModeFromConfig(ModeConfig mc) { |
| if(DEBUG) { |
| debugLog("Getting mode name=" + mc.name); |
| } |
| |
| ModeImpl mode = (ModeImpl)WindowManagerImpl.getInstance().findMode(mc.name); |
| if(mode == null) { |
| mode = createModeFromConfig(mc); |
| } |
| return mode; |
| } |
| |
| private ModeImpl createModeFromConfig(ModeConfig mc) { |
| if(DEBUG) { |
| debugLog(""); // NOI18N |
| debugLog("Creating mode name=\"" + mc.name + "\""); // NOI18N |
| } |
| |
| ModeImpl mode; |
| if (mc.kind == Constants.MODE_KIND_SLIDING) { |
| mode = WindowManagerImpl.getInstance().createSlidingMode( |
| mc.name, mc.permanent, mc.side, mc.slideInSizes); |
| } else { |
| mode = WindowManagerImpl.getInstance().createMode( |
| mc.name, mc.kind, mc.state, mc.permanent, mc.constraints); |
| } |
| name2mode.put(mc.name, mode); |
| if( mc.minimized ) |
| mode.setMinimized( mc.minimized ); |
| if( null != mc.otherNames ) { |
| for( String s : mc.otherNames ) { |
| mode.addOtherName( s ); |
| } |
| } |
| |
| return mode; |
| } |
| |
| /** |
| * find the the previous mode for tc if exists and set it in the model.. |
| */ |
| private void initPreviousModes(ModeImpl mode, ModeConfig mc, Map modes) { |
| for (int j = 0; j < mc.tcRefConfigs.length; j++) { |
| TCRefConfig tcRefConfig = mc.tcRefConfigs[j]; |
| if(DEBUG) { |
| debugLog("\tTopComponent[" + j + "] id=\"" // NOI18N |
| + tcRefConfig.tc_id + "\", \topened=" + tcRefConfig.opened); // NOI18N |
| } |
| if (tcRefConfig.previousMode != null) { |
| Iterator it = modes.keySet().iterator(); |
| ModeImpl previous = null; |
| while (it.hasNext()) { |
| ModeImpl md = (ModeImpl)it.next(); |
| |
| if (tcRefConfig.previousMode.equals(md.getName()) |
| || md.getOtherNames().contains( tcRefConfig.previousMode ) ) { |
| previous = md; |
| break; |
| } |
| } |
| if (previous != null) { |
| WindowManagerImpl.getInstance().setPreviousModeForTopComponent(tcRefConfig.tc_id, mode, previous, tcRefConfig.previousIndex); |
| } else { |
| Logger.getLogger(PersistenceHandler.class.getName()).log(Level.INFO, null, |
| new java.lang.NullPointerException("Cannot find previous mode named \'" + |
| tcRefConfig.previousMode + |
| "\'")); |
| |
| } |
| } |
| } |
| } |
| |
| /** |
| * find the the previous mode for tc if exists and set it in the model.. |
| */ |
| private void initPreviousMode (ModeImpl mode, TCRefConfig tcRefConfig) { |
| if(DEBUG) { |
| debugLog("\tTopComponent id=\"" // NOI18N |
| + tcRefConfig.tc_id + "\", \topened=" + tcRefConfig.opened); // NOI18N |
| } |
| if (tcRefConfig.previousMode == null) { |
| return; |
| } |
| Set<? extends ModeImpl> modes = WindowManagerImpl.getInstance().getModes(); |
| Iterator it = modes.iterator(); |
| ModeImpl previous = null; |
| while (it.hasNext()) { |
| ModeImpl md = (ModeImpl) it.next(); |
| |
| if (tcRefConfig.previousMode.equals(md.getName()) |
| || md.getOtherNames().contains( tcRefConfig.previousMode ) ) { |
| previous = md; |
| break; |
| } |
| } |
| if (previous != null) { |
| WindowManagerImpl.getInstance().setPreviousModeForTopComponent |
| (tcRefConfig.tc_id, mode, previous, tcRefConfig.previousIndex); |
| } else { |
| Logger.getLogger(PersistenceHandler.class.getName()).log(Level.INFO, null, |
| new java.lang.NullPointerException("Cannot find previous mode named \'" + |
| tcRefConfig.previousMode + |
| "\'")); |
| } |
| } |
| |
| private ModeImpl initModeFromConfig(ModeImpl mode, ModeConfig mc, boolean initPrevModes) { |
| WindowManagerImpl wm = WindowManagerImpl.getInstance(); |
| if( null != mc.otherNames ) { |
| for( String s : mc.otherNames ) { |
| mode.addOtherName( s ); |
| } |
| } |
| for (int j = 0; j < mc.tcRefConfigs.length; j++) { |
| TCRefConfig tcRefConfig = mc.tcRefConfigs[j]; |
| if(DEBUG) { |
| debugLog("\tTopComponent[" + j + "] id=\"" // NOI18N |
| + tcRefConfig.tc_id + "\", \topened=" + tcRefConfig.opened); // NOI18N |
| } |
| |
| // PENDING |
| if (tcRefConfig.opened) { |
| lazyLoader.lazyLoad(mode, mc.selectedTopComponentID, tcRefConfig, j ); |
| } else { |
| mode.addUnloadedTopComponent(tcRefConfig.tc_id); |
| } |
| wm.setTopComponentDockedInMaximizedMode( tcRefConfig.tc_id, tcRefConfig.dockedInMaximizedMode ); |
| wm.setTopComponentSlidedInDefaultMode( tcRefConfig.tc_id, !tcRefConfig.dockedInDefaultMode ); |
| wm.setTopComponentMaximizedWhenSlidedIn( tcRefConfig.tc_id, tcRefConfig.slidedInMaximized ); |
| if (initPrevModes) { |
| initPreviousMode(mode, tcRefConfig); |
| } |
| } |
| |
| // PENDING Refine the unneded computing. |
| Rectangle absBounds = mc.bounds == null ? new Rectangle() : mc.bounds; |
| Rectangle relBounds = mc.relativeBounds == null ? new Rectangle() : mc.relativeBounds; |
| Rectangle bounds = computeBounds(false, false, |
| absBounds.x, |
| absBounds.y, |
| absBounds.width, |
| absBounds.height, |
| relBounds.x / 100.0F, |
| relBounds.y / 100.0F, |
| relBounds.width / 100.0F, |
| relBounds.height / 100.0F); |
| mode.setBounds(bounds); |
| mode.setFrameState(mc.frameState); |
| mode.setMinimized( mc.minimized ); |
| |
| return mode; |
| } |
| |
| TopComponent getTopComponentForID(String tc_id, boolean deserialize) { |
| if(tc_id == null || "".equals(tc_id)) { |
| return null; |
| } |
| |
| // long start = System.currentTimeMillis(); |
| TopComponent tc = PersistenceManager.getDefault().getTopComponentForID(tc_id, deserialize); |
| // if(DEBUG) { |
| // debugLog("***Getting TopComponent for ID=" + tc_id + " in " + (System.currentTimeMillis() - start) + " ms"); // NOI18N |
| // } |
| |
| return tc; |
| } |
| |
| private TopComponentGroupImpl createTopComponentGroupFromConfig(GroupConfig groupCfg) { |
| if(DEBUG) { |
| debugLog(""); // NOI18N |
| debugLog("Creating group name=\"" + groupCfg.name + "\" \t[opened=" + groupCfg.opened + "]"); // NOI18N |
| } |
| |
| TopComponentGroupImpl tcGroup = new TopComponentGroupImpl(groupCfg.name, groupCfg.opened); |
| |
| name2group.put(groupCfg.name, tcGroup); |
| |
| for (int j = 0; j < groupCfg.tcGroupConfigs.length; j++) { |
| TCGroupConfig tcGroupCfg = groupCfg.tcGroupConfigs[j]; |
| if(DEBUG) { |
| debugLog("\tTopComponent[" + j + "] id=\"" // NOI18N |
| + tcGroupCfg.tc_id + "\", \topen=" + tcGroupCfg.open + ", \tclose=" + tcGroupCfg.close |
| + ", \twasOpened=" + tcGroupCfg.wasOpened); // NOI18N |
| } |
| |
| tcGroup.addUnloadedTopComponent(tcGroupCfg.tc_id); |
| |
| if (tcGroupCfg.open) { |
| tcGroup.addUnloadedOpeningTopComponent(tcGroupCfg.tc_id); |
| } |
| if (tcGroupCfg.close) { |
| tcGroup.addUnloadedClosingTopComponent(tcGroupCfg.tc_id); |
| } |
| |
| // Handle also wasOpened flag. |
| if(groupCfg.opened && tcGroupCfg.wasOpened) { |
| tcGroup.addGroupUnloadedOpenedTopComponent(tcGroupCfg.tc_id); |
| } |
| } |
| |
| WindowManagerImpl.getInstance().addTopComponentGroup(tcGroup); |
| |
| return tcGroup; |
| } |
| |
| |
| |
| private WindowManagerConfig getConfig() { |
| WindowManagerConfig wmc = new WindowManagerConfig(); |
| |
| wmc.preferredToolbarIconSize = ToolbarPool.getDefault().getPreferredIconSize(); |
| |
| WindowManagerImpl wmi = WindowManagerImpl.getInstance(); |
| |
| Rectangle joinedBounds = wmi.getMainWindowBoundsJoined(); |
| if(DEBUG) { |
| debugLog("joinedBouds=" + joinedBounds); // NOI18N |
| } |
| wmc.xJoined = joinedBounds.x; |
| wmc.yJoined = joinedBounds.y; |
| wmc.widthJoined = joinedBounds.width; |
| wmc.heightJoined = joinedBounds.height; |
| Rectangle separatedBounds = wmi.getMainWindowBoundsSeparated(); |
| if(DEBUG) { |
| debugLog("separatedBounds=" + separatedBounds); // NOI18N |
| } |
| wmc.xSeparated = separatedBounds.x; |
| wmc.ySeparated = separatedBounds.y; |
| wmc.widthSeparated = separatedBounds.width; |
| wmc.heightSeparated = separatedBounds.height; |
| |
| if( Utilities.isMac() ) { |
| //125881 - mac doesn't fire events when maximized window is resized by user |
| wmc.mainWindowFrameStateJoined = wmi.getMainWindow().getExtendedState(); |
| } else { |
| wmc.mainWindowFrameStateJoined = wmi.getMainWindowFrameStateJoined(); |
| } |
| if (wmc.mainWindowFrameStateJoined == Frame.ICONIFIED) { |
| // #46646 - don't save iconified state |
| //mkleint - actually shoudn't we ignore the maximized states as well? |
| wmc.mainWindowFrameStateJoined = Frame.NORMAL; |
| } |
| if(DEBUG) { |
| debugLog("mainWindowFrameStateJoined=" + wmc.mainWindowFrameStateJoined); // NOI18N |
| } |
| wmc.mainWindowFrameStateSeparated = wmi.getMainWindowFrameStateSeparated(); |
| if (wmc.mainWindowFrameStateSeparated == Frame.ICONIFIED) { |
| // #46646 - don't save iconified state |
| wmc.mainWindowFrameStateSeparated = Frame.NORMAL; |
| } |
| if(DEBUG) { |
| debugLog("mainWindowFrameStateSeparated=" + wmc.mainWindowFrameStateSeparated); // NOI18N |
| } |
| |
| wmc.editorAreaState = wmi.getEditorAreaState(); |
| if(DEBUG) { |
| debugLog("editorAreaState=" + wmc.editorAreaState); // NOI18N |
| } |
| wmc.editorAreaBounds = wmi.getEditorAreaBounds(); |
| if(DEBUG) { |
| debugLog("editorAreaBounds=" + wmc.editorAreaBounds); // NOI18N |
| } |
| wmc.editorAreaConstraints = wmi.getEditorAreaConstraints(); |
| if(DEBUG) { |
| debugLog("editorAreaConstraints=" + Arrays.toString(wmc.editorAreaConstraints)); // NOI18N |
| } |
| wmc.editorAreaFrameState = wmi.getEditorAreaFrameState(); |
| if(DEBUG) { |
| debugLog("editorAreaFrameState=" + wmc.editorAreaFrameState); // NOI18N |
| } |
| wmc.screenSize = Toolkit.getDefaultToolkit().getScreenSize(); |
| |
| ModeImpl mo = wmi.getActiveMode(); |
| if(DEBUG) { |
| debugLog("active mode=" + mo); // NOI18N |
| } |
| if (mo != null) { |
| wmc.activeModeName = mo.getName(); |
| } |
| |
| mo = wmi.getEditorMaximizedMode(); |
| if(DEBUG) { |
| debugLog("editor maximized mode=" + mo); // NOI18N |
| } |
| if (mo != null) { |
| wmc.editorMaximizedModeName = mo.getName(); |
| } |
| |
| mo = wmi.getViewMaximizedMode(); |
| if(DEBUG) { |
| debugLog("view maximized mode=" + mo); // NOI18N |
| } |
| if (mo != null) { |
| wmc.viewMaximizedModeName = mo.getName(); |
| } |
| |
| wmc.toolbarConfiguration = wmi.getToolbarConfigName(); |
| if(DEBUG) { |
| debugLog("toolbarConfiguration=" + wmc.toolbarConfiguration); // NOI18N |
| } |
| |
| // Modes. |
| Set<? extends Mode> modeSet = wmi.getModes(); |
| List<ModeConfig> modeConfigs = new ArrayList<ModeConfig>(modeSet.size()); |
| for (Iterator<? extends Mode> it = modeSet.iterator(); it.hasNext(); ) { |
| ModeImpl modeImpl = (ModeImpl)it.next(); |
| //Do not save empty non permanent mode |
| ModeConfig mc = getConfigFromMode(modeImpl); |
| if ((mc.tcRefConfigs.length == 0) && (!mc.permanent) && wmi.getCentral().doCheckSlidingModes(modeImpl)) { |
| continue; |
| } |
| modeConfigs.add(mc); |
| } |
| wmc.modes = modeConfigs.toArray(new ModeConfig[0]); |
| |
| // TopComponent groups. |
| Set<TopComponentGroupImpl> tcGroups = wmi.getTopComponentGroups(); |
| List<GroupConfig> groupConfigs = new ArrayList<GroupConfig>(tcGroups.size()); |
| for (Iterator<TopComponentGroupImpl> it = tcGroups.iterator(); it.hasNext(); ) { |
| groupConfigs.add(getConfigFromGroup(it.next())); |
| } |
| wmc.groups = groupConfigs.toArray(new GroupConfig[0]); |
| |
| PersistenceManager pm = PersistenceManager.getDefault(); |
| //RecentViewList |
| TopComponent [] tcs = wmi.getRecentViewList(); |
| List<String> tcIdList = new ArrayList<String>(tcs.length); |
| for (int i = 0; i < tcs.length; i++) { |
| if (pm.isTopComponentPersistent(tcs[i])) { |
| String tc_id = WindowManager.getDefault().findTopComponentID(tcs[i]); |
| tc_id = PersistenceManager.escapeTcId4XmlContent(tc_id); |
| tcIdList.add(tc_id); |
| } |
| } |
| wmc.tcIdViewList = tcIdList.toArray(new String [tcIdList.size()]); |
| |
| return wmc; |
| } |
| |
| public ModeConfig getConfigFromMode(ModeImpl mode) { |
| PersistenceManager pm = PersistenceManager.getDefault(); |
| WindowManagerImpl wm = WindowManagerImpl.getInstance(); |
| ModeConfig modeCfg = new ModeConfig(); |
| modeCfg.name = mode.getName(); |
| if(DEBUG) { |
| debugLog(""); // NOI18N |
| debugLog("mode name=" + modeCfg.name); // NOI18N |
| } |
| modeCfg.state = mode.getState(); |
| if(DEBUG) { |
| debugLog("mode state=" + modeCfg.state); // NOI18N |
| } |
| |
| modeCfg.kind = mode.getKind(); |
| if(DEBUG) { |
| debugLog("mode kind=" + modeCfg.kind); // NOI18N |
| } |
| if (wm instanceof WindowManagerImpl) { |
| modeCfg.side = wm.getCentral().getModeSide(mode); |
| if( null != modeCfg.side ) { |
| modeCfg.slideInSizes = wm.getCentral().getSlideInSizes( modeCfg.side ); |
| } |
| } |
| if(DEBUG) { |
| debugLog("mode side=" + modeCfg.side); // NOI18N |
| } |
| |
| modeCfg.constraints = mode.getConstraints(); |
| if(DEBUG) { |
| debugLog("mode constraints=" + Arrays.toString(modeCfg.constraints)); // NOI18N |
| } |
| // PENDING Whether to save relative or absolute bounds. |
| // In case of relative, they would need to be computed. |
| Rectangle relBounds = null; |
| if (relBounds != null) { |
| modeCfg.relativeBounds = relBounds; |
| } else { |
| modeCfg.bounds = mode.getBounds(); |
| if(DEBUG) { |
| debugLog("mode bounds=" + modeCfg.bounds); // NOI18N |
| } |
| } |
| modeCfg.frameState = mode.getFrameState(); |
| if(DEBUG) { |
| debugLog("mode frame state=" + modeCfg.frameState); // NOI18N |
| } |
| if( modeCfg.frameState == Frame.MAXIMIZED_BOTH && Utilities.isWindows() ) { |
| //#200199 - when a window is maximized on MS Windows its bounds origin |
| //are shifted -4 pixels horizontally and vertically for some reason |
| //so the window location may seem to be out of screen on some multi-monitor setups |
| if( modeCfg.bounds.x < 0 ) { |
| modeCfg.bounds.x += 4; |
| modeCfg.bounds.width -= 4; |
| } |
| if( modeCfg.bounds.y < 0 ) { |
| modeCfg.bounds.y += 4; |
| modeCfg.bounds.height -= 4; |
| } |
| |
| } |
| |
| TopComponent selectedTC = mode.getSelectedTopComponent(); |
| if(selectedTC != null) { |
| if (pm.isTopComponentPersistent(selectedTC)) { |
| String tc_id = wm.findTopComponentID(selectedTC); |
| if(DEBUG) { |
| debugLog("selected tc=" + selectedTC.getName()); // NOI18N |
| } |
| modeCfg.selectedTopComponentID = tc_id; |
| } |
| } |
| modeCfg.permanent = mode.isPermanent(); |
| if(DEBUG) { |
| debugLog("mode permanent=" + modeCfg.permanent); // NOI18N |
| } |
| |
| String prevSelectedTCID = mode.getPreviousSelectedTopComponentID(); |
| if(prevSelectedTCID != null) { |
| if(DEBUG) { |
| debugLog("previous selected tc id=" + prevSelectedTCID); // NOI18N |
| } |
| modeCfg.previousSelectedTopComponentID = prevSelectedTCID; |
| } |
| |
| modeCfg.minimized = mode.isMinimized(); |
| |
| modeCfg.otherNames = mode.getOtherNames(); |
| |
| // TopComponents: |
| List<TCRefConfig> tcRefCfgList = new ArrayList<TCRefConfig>(); |
| List<String> openedTcIDs = mode.getOpenedTopComponentsIDs(); |
| for(Iterator it = mode.getTopComponentsIDs().iterator(); it.hasNext(); ) { |
| String tcID = (String)it.next(); |
| //Filter tc we do not want to save |
| boolean opened = openedTcIDs.contains(tcID); |
| if (opened) { |
| if (pm.isTopComponentNonPersistentForID(tcID)) { |
| continue; |
| } |
| } else { |
| if (pm.isTopComponentNonPersistentForID(tcID)) { |
| continue; |
| } else if (pm.isTopComponentPersistentOnlyOpenedForID(tcID)) { |
| continue; |
| } |
| } |
| |
| // #45981: save previous mode even for closed tcs |
| String modeName = null; |
| int prevIndex = -1; |
| ModeImpl prev = wm.getPreviousModeForTopComponent(tcID, mode); |
| if (prev != null) { |
| modeName = prev.getName(); |
| prevIndex = wm.getPreviousIndexForTopComponent(tcID, mode); |
| } |
| |
| if(DEBUG) { |
| debugLog("tc ID=" + tcID + " opened=" + opened); // NOI18N |
| } |
| TCRefConfig tcRefCfg = new TCRefConfig(); |
| tcRefCfg.tc_id = tcID; |
| tcRefCfg.opened = opened; |
| tcRefCfg.previousMode = modeName; |
| tcRefCfg.previousIndex = prevIndex; |
| tcRefCfg.dockedInMaximizedMode = wm.isTopComponentDockedInMaximizedMode( tcID ); |
| tcRefCfg.dockedInDefaultMode = !wm.isTopComponentSlidedInDefaultMode( tcID ); |
| tcRefCfg.slidedInMaximized = wm.isTopComponentMaximizedWhenSlidedIn( tcID ); |
| tcRefCfgList.add(tcRefCfg); |
| } |
| |
| modeCfg.tcRefConfigs = tcRefCfgList.toArray(new TCRefConfig[tcRefCfgList.size()]); |
| return modeCfg; |
| } |
| |
| private GroupConfig getConfigFromGroup(TopComponentGroupImpl tcGroup) { |
| GroupConfig groupCfg = new GroupConfig(); |
| groupCfg.name = tcGroup.getName(); |
| groupCfg.opened = tcGroup.isOpened(); |
| if(DEBUG) { |
| debugLog(""); // NOI18N |
| debugLog("group name=" + groupCfg.name); // NOI18N |
| } |
| Set<String> openSet = tcGroup.getOpeningSetIDs(); |
| Set<String> closeSet = tcGroup.getClosingSetIDs(); |
| Set<String> wasOpenedSet = tcGroup.getGroupOpenedTopComponentsIDs(); |
| |
| Map<String, TCGroupConfig> tcGroupCfgMap = new HashMap<String, TCGroupConfig>(); |
| |
| for (String tcID: tcGroup.getTopComponentsIDs()) { |
| |
| TCGroupConfig tcGroupCfg; |
| if (tcGroupCfgMap.containsKey(tcID)) { |
| tcGroupCfg = tcGroupCfgMap.get(tcID); |
| } else { |
| tcGroupCfg = new TCGroupConfig(); |
| tcGroupCfg.tc_id = tcID; |
| tcGroupCfgMap.put(tcID, tcGroupCfg); |
| } |
| |
| tcGroupCfg.open = openSet.contains(tcID); |
| tcGroupCfg.close = closeSet.contains(tcID); |
| if(groupCfg.opened) { |
| tcGroupCfg.wasOpened = wasOpenedSet.contains(tcID); |
| } |
| if(DEBUG) { |
| debugLog("tc id=" + tcGroupCfg.tc_id // NOI18N |
| + ", open=" + tcGroupCfg.open // NOI18N |
| + ", close=" + tcGroupCfg.close // NOI18N |
| + ", wasOpened=" + tcGroupCfg.wasOpened); // NOI18N |
| } |
| } |
| |
| groupCfg.tcGroupConfigs = tcGroupCfgMap.values().toArray(new TCGroupConfig[0]); |
| return groupCfg; |
| } |
| |
| |
| /** Handles adding mode to model. |
| * @param modeConfig configuration data of added mode |
| */ |
| @Override |
| public synchronized void modeConfigAdded(ModeConfig modeConfig) { |
| if(DEBUG) { |
| debugLog("WMI.modeConfigAdded mo:" + modeConfig.name); // NOI18N |
| } |
| ModeImpl mode = getModeFromConfig(modeConfig); |
| initModeFromConfig(mode, modeConfig, true); |
| } |
| |
| /** Handles removing mode from model. |
| * @param modeName unique name of removed mode |
| */ |
| @Override |
| public synchronized void modeConfigRemoved(String modeName) { |
| if(DEBUG) { |
| debugLog("WMI.modeConfigRemoved mo:" + modeName); // NOI18N |
| } |
| ModeImpl mode = (ModeImpl)name2mode.remove(modeName); |
| if(mode != null) { |
| WindowManagerImpl.getInstance().removeMode(mode); |
| } else { |
| Logger.getLogger(PersistenceHandler.class.getName()).log(Level.WARNING, null, |
| new java.lang.NullPointerException("Mode for name=" + |
| modeName + |
| " was not created")); // NOI18N |
| } |
| } |
| |
| /** Handles adding tcRef to model. |
| * @param modeName unique name of parent mode. |
| * @param tcRefConfig configuration data of added tcRef |
| * @param tcRefNames array of tcIds to pass ordering of new tcRef, |
| * if there is no ordering defined tcRef is appended to end of array |
| */ |
| @Override |
| public synchronized void topComponentRefConfigAdded |
| (String modeName, TCRefConfig tcRefConfig, String [] tcRefNames) { |
| if(DEBUG) { |
| debugLog("WMI.topComponentRefConfigAdded mo:" + modeName + " tcRef:" + tcRefConfig.tc_id); // NOI18N |
| } |
| |
| WindowManagerImpl wm = WindowManagerImpl.getInstance(); |
| wm.setTopComponentDockedInMaximizedMode( tcRefConfig.tc_id, tcRefConfig.dockedInMaximizedMode ); |
| wm.setTopComponentSlidedInDefaultMode( tcRefConfig.tc_id, !tcRefConfig.dockedInDefaultMode ); |
| wm.setTopComponentMaximizedWhenSlidedIn( tcRefConfig.tc_id, tcRefConfig.slidedInMaximized ); |
| ModeImpl mode = (ModeImpl) name2mode.get(modeName); |
| if( null == mode ) { |
| for( ModeImpl m : name2mode.values() ) { |
| if( m.getOtherNames().contains( modeName ) ) { |
| mode = m; |
| break; |
| } |
| } |
| } |
| if (mode != null) { |
| initPreviousMode(mode, tcRefConfig); |
| } |
| |
| TopComponent tc = getTopComponentForID(tcRefConfig.tc_id,true); |
| if (tc != null) { |
| if (mode != null) { |
| if (tcRefConfig.opened) { |
| mode.addOpenedTopComponent(tc); |
| } else { |
| mode.addClosedTopComponent(tc); |
| } |
| } |
| } |
| } |
| |
| /** Handles removing tcRef from model. |
| * @param tc_id unique id of removed tcRef |
| */ |
| @Override |
| public synchronized void topComponentRefConfigRemoved(String tc_id) { |
| if(DEBUG) { |
| debugLog("WMI.topComponentRefConfigRemoved tcRef:" + tc_id); // NOI18N |
| } |
| |
| WindowManagerImpl wm = WindowManagerImpl.getInstance(); |
| ModeImpl mode = wm.findModeForOpenedID(tc_id); |
| if(mode != null) { |
| TopComponent tc = getTopComponentForID(tc_id,true); |
| if(tc != null) { |
| mode.removeTopComponent(tc); |
| } |
| } else { |
| mode = wm.findModeForClosedID(tc_id); |
| if(mode != null) { |
| mode.removeClosedTopComponentID(tc_id); |
| } |
| } |
| } |
| |
| /** Handles adding group to model. |
| * @param groupConfig configuration data of added group |
| */ |
| @Override |
| public synchronized void groupConfigAdded(GroupConfig groupConfig) { |
| if(DEBUG) { |
| debugLog("WMI.groupConfigAdded group:" + groupConfig.name); // NOI18N |
| } |
| createTopComponentGroupFromConfig(groupConfig); |
| } |
| |
| /** Handles removing group from model. |
| * @param groupName unique name of removed group |
| */ |
| @Override |
| public synchronized void groupConfigRemoved(String groupName) { |
| if(DEBUG) { |
| debugLog("WMI.groupConfigRemoved group:" + groupName); // NOI18N |
| } |
| TopComponentGroupImpl group = (TopComponentGroupImpl)name2group.remove(groupName); |
| if(group != null) { |
| WindowManagerImpl.getInstance().removeTopComponentGroup(group); |
| } else { |
| Logger.getLogger(PersistenceHandler.class.getName()).log(Level.WARNING, null, |
| new java.lang.NullPointerException("Null group for name=" + |
| groupName)); |
| } |
| } |
| |
| /** Handles adding tcGroup to model. |
| * @param groupName unique name of parent group |
| * @param tcGroupConfig configuration data of added tcGroup |
| */ |
| @Override |
| public synchronized void topComponentGroupConfigAdded(String groupName, TCGroupConfig tcGroupConfig) { |
| if(DEBUG) { |
| debugLog("WMI.topComponentGroupConfigAdded group:" + groupName + " tcGroup:" + tcGroupConfig.tc_id); // NOI18N |
| } |
| |
| TopComponentGroupImpl group = (TopComponentGroupImpl)name2group.get(groupName); |
| if(group != null) { |
| group.addUnloadedTopComponent(tcGroupConfig.tc_id); |
| if(tcGroupConfig.open) { |
| group.addUnloadedOpeningTopComponent(tcGroupConfig.tc_id); |
| } |
| |
| if(tcGroupConfig.close) { |
| group.addUnloadedClosingTopComponent(tcGroupConfig.tc_id); |
| } |
| } |
| } |
| |
| /** Handles removing tcGroup from model. |
| * @param groupName unique name of parent group |
| * @param tc_id unique id of removed tcGroup |
| */ |
| @Override |
| public synchronized void topComponentGroupConfigRemoved(String groupName, String tc_id) { |
| if(DEBUG) { |
| debugLog("WMI.topComponentGroupConfigRemoved group:" + groupName + " tcGroup:" + tc_id); // NOI18N |
| } |
| |
| TopComponentGroupImpl group = (TopComponentGroupImpl)name2group.get(groupName); |
| if(group != null) { |
| group.removeUnloadedTopComponent(tc_id); |
| } |
| } |
| |
| /** Dump window manager configuration data to standard output. */ |
| private static String dumpConfig (WindowManagerConfig wmc) { |
| StringBuffer buffer = new StringBuffer(); |
| buffer.append("\n-- wmc: [" + Integer.toHexString(System.identityHashCode(wmc)) + "]"); |
| buffer.append("\n-- JOINED --"); |
| buffer.append("\n-- x: " + wmc.xJoined); |
| buffer.append("\n-- y: " + wmc.yJoined); |
| buffer.append("\n-- width: " + wmc.widthJoined); |
| buffer.append("\n-- height: " + wmc.heightJoined); |
| buffer.append("\n-- relativeX: " + wmc.relativeXJoined); |
| buffer.append("\n-- relativeY: " + wmc.relativeYJoined); |
| buffer.append("\n-- relativeWidth: " + wmc.relativeWidthJoined); |
| buffer.append("\n-- relativeHeight: " + wmc.relativeHeightJoined); |
| buffer.append("\n-- centeredHorizontally: " + wmc.centeredHorizontallyJoined); |
| buffer.append("\n-- centeredVertically: " + wmc.centeredVerticallyJoined); |
| buffer.append("\n-- maximizeIfWidthBelowJoined: " + wmc.maximizeIfWidthBelowJoined); |
| buffer.append("\n-- maximizeIfHeightBelowJoined: " + wmc.maximizeIfHeightBelowJoined); |
| |
| buffer.append("\n-- SEPARATED --"); |
| buffer.append("\n-- x: " + wmc.xSeparated); |
| buffer.append("\n-- y: " + wmc.ySeparated); |
| buffer.append("\n-- width: " + wmc.widthSeparated); |
| buffer.append("\n-- height: " + wmc.heightSeparated); |
| buffer.append("\n-- relativeX: " + wmc.relativeXSeparated); |
| buffer.append("\n-- relativeY: " + wmc.relativeYSeparated); |
| buffer.append("\n-- relativeWidth: " + wmc.relativeWidthSeparated); |
| buffer.append("\n-- relativeHeight: " + wmc.relativeHeightSeparated); |
| buffer.append("\n-- centeredHorizontally: " + wmc.centeredHorizontallySeparated); |
| buffer.append("\n-- centeredVertically: " + wmc.centeredVerticallySeparated); |
| |
| buffer.append("\n-- editorAreaState: " + wmc.editorAreaState); |
| if(wmc.editorAreaConstraints != null) { |
| for (int i = 0; i < wmc.editorAreaConstraints.length; i++) { |
| buffer.append("\n-- co[" + i + "]: " + wmc.editorAreaConstraints[i]); |
| } |
| } |
| buffer.append("\n-- editorAreaBounds: " + wmc.editorAreaBounds); |
| buffer.append("\n-- editorAreaRelativeBounds: " + wmc.editorAreaRelativeBounds); |
| |
| buffer.append("\n-- screenSize: " + wmc.screenSize); |
| buffer.append("\n-- activeModeName: " + wmc.activeModeName); |
| buffer.append("\n-- editorMaximizedModeName: " + wmc.editorMaximizedModeName); |
| buffer.append("\n-- viewMaximizedModeName: " + wmc.viewMaximizedModeName); |
| buffer.append("\n-- toolbarconfig: " + wmc.toolbarConfiguration); |
| buffer.append("\n-- modes: " + Arrays.toString(wmc.modes) + " size " + (wmc.modes == null ? -1 : wmc.modes.length)); |
| for (int i = 0; i < wmc.modes.length; i++) { |
| ModeConfig mc = wmc.modes[i]; |
| buffer.append("\n-- --"); |
| buffer.append("\n-- -- mode[" + i + "]: " + mc.name); |
| buffer.append("\n-- -- state: " + mc.state + " " |
| + ((mc.state == Constants.MODE_STATE_JOINED) ? "joined" : "separated")); |
| if (mc.constraints != null) { |
| buffer.append("\n-- -- constraints.sz: " + mc.constraints.length); |
| for (int j = 0; j < mc.constraints.length; j++) { |
| buffer.append("\n-- -- co[" + j + "]: " + mc.constraints[j]); |
| } |
| } |
| buffer.append("\n-- -- kind: " + mc.kind + " "); |
| if (mc.kind == Constants.MODE_KIND_EDITOR) { |
| buffer.append("editor"); |
| } else if (mc.kind == Constants.MODE_KIND_VIEW) { |
| buffer.append("view"); |
| } else if (mc.kind == Constants.MODE_KIND_SLIDING) { |
| buffer.append("sliding"); |
| } else { |
| buffer.append("unknown"); |
| } |
| buffer.append("\n-- -- bounds: " + mc.bounds); |
| buffer.append("\n-- -- relativeBounds: " + mc.relativeBounds); |
| buffer.append("\n-- -- state: " + mc.frameState); |
| buffer.append("\n-- -- active-tc: " + mc.selectedTopComponentID); |
| buffer.append("\n-- -- permanent: " + mc.permanent); |
| if (mc.tcRefConfigs != null) { |
| for (int k = 0; k < mc.tcRefConfigs.length; k++) { |
| TCRefConfig tcRefCfg = mc.tcRefConfigs[k]; |
| buffer.append("\n++ ++ ++ tcRef[" + k + "]: " + tcRefCfg.tc_id); |
| buffer.append("\n++ ++ ++ opened: " + tcRefCfg.opened); |
| } |
| } |
| } |
| buffer.append("\n-- groups: " + Arrays.toString(wmc.groups) + " size " + (wmc.groups == null ? -1 : wmc.groups.length)); |
| for (int i = 0; i < wmc.groups.length; i++) { |
| GroupConfig sc = wmc.groups[i]; |
| buffer.append("\n-- --"); |
| buffer.append("\n-- -- group[" + i + "]: " + sc.name); |
| if (sc.tcGroupConfigs != null) { |
| for (int k = 0; k < sc.tcGroupConfigs.length; k++) { |
| TCGroupConfig tcGroupCfg = sc.tcGroupConfigs[k]; |
| buffer.append("\n++ ++ ++ tcGroup[" + k + "]: " + tcGroupCfg.tc_id); |
| buffer.append("\n++ ++ ++ open: " + tcGroupCfg.open); |
| buffer.append("\n++ ++ ++ close: " + tcGroupCfg.close); |
| } |
| } |
| } |
| |
| return buffer.toString(); |
| } |
| |
| private static void debugLog(String message) { |
| Debug.log(PersistenceHandler.class, message); |
| } |
| |
| /** |
| * @return False if the given point is not inside any screen device that are currently available. |
| */ |
| private static boolean isOutOfScreen( int x, int y ) { |
| GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); |
| GraphicsDevice[] gs = ge.getScreenDevices(); |
| for( int j=0; j<gs.length; j++ ) { |
| GraphicsDevice gd = gs[j]; |
| if( gd.getType() != GraphicsDevice.TYPE_RASTER_SCREEN ) |
| continue; |
| Rectangle bounds = gd.getDefaultConfiguration().getBounds(); |
| if( bounds.contains( x, y ) ) |
| return false; |
| } |
| return true; |
| } |
| |
| public static Rectangle computeBounds(boolean centeredHorizontaly, boolean centeredVerticaly, |
| int x, int y, int width, int height, float relativeX, float relativeY, float relativeWidth, float relativeHeight) { |
| Rectangle bounds; |
| if(width > 0 && height > 0) { |
| // From absoute values. |
| bounds = new Rectangle(x, y, width, height); |
| // #33288 fix start- when screen resolution changes, some windows may get completely out of the screen. |
| Rectangle screen = Utilities.getUsableScreenBounds(); |
| int xlimit = screen.x + screen.width - 20; // 20 = let's have some buffer area.. |
| int ylimit = screen.y + screen.height - 20; // 20 = let's have some buffer area.. |
| // will make sure that the out-of-screen windows get thrown in. |
| if( isOutOfScreen( bounds.x, bounds.y ) ) { |
| while (bounds.x > xlimit) { |
| bounds.x = Math.max(bounds.x - screen.width, screen.x); |
| } |
| while (bounds.y > ylimit) { |
| bounds.y = Math.max(bounds.y - ylimit, screen.y); |
| } |
| } |
| // #33288 fix end |
| } else if(relativeWidth > 0F && relativeHeight > 0F) { |
| // From relative values. |
| Rectangle screen = Utilities.getUsableScreenBounds(); |
| bounds = new Rectangle((int)(screen.width * relativeX), (int)(screen.height * relativeY), |
| (int)(screen.width * relativeWidth), (int)(screen.height * relativeHeight)); |
| } else { |
| return null; |
| } |
| // Center the bounds if necessary. |
| if(centeredHorizontaly || centeredVerticaly) { |
| Rectangle centered = Utilities.findCenterBounds(new Dimension(bounds.width, bounds.height)); |
| if(centeredHorizontaly) { |
| bounds.x = centered.x; |
| } |
| if(centeredVerticaly) { |
| bounds.y = centered.y; |
| } |
| } |
| |
| return bounds; |
| } |
| |
| void finishLazyLoading() { |
| lazyLoader.loadAllNow(); |
| } |
| |
| } |