/*
 * 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.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.*;
import java.io.IOException;
import java.net.URL;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import org.netbeans.core.IDESettings;
import org.netbeans.core.windows.actions.ActionUtils;
import org.netbeans.core.windows.options.WinSysPrefs;
import org.netbeans.core.windows.persistence.ModeConfig;
import org.netbeans.core.windows.persistence.PersistenceManager;
import org.netbeans.core.windows.view.dnd.TopComponentDraggable;
import org.netbeans.core.windows.view.ui.MainWindow;
import org.netbeans.swing.tabcontrol.plaf.BusyTabsSupport;
import org.openide.nodes.Node;
import org.openide.util.*;
import org.openide.windows.*;

/**
 * This class extends WindowManager to provide all window system functionality.
 *
 * This class is final only for performance reasons. Can be freely
 * unfinaled if desired.
 *
 * @author Peter Zavadsky
 */
@org.openide.util.lookup.ServiceProvider(service=org.openide.windows.WindowManager.class)
public final class WindowManagerImpl extends WindowManager implements Workspace {
// XXX Implements Workspace for backward compatibility of old API only,
// there are no workspaces any more.
    
    // XXX PENDING additional, not-yet officialy supported properties.
    /** Name of property change fired when active mode changed. */
    public static final String PROP_ACTIVE_MODE = "activeMode"; // NOI18N
    /** Name of property change fired when maximized mode changed. */
    public static final String PROP_MAXIMIZED_MODE = "maximizedMode"; // NOI18N
    /** Name of property change fired when editor area state changed. */
    public static final String PROP_EDITOR_AREA_STATE = "editorAreaState"; // NOI18N    
    
    /** Init lock. */
    private static final Object LOCK_INIT = new Object();
    
    /** The only instance of the window manager implementation in the system */
    private static WindowManagerImpl defaultInstance;

    /** Flag to tell is assertions are on. Note it's package private and non-final for tests */
    static boolean assertsEnabled;

    /** Central unit of window system. */
    private final Central central = new Central();
    
    /** properties support */
    private final PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
    
    // PENDING
    /** Manages list of recently activated <code>TopCompoennt</code>s. */
    private final RecentViewList recentViewList = new RecentViewList(this);

    /** Only for hack 40237, to not call componentShowing twice */ 
    private TopComponent persistenceShowingTC;
    
    /** exclusive invocation of runnables */
    private Exclusive exclusive;

    /** flag that prevents calling Exclusive.run on each main window repaint */
    private boolean exclusivesCompleted = false;
    /** possibly stacktrace of creator */
    private Throwable createdBy;
    
    private final Collection<WindowSystemListener> listeners = new ArrayList<WindowSystemListener>(10);
    
    /** Default constructor. Don't use directly, use getDefault()
     * instead.
     */
    public WindowManagerImpl() {
        synchronized(LOCK_INIT) {
            // a static object to synchronize on
            if(defaultInstance != null) {
                IllegalStateException ex = new IllegalStateException("Instance already exists"); // NOI18N
                if (defaultInstance.createdBy != null) {
                    ex.initCause(defaultInstance.createdBy);
                }
                throw ex;
            }
            boolean on = false;
            assert on = true;
            if (on) {
                createdBy = new Exception("createdBy");
            }
            defaultInstance = this;
        }
        busyIconWarmUp();
    }
    
    /** Singleton accessor, returns instance of window manager implementation */
    public static WindowManagerImpl getInstance() {
        if (defaultInstance != null) {
            // Save a bunch of time accessing global lookup, acc. to profiler.
            return defaultInstance;
        }
        return (WindowManagerImpl)Lookup.getDefault().lookup(WindowManager.class);
    }
    
    @Override
    public void topComponentRequestAttention(TopComponent tc) {
        if( tc.isOpened() ) {
            ModeImpl mode = (ModeImpl) findMode(tc);

            central.topComponentRequestAttention(mode, tc);
        }
    }

    @Override
    public void topComponentCancelRequestAttention(TopComponent tc) {
        if( tc.isOpened() ) {
            ModeImpl mode = (ModeImpl) findMode(tc);

            central.topComponentCancelRequestAttention(mode, tc);
        }
    }

    @Override
    public void topComponentAttentionHighlight(TopComponent tc, boolean highlight) {
        if( tc.isOpened() ) {
            ModeImpl mode = (ModeImpl) findMode(tc);

            central.topComponentAttentionHighlight(mode, tc, highlight);
        }
    }

    /////////////////////////
    // API impelementation >>
    /////////////////////////
    
    // PENDING revise this method, it is dangerous to expose the GUI.
    /** Provides access to the MainWindow of the IDE.
     * Implements <code>WindowManager</code> abstract method.
     * @return the MainWindow */
    @Override
    public Frame getMainWindow() {
        warnIfNotInEDT();
        
        return central.getMainWindow();
    }
    
    /** Called after a current LookAndFeel change to update the IDE's UI
     * Implements <code>WindowManager</code> abstract method. */
    @Override
    public void updateUI() {
        warnIfNotInEDT();
        
        central.updateUI();
    }
    
    /** Creates a component manager for given top component.
     * Implements <code>WindowManager</code> abstract method.
     * @param c the component
     * @return the manager that handles opening, closing and selecting a component
     * @deprecated Don't use this. */
    @Override
    protected synchronized WindowManager.Component createTopComponentManager(TopComponent c) {
        warnIfNotInEDT();
        
        return null;
    }
    
    /** Creates new workspace with given name and display name.
     * Implements <code>WindowManager</code> abstract method.
     * @return fake implementation of only workspace
     * @deprecated Doesn't have a sense now. Workspaces aren't supported anymore. */
    @Override
    public Workspace createWorkspace(String name, String displayName) {
        warnIfNotInEDT();
        
        // get back fake workspace.
        return this;
    }

    /** Finds workspace given its name.
     * @return fake implementation of only workspace
     * @deprecated Doesn't have a sense now. Workspaces aren't supported anymore. */
    @Override
    public Workspace findWorkspace(String name) {
        warnIfNotInEDT();
        
        // PENDING what to return?
        return this;
    }
    
    /** List of all currenty available workspaces.
     * Implements <code>WindowManager</code> abstract method. 
     * @return array with only one (fake) workspace impl
     * @deprecated Doesn't have a sense now. Workspaces aren't supported anymore. */
    @Override
    public Workspace[] getWorkspaces() {
        warnIfNotInEDT();
        
        return new Workspace[] {this};
    }

    /** Sets new workspaces.
     * Implements <code>WindowManager</code> abstract method.
     * @param workspaces array of new workspaces
     * @deprecated Doesn't have a sense now. Workspaces aren't supported anymore. */
    @Override
    public void setWorkspaces(Workspace[] workspaces) {
        warnIfNotInEDT();
    }

    /** Gets current workspace. Can be changed by calling Workspace.activate ()
     * Implements <code>WindowManager</code> abstract method.
     * @return fake implementation of only workspace
     * @deprecated Doesn't have a sense now. Workspaces aren't supported anymore. */
    @Override
    public Workspace getCurrentWorkspace() {
        warnIfNotInEDT();
        
        // Gets back this as a fake workspace.
        return this;
    }

    /** Finds TopComponentGroup of given name. */
    @Override
    public TopComponentGroup findTopComponentGroup(String name) {
        assertEventDispatchThread();
        
        for(Iterator it = getTopComponentGroups().iterator(); it.hasNext(); ) {
            TopComponentGroupImpl group = (TopComponentGroupImpl)it.next();
            if(group.getName().equals(name)) {
                return group;
            }
        }
        
        return null;
    }
    
    /** Returns <code>TopComponent</code> for given unique ID.
     * @param tcID unique <code>TopComponent</code> ID
     * @return <code>TopComponent</code> instance corresponding to unique ID
     */
    @Override
    public TopComponent findTopComponent(String tcID) {
        warnIfNotInEDT();
        
        return getTopComponentForID(tcID);
    }
    
    /** Adds listener.
    * Implements <code>WindowManager</code> abstract method. */
    @Override
    public void addPropertyChangeListener(PropertyChangeListener l) {
        changeSupport.addPropertyChangeListener(l);
    }
    
    /** Removes listener.
     * Implements <code>WindowManager</code> abstract method. */
    @Override
    public void removePropertyChangeListener(PropertyChangeListener l) {
        changeSupport.removePropertyChangeListener(l);
    }

    ////////////////////////
    // API implementation <<
    ////////////////////////

//    /** Activates <code>TopComponent</code>, if it is opened. */
//    private boolean activateTopComponent(TopComponent tc) {
//        if(tc != null) {
//            // Find whether the component is in mode.
//            ModeImpl mode = (ModeImpl)findMode(tc);
//            if(mode != null) {
//                // Actually activates the TopComponent.
//                central.activateModeTopComponent(mode, tc);
//            } else {
//                // TopComponent not in mode yet.
//                return false;
//            }
//        }
//        
//        return true;
//    }
    
//    /** Selects <code>TopComponent</code>, if it is opened. */
//    protected void selectTopComponentImpl(TopComponent tc) {
//        if(tc != null) {
//            // Find whether the component is in mode.
//            ModeImpl mode = (ModeImpl)findMode(tc);
//            if(mode != null) {
//                // Actually select the TopComponent.
//                central.setModeSelectedTopComponent(mode, tc);
//            }
//        }
//    }
    

    // XXX For backward compatibility (Workspace class), this is the only (fake) workspace.
    // There are not supported workspaces any more.
    ///////////////////////////////////////
    // Start of  Workspace implementation>>
    ///////////////////////////////////////
    
    /** Gets the programmatic unique name of this workspace.
     * Implements <code>Workspace</code> interface method.
     * @return the programmatic name of only workspace impl
     * @deprecated Doesn't have a sense now. Workspaces aren't supported anymore. */
    @Override
    public String getName () {
        return "FakeWorkspace"; // NOI18N
    }
    
    /** Gets human-presentable name of the workspace.
     * Implements <code>Workspace</code> interface method.
     * @return the diplay name of the workspace
     * @deprecated Doesn't have a sense now. Workspaces aren't supported anymore. */
    @Override
    public String getDisplayName () {
        return NbBundle.getMessage(WindowManagerImpl.class, "LBL_FakeWorkspace");
    }

    /** Gets <code>Set</code> of all <code>Mode</code>'s.
     * Implements <code>Workspace</code> interface method. */
    @Override
    public Set<? extends ModeImpl> getModes () {
        return central.getModes();
    }
    
    /** Get bounds.
     * Implements <code>Workspace</code> interface method. */
    @Override
    public Rectangle getBounds () {
        if(getEditorAreaState() == Constants.EDITOR_AREA_JOINED) {
            return getMainWindowBoundsJoined();
        } else {
            return getMainWindowBoundsSeparated();
        }
    }

    /** Activates this workspace to be current one.
     * @deprecated Doesn't have a sense now. Workspaces aren't supported anymore. */
    @Override
    public void activate () {
    }
    
    /** Creates new <code>Mode</code>.
     * Implements <code>Workspace</code> interface method.
     * @param name a unique programmatic name of the mode 
     * @param displayName <em>ignored</em> doesn't have a sense now
     * @param icon <em>ignored</em> doesn't have a sense now
     * @return the new mode */
    @Override
    public Mode createMode(String name, String displayName, URL icon) {
        if(getEditorAreaState() == Constants.EDITOR_AREA_JOINED) {
            return new WrapMode (createMode(name, Constants.MODE_KIND_EDITOR, Constants.MODE_STATE_JOINED, false, null));
        } else {
            // #36945 In 'separate' ui mode create new mode.
            return createMode(name, Constants.MODE_KIND_VIEW, Constants.MODE_STATE_SEPARATED, false,
                new SplitConstraint[] { new SplitConstraint(Constants.HORIZONTAL, 1, 0.2)});
        }
    }

    /**
     * User made the given mode floating.
     * @param mode 
     * @since 2.30
     */
    public void userUndockedMode( ModeImpl mode ) {
        if( mode.getState() != Constants.MODE_STATE_JOINED ) {
            throw new IllegalStateException("Mode is already in floating state: " + mode);
        }

        central.userUndockedMode(mode);
    }

    /**
     * User docked the given mode back to the main window.
     * @param mode 
     * @since 2.30
     */
    public void userDockedMode( ModeImpl mode ) {
        if( mode.getState() != Constants.MODE_STATE_SEPARATED ) {
            throw new IllegalStateException("Mode is not in floating state: " + mode);
        }

        central.userDockedMode(mode);
    }

    /**
     * User minimized the whole mode.
     * @param mode 
     * @since 2.30
     */
    public void userMinimizedMode( ModeImpl mode ) {
        assertEventDispatchThread();
        
        getCentral().userMinimizedMode( mode );
    }

    /**
     * User restored the whole mode from minimized state.
     * @param slidingMode Sliding mode to be searched for minimized TopComponents
     * @param modeToRestore Mode to restored from minimized state.
     * @since 2.35
     */
    public void userRestoredMode( ModeImpl slidingMode, ModeImpl modeToRestore ) {
        assertEventDispatchThread();
        
        getCentral().userRestoredMode( slidingMode, modeToRestore );
    }

    /**
     * User closed the whole mode.
     * @param mode 
     * @since 2.30
     */
    public void userClosedMode( ModeImpl mode ) {
        assertEventDispatchThread();

        getCentral().userClosedMode( mode );
    }

    /**
     * @return the exclusive
     */
    private Exclusive getExclusive() {
        if (exclusive == null) {
            exclusive = new Exclusive();
        }
        return exclusive;
    }

    private void toggleUseNativeFileChooser() {
        if( null == System.getProperty("nb.native.filechooser") ) { //NOI18N
            boolean useNativeFileChooser = WinSysPrefs.HANDLER.getBoolean(WinSysPrefs.MAXIMIZE_NATIVE_LAF, false);
            System.setProperty("nb.native.filechooser", useNativeFileChooser ? "true" : "false"); //NOI18N
        }
    }

    @Override
    public Mode createModeFromXml(String xml) {
        try {
            ModeConfig modeConfig = PersistenceManager.getDefault().createModeFromXml(xml);
            ModeImpl mode = createMode(modeConfig);
            addMode(mode, modeConfig);
            return mode;
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
            return null;
        }
    }
    
    public ModeImpl createMode(ModeConfig config) {
        WindowManagerImpl wmi = WindowManagerImpl.getInstance();

        ModeImpl res = wmi.createMode(config.name, config.kind, config.state, false, config.constraints);
        Rectangle absBounds = config.bounds == null ? new Rectangle() : config.bounds;
        Rectangle relBounds = config.relativeBounds == null ? new Rectangle() : config.relativeBounds;
        Rectangle bounds = PersistenceHandler.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);
        res.setBounds(bounds);
        res.setFrameState(config.frameState);
        res.setMinimized(config.minimized);
        return res;
    }
    
    @Override
    public boolean removeMode(Mode mode) {
        String modeName = mode.getName();
        removeMode((ModeImpl)mode);
        return findMode(modeName) == null;
    }
    
    @Override
    public boolean updateModeConstraintsFromXml(String xml) {
        try {
            ModeConfig modeConfig = PersistenceManager.getDefault().createModeFromXml(xml);
            ModeImpl mode = findModeImpl(modeConfig.name);
            mode.setConstraints(modeConfig.constraints);
            return true;
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
            return false;
        }
    }

    private static class WrapMode implements Mode {
        private Mode wrap;
        
        public WrapMode (Mode wrap) {
            this.wrap = wrap;
        }
        
        @Override
        public void addPropertyChangeListener (PropertyChangeListener list) {
            wrap.addPropertyChangeListener (list);
        }
        
        @Override
        public boolean canDock (TopComponent tc) {
            return wrap.canDock (tc);
        }
        
        @Override
        public boolean dockInto (TopComponent c) {
            if (c.getClientProperty (Constants.TOPCOMPONENT_ALLOW_DOCK_ANYWHERE) == null) {
                c.putClientProperty (Constants.TOPCOMPONENT_ALLOW_DOCK_ANYWHERE, Boolean.TRUE);
            }
            return wrap.dockInto (c);
        }
        
        @Override
        public Rectangle getBounds () {
            return wrap.getBounds ();
        }
        
        @Override
        public String getDisplayName () {
            return wrap.getDisplayName ();
        }
        
        @Override
        public Image getIcon () {
            return wrap.getIcon ();
        }
        
        @Override
        public String getName () {
            return wrap.getName ();
        }
        
        @Override
        public TopComponent getSelectedTopComponent () {
            return wrap.getSelectedTopComponent ();
        }
        
        @Override
        public TopComponent[] getTopComponents () {
            return wrap.getTopComponents ();
        }
        
        @Override
        public Workspace getWorkspace () {
            return wrap.getWorkspace ();
        }
        
        @Override
        public void removePropertyChangeListener (PropertyChangeListener list) {
            wrap.removePropertyChangeListener (list);
        }
        
        @Override
        public void setBounds (Rectangle s) {
            wrap.setBounds (s);
        }
    } // end of WrapMode

    /** Finds mode by specified name.
     * Implements <code>Workspace</code> interface method.
     * @param name the name of the mode to search for
     * @return the mode with that name, or <code>null</code> */
    @Override
    public Mode findMode(String name) {
        return findModeImpl(name);
    }
    
    /** Finds mode the component is in.
     * Implements <code>Workspace</code> interface method.
     * @param c component to find mode for
     * @return the mode or <code>null</code> if the component is not in any mode */
    @Override
    public Mode findMode(TopComponent tc) {
        if(tc == null) {
            // Log something?
            return null;
        }

        //#235242
        TopComponent multiviewParent = ( TopComponent ) SwingUtilities.getAncestorOfClass( TopComponent.class, tc);
        if( null != multiviewParent )
            tc = multiviewParent;
        
        for(Iterator it = getModes().iterator(); it.hasNext(); ) {
            ModeImpl mode = (ModeImpl)it.next();
            
            if(mode.containsTopComponent(tc)) {
                return mode;
            }
        }

        return null;
    }
    
    /** Clears this workspace and removes this workspace from window manager.
     * Implements <code>Workspace</code> interface method.
     * @deprecated Doesn't have a sense now. Workspaces aren't supported anymore. */
    @Override
    public void remove () {
    }
    ////////////////////////////////////
    // End of Workspace implementation<<
    ////////////////////////////////////

    //////////////////////////////
    // TopComponentGroup>>
    public void addTopComponentGroup(TopComponentGroupImpl tcGroup) {
        central.addTopComponentGroup(tcGroup);
    }
    
    public void removeTopComponentGroup(TopComponentGroupImpl tcGroup) {
        central.removeTopComponentGroup(tcGroup);
    }
    
    public Set<TopComponentGroupImpl> getTopComponentGroups() {
        return central.getTopComponentGroups();
    }
    // TopComponentGroup<<
    //////////////////////////////

    
    /// Copy from older WorkspaceImpl>>

    ////////////////////////////////////////////////////////
    // PENDING some of the next methods could make inner API
    /** Creates new mode.
     * @param name a unique programmatic name of the mode 
     * @param permanent true if mode has to remain in model even it is emptied */
    public ModeImpl createMode(String name, int kind, int state, boolean permanent, SplitConstraint[] constraints) {
        // It gets existing mode with the same name.
        ModeImpl mode = (ModeImpl)findMode(name);
        if(mode != null) {
            return mode;
        }
        
        // XXX PENDING When no constraints are specified, default (editor or view) mode is returned.
        if(constraints == null && kind != Constants.MODE_KIND_SLIDING) {
            if(kind == Constants.MODE_KIND_EDITOR) {
                return getDefaultEditorMode();
            } else {
                return getDefaultViewMode();
            }
        }

        mode = createModeImpl(name, kind, state, permanent);
        addMode(mode, constraints);
        return mode;
    }
    
    public ModeImpl createSlidingMode(String name, boolean permanent, String side, Map<String,Integer> slideInSizes) {
        // It gets existing mode with the same name.
        ModeImpl mode = (ModeImpl)findMode(name);
        if(mode != null) {
            return mode;
        }
        
        mode = createModeImpl(name, Constants.MODE_KIND_SLIDING, permanent);
        central.addSlidingMode(mode, null, side, slideInSizes);
        return mode;
    }
    
    
    /*private*/ ModeImpl createModeImpl(String name, int kind, boolean permanent) {
        int state = getEditorAreaState() == Constants.EDITOR_AREA_JOINED
                                                ? Constants.MODE_STATE_JOINED
                                                : Constants.MODE_STATE_SEPARATED;
        return createModeImpl(name, kind, state, permanent);
    }
    
    /** */
    /*private*/ ModeImpl createModeImpl(String name, int kind, int state, boolean permanent) {
        if(name == null) {
            name = ModeImpl.getUnusedModeName();
        }
        ModeImpl toReturn =  ModeImpl.createModeImpl(name, state, kind, permanent);
        return toReturn;
    }

    // XXX
    /** Gets default mode. */
    /*private*/ ModeImpl getDefaultEditorMode() {
        ModeImpl mode = findModeImpl("editor"); // NOI18N
        if(mode == null) {
            Logger.getLogger(WindowManagerImpl.class.getName()).log(Level.FINE, null,
                              new java.lang.IllegalStateException("Creating default editor mode. It shouldn\'t happen this way")); // NOI18N
            // PENDING should be defined in winsys layer?
            ModeImpl newMode = createModeImpl("editor", Constants.MODE_KIND_EDITOR, true); // NOI18N
            addMode(newMode, new SplitConstraint[0]);
            return newMode;
        } else {
            return mode;
        }
    }
    
    /** Gets default mode for opening new component. */
    /*private*/ ModeImpl getDefaultEditorModeForOpen() {
        ModeImpl mode = central.getLastActiveEditorMode();
        if (mode == null) {
            return getDefaultEditorMode();
        } else {
            return mode;
        }
    }
    
    // XXX
    /** Gets default view mode. */
    ModeImpl getDefaultViewMode() {
        ModeImpl mode = findModeImpl("explorer"); // NOI18N
        if(mode == null) {
            Logger.getLogger(WindowManagerImpl.class.getName()).log(Level.INFO, null,
                              new java.lang.IllegalStateException("Creating default view mode. It shouldn\'t happen this way")); // NOI18N
            // PENDING should be defined in winsys layer?
            ModeImpl newMode = createModeImpl("explorer", Constants.MODE_KIND_VIEW, true); // NOI18N
            addMode(newMode, new SplitConstraint[] {
                new SplitConstraint(Constants.VERTICAL, 0, 0.7D),
                new SplitConstraint(Constants.HORIZONTAL, 0, 0.25D)
            });
            return newMode;
        } else {
            return mode;
        }
    }
    
    /** Gets default sliding view mode. */
    ModeImpl getDefaultSlidingMode() {
        ModeImpl mode = findModeImpl("sliding"); // NOI18N
        if(mode == null) {
            Logger.getLogger(WindowManagerImpl.class.getName()).log(Level.INFO, null,
                              new java.lang.IllegalStateException("Creating default sliding mode. It shouldn\'t happen this way")); // NOI18N
            // PENDING should be defined in winsys layer?
            ModeImpl newMode = createModeImpl("sliding", Constants.MODE_KIND_SLIDING, true); // NOI18N
            addMode(newMode, new SplitConstraint[] {
                new SplitConstraint(Constants.VERTICAL, 0, 0.7D),
                new SplitConstraint(Constants.HORIZONTAL, 0, 0.25D)
            });
            return newMode;
        } else {
            return mode;
        }
    }
    
    private ModeImpl findModeImpl(String name) {
        if(name == null) {
            // PENDING log something?
            return null;
        }
        
        for(Iterator it = getModes().iterator(); it.hasNext(); ) {
            ModeImpl mode = (ModeImpl)it.next();
            if (name.equals(mode.getName()) || mode.getOtherNames().contains( name ) ) {
                return mode;
            }
        }
        
        return null;
    }
    
    // XXX PENDING see WindowManager
    public TopComponent getSelectedTopComponent(Mode mode) {
        return central.getModeSelectedTopComponent((ModeImpl)mode);
    }
    
    public Rectangle getMainWindowBoundsJoined() {
        return central.getMainWindowBoundsJoined();
    }
    
    public void setMainWindowBoundsJoined(Rectangle bounds) {
        central.setMainWindowBoundsJoined(bounds);
    }
    
    public Rectangle getMainWindowBoundsSeparated() {
        return central.getMainWindowBoundsSeparated();
    }
    
    public void setMainWindowBoundsSeparated(Rectangle bounds) {
        central.setMainWindowBoundsSeparated(bounds);
    }
    
    public int getMainWindowFrameStateJoined() {
        return central.getMainWindowFrameStateJoined();
    }
    
    public void setMainWindowFrameStateJoined(int frameState) {
        central.setMainWindowFrameStateJoined(frameState);
    }
    
    public int getMainWindowFrameStateSeparated() {
        return central.getMainWindowFrameStateSeparated();
    }
    
    public void setMainWindowFrameStateSeparated(int frameState) {
        central.setMainWindowFrameStateSeparated(frameState);
    }
    
    
    /** Gets active mode.
     * @return active mode */
    public ModeImpl getActiveMode () {
        return central.getActiveMode();
    }
    
    /** Sets active mode.
     * @param current active mode */
    public void setActiveMode(ModeImpl activeMode) {
        central.setActiveMode(activeMode);
    }
    
    public void setEditorAreaBounds(Rectangle editorAreaBounds) {
        central.setEditorAreaBounds(editorAreaBounds);
    }
    
    public Rectangle getEditorAreaBounds() {
        return central.getEditorAreaBounds();
    }

    /** Sets editor area constraints. */
    public void setEditorAreaConstraints(SplitConstraint[] editorAreaConstraints) {
        central.setEditorAreaConstraints(editorAreaConstraints);
    }
    
    public java.awt.Component getEditorAreaComponent() {
        return central.getEditorAreaComponent();
    }
    
    /** Gets editor area constraints. */
    public SplitConstraint[] getEditorAreaConstraints() {
        return central.getEditorAreaConstraints();
    }
    
    /** Sets editor area state. */
    public void setEditorAreaState(int editorAreaState) {
        setEditorAreaStateImpl(editorAreaState);
    }
    
    // XXX
    void setEditorAreaStateImpl(int editorAreaState) {
        central.setEditorAreaState(editorAreaState);
    }
    
    public int getEditorAreaState() {
        return central.getEditorAreaState();
    }
    
    public void setEditorAreaFrameState(int editorAreaFrameState) {
        central.setEditorAreaFrameState(editorAreaFrameState);
    }
    
    public int getEditorAreaFrameState() {
        return central.getEditorAreaFrameState();
    }
    
    /** 
     * Sets new maximized mode or cancels the current one. 
     * @param newMaximizedMode Mode to set as the maximized one or null to cancel the current one.
     */
    public void switchMaximizedMode(ModeImpl newMaximizedMode) {
        central.switchMaximizedMode(newMaximizedMode);
    }
    
    /** Sets editor mode that is currenlty maximized (used when the window system loads) */
    public void setEditorMaximizedMode(ModeImpl editorMaximizedMode) {
        central.setEditorMaximizedMode(editorMaximizedMode);
    }
    
    /** Sets view mode that is currenlty maximized (used when the window system loads) */
    public void setViewMaximizedMode(ModeImpl viewMaximizedMode) {
        central.setViewMaximizedMode(viewMaximizedMode);
    }
    
    /** Gets mode that is currently maximized. */
    public ModeImpl getCurrentMaximizedMode() {
        return central.getCurrentMaximizedMode();
    }
    
    /** Gets editor maximized mode. */
    public ModeImpl getEditorMaximizedMode() {
        return central.getEditorMaximizedMode();
    }
    
    /** Gets view maximized mode. */
    public ModeImpl getViewMaximizedMode() {
        return central.getViewMaximizedMode();
    }
    
    /** Sets constraints, delegates from ModeImpl. */
    public void setModeConstraints(ModeImpl mode, SplitConstraint[] modeConstraints) {
        central.setModeConstraints(mode, modeConstraints);
    }
    
    /** Gets constraints, delegates from ModeImpl. */
    public SplitConstraint[] getModeConstraints(ModeImpl mode) {
        return central.getModeConstraints(mode);
    }

    /** Adds mode. */
    private void addMode(ModeImpl mode, SplitConstraint[] modeConstraints) {
        if (mode.getKind() == Constants.MODE_KIND_SLIDING) {
            // TODO.. where to get the side..
            central.addSlidingMode(mode, null, Constants.LEFT, null);
        } else {
            central.addMode(mode, modeConstraints);
        }
    }
    
    private void addMode(ModeImpl mode, ModeConfig modeConfig) {
        if (mode.getKind() == Constants.MODE_KIND_SLIDING) {
            central.addSlidingMode(mode, null, modeConfig.side, modeConfig.slideInSizes);
        } else {
            central.addMode(mode, modeConfig.constraints);
        }
    }
    
    /** Removes mode. */
    public void removeMode(ModeImpl mode) {
        if (mode.getKind() == Constants.MODE_KIND_SLIDING) {
            
        } else {
            central.removeMode(mode);
        }
    }

    /** Sets toolbar configuration name. */
    public void setToolbarConfigName(String toolbarConfigName) {
        central.setToolbarConfigName(toolbarConfigName);
    }

    /** Gets toolbar configuration name.
     * @return toolbar configuration name */
    public String getToolbarConfigName () {
        return central.getToolbarConfigName();
    }

    // Copy from older WorkspaceImpl<< 
    
   

    /** Sets visible or invisible window system GUI. */
    public void setVisible(boolean visible) {
        if( !visible ) {
            FloatingWindowTransparencyManager.getDefault().stop();
        }
        central.setVisible(visible);

        // handle timer that assures runnign of exclusives when somehow
        // mainWindow.paint is not called during startup
        if (visible) {
            if (!exclusivesCompleted) {
                getExclusive().restart();
            } else {
                FloatingWindowTransparencyManager.getDefault().start();
            }
            toggleUseNativeFileChooser();
        } else {
            getExclusive().stop();
            exclusivesCompleted = false;
        }
    }
    
    /** Creates a new mode on the side of the given mode 
     * @since 2.32
     */
    public ModeImpl attachModeToSide(ModeImpl referenceMode, String side, String modeName, int modeKind, boolean permanent) {
        return central.attachModeToSide(referenceMode, side, modeName, modeKind, permanent);
    }
    
    /** Indicates whether windows system shows GUI. */
    public boolean isVisible() {
        return central.isVisible();
    }
    
    // XXX
    public TopComponent getTopComponentForID(String tcID) {
        return PersistenceHandler.getDefault().getTopComponentForID(tcID,true);
    }
    
    public boolean isTopComponentAllowedToMoveAnywhere(TopComponent tc) {
        if(Boolean.TRUE.equals(tc.getClientProperty(Constants.TOPCOMPONENT_ALLOW_DOCK_ANYWHERE))) {
            return true;
        }
        
        return false;
    }
    
    // XXX
    public ModeImpl findModeForOpenedID(String tcID) {
        if(tcID == null) {
            return null;
        }
        
        for(ModeImpl mode: getModes()) {
            if(mode.getOpenedTopComponentsIDs().contains(tcID)) {
                return mode;
            }
        }
        
        return null;
    }
    
    // XXX
    public ModeImpl findModeForClosedID(String tcID) {
        if(tcID == null) {
            return null;
        }
        
        for(ModeImpl mode: getModes()) {
            if(mode.getClosedTopComponentsIDs().contains(tcID)) {
                return mode;
            }
        }
        
        return null;
    }
    
    /** Helper method to retrieve some form of display name of TopComponent.
     * First tries TopComponent's getHtmlDisplayName, if is it null then continues
     * with getDisplayName and getName in this order.
     *
     * @param tc TopComponent to retrieve display name from. May be null.
     * @return TopComponent's display name or null if no display name available
     * or null TopComponent is given
     */
    public String getTopComponentDisplayName(TopComponent tc) {
        if(tc == null) {
            return null;
        }
        String displayName = tc.getHtmlDisplayName();
        if (displayName == null) {
            displayName = tc.getDisplayName();
        }
        if (displayName == null) {
            displayName = tc.getName();
        }
        return displayName;
    }
    
    // PENDING for ModeImpl only.
    Central getCentral() {
        return central;
    }

    // XXX
    public boolean isDragInProgress() {
        return central.isDragInProgress();
    }
    
    /** Analyzes bounds of given top component and finds appropriate side
     * of desktop for sliding for given top component.
     *
     * @param tc top component to find side for sliding for
     * @return side where top component should live in sliding state
     * @see Constants.LEFT 
     */ 
    public String guessSlideSide(TopComponent tc) {
        return central.guessSlideSide(tc);
    }

    /**
     * {@inheritDoc}
     */
    public boolean isDocked (TopComponent comp) {
        return central.isDocked(comp);
    }

    /** Takes given top component out of the main window and puts it in
     * new separate floating window.
     *
     * @param tc TopComponent to make floating
     * @param mode mode where TopComponent currently lives (before undock)
     *
     * @throws IllegalStateException when given top component is already floating
     */
    public void userUndockedTopComponent(TopComponent tc, ModeImpl mode) {
        if (!isDocked(tc)) {
            throw new IllegalStateException("TopComponent is already in floating state: " + tc);
        }

        central.userUndockedTopComponent(tc, mode);
    }

    /** Puts given top component back into main window.
     *
     * @param tc TopComponent to put back into main window
     * @param mode mode where TopComponent currently lives (before dock)
     *
     * @throws IllegalStateException when given top component is already inside main window
     */
    public void userDockedTopComponent(TopComponent tc, ModeImpl mode) {
        if (isDocked(tc)) {
            throw new IllegalStateException("TopComponent is already inside main window: " + tc);
        }

        central.userDockedTopComponent(tc, mode);
    }
    /**
     * 
     * @param tc
     * @param minimized 
     * @since 2.32
     */
    @Override
    public void setTopComponentMinimized( TopComponent tc, boolean minimized ) {
        assertEventDispatchThread();
        central.setTopComponentMinimized( tc, minimized );
    }
    
    /**
     * 
     * @param tc
     * @return 
     * @since 2.32
     */
    @Override
    public boolean isTopComponentMinimized( TopComponent tc ) {
        assertEventDispatchThread();
        return central.isTopComponentMinimized( tc );
    }

    // PENDING>>
    public void setRecentViewList(String[] tcIDs) {
        recentViewList.setTopComponents(tcIDs);
    }
    
    public TopComponent[] getRecentViewList() {
        return recentViewList.getTopComponents();
    }

    public String[] getRecentViewIDList() {
        return recentViewList.getTopComponentIDs();
    }
    // PENDING<<
    
    void doFirePropertyChange(final String propName,
    final Object oldValue, final Object newValue) {
        // PENDING When #37529 finished, then uncomment the next row and move the
        // checks of AWT thread away.
        //  WindowManagerImpl.assertEventDispatchThread();
        if(SwingUtilities.isEventDispatchThread()) {
            changeSupport.firePropertyChange(propName, oldValue, newValue);
        } else {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    changeSupport.firePropertyChange(propName, oldValue, newValue);
                }
            });
        }
    }

    // PENDING used in persistence only, revise how to restrict its usage only there.
    /** Gets persistence observer. */
    public org.netbeans.core.windows.persistence.PersistenceObserver getPersistenceObserver() {
        return PersistenceHandler.getDefault();
    }

    
    /////////////////////////
    // Notifications>>
    public void notifyTopComponentOpened(TopComponent tc) {
        // Inform component instance.
        componentOpenNotify(tc);
        // then let others know that top component was opened...
        notifyRegistryTopComponentOpened(tc);
    }
    
    public void notifyTopComponentClosed(TopComponent tc) {
        // Inform component instance.
        componentCloseNotify(tc);
        // let others know that top component was closed...
        notifyRegistryTopComponentClosed(tc);
    }
    // Notifications<<
    /////////////////////////

    /////////////////////////////
    // Registry notifications
    static void notifyRegistryTopComponentActivated(final TopComponent tc) {
        ((RegistryImpl)getDefault().getRegistry()).topComponentActivated(tc);

        
        // #37457 It is needed to ensure the activation calls are in AWT thread.
        if(SwingUtilities.isEventDispatchThread()) {
            WindowManagerImpl.getInstance().activateComponent(tc);
        } else {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    WindowManagerImpl.getInstance().activateComponent(tc);
                }
            });
        }
    }
    
    private static void notifyRegistryTopComponentOpened(TopComponent tc) {
        ((RegistryImpl)getDefault().getRegistry()).topComponentOpened(tc);
    }
    
    private static void notifyRegistryTopComponentClosed(TopComponent tc) {
        ((RegistryImpl)getDefault().getRegistry()).topComponentClosed(tc);
    }
    
    private static void notifyRegistrySelectedNodesChanged(TopComponent tc, Node[] nodes) {
        ((RegistryImpl)getDefault().getRegistry()).selectedNodesChanged(tc, nodes);
    }
    // Registry notifications
    /////////////////////////////

    /** Overrides superclass method, to enhance access modifier. */
    @Override
    public void componentShowing(TopComponent tc) {
        if((tc != null) && (tc != persistenceShowingTC)) {
            super.componentShowing(tc);
        }
    }
    
    /** XXX - Hack for 40237, should be changed to fix real reason of 37188
     * timing of activate events */
    void specialPersistenceCompShow(TopComponent tc) {
        componentShowing(tc);
        persistenceShowingTC = tc;
    }
    
    /** Overrides superclass method, to enhance access modifier. */
    @Override
    public void componentHidden(TopComponent tc) {
        if(tc != null) {
            super.componentHidden(tc);
            if (tc == persistenceShowingTC) {
                persistenceShowingTC = null;
            }
        }
    }

    
    // Manipulating methods (overriding the superclass dummy ones) >>
    @Override
    protected void topComponentOpen (TopComponent tc) {
        topComponentOpenAtTabPosition(tc, -1);
    }

    @Override
    protected void topComponentOpenAtTabPosition (TopComponent tc, int position) {
        warnIfNotInEDT();
        
        if (tc == null) {
            throw new IllegalArgumentException ("Cannot open a null " +
                "TopComponent"); //NOI18N
        }
        
        ModeImpl mode = getMode(tc);
        
        if (mode == null) {
            mode = getDefaultEditorModeForOpen();
            Collection<? extends ModeSelector> selectors = Lookup.getDefault().lookupAll(ModeSelector.class);
            for (ModeSelector s : selectors) {
                Mode hintMode = s.selectModeForOpen(tc, mode);
                if (hintMode instanceof ModeImpl) {
                    mode = (ModeImpl)hintMode;
                    break;
                }
            }
            assert getModes().contains(mode) : "Mode " + mode.getName() + " is not in model."; //NOI18N
            if (tc.getClientProperty (Constants.TOPCOMPONENT_ALLOW_DOCK_ANYWHERE) == null) {
                tc.putClientProperty (Constants.TOPCOMPONENT_ALLOW_DOCK_ANYWHERE, Boolean.TRUE);
            }
        }
        boolean alreadyOpened = mode.getOpenedTopComponents().contains( tc );
        
        TopComponentTracker.getDefault().add( tc, mode );

        // XXX PENDING If necessary, unmaximize the state, but exclude sliding modes
        // Consider to put it in addOpenedTopComponent, to do it in one step.
        ModeImpl maximizedMode = getCurrentMaximizedMode();
        if(maximizedMode != null && mode != maximizedMode
           && mode.getKind() != Constants.MODE_KIND_SLIDING
           && (central.isViewMaximized() || mode.getKind() == Constants.MODE_KIND_EDITOR)) {
            switchMaximizedMode(null);
        }
        
        if (position == -1) {
            mode.addOpenedTopComponent(tc);
        } else {
            mode.addOpenedTopComponent(tc, position);
        }
        
        if( central.isEditorMaximized() 
                && !alreadyOpened 
                && mode.getState() != Constants.MODE_STATE_SEPARATED ) {
            //the editor is maximized so the newly opened TopComponent should slide out
            String tcID = findTopComponentID( tc );
            if( !isTopComponentDockedInMaximizedMode( tcID ) && mode.getKind() == Constants.MODE_KIND_VIEW ) {
                //slide the TopComponent to edgebar and slide it out
                central.slide( tc, mode, central.getSlideSideForMode( mode ) );

                topComponentRequestActive( tc );
                return;
            }
        }
        if( mode.isMinimized() && Switches.isTopComponentAutoSlideInMinimizedModeEnabled() ) {
            central.slide( tc, mode, central.getSlideSideForMode( mode ) );

            topComponentRequestActive( tc );
        }
    }
    
    @Override
    protected int topComponentGetTabPosition (TopComponent tc) {
        warnIfNotInEDT();
        
        ModeImpl mode = getModeForOpenedTopComponent(tc);
        if(mode != null) {
            return mode.getTopComponentTabPosition(tc);
        } else {
            return -1;
        }
    }
    
    @Override
    protected void topComponentClose(TopComponent tc) {
        warnIfNotInEDT();
        
        boolean opened = topComponentIsOpened(tc);
        boolean inCloseAll = tc.getClientProperty("inCloseAll") != null;
        tc.putClientProperty("inCloseAll", null);

        if(!opened) {
            return;
        }

        ModeImpl mode = getModeForOpenedTopComponent(tc);
        if(mode != null) {
            if( mode == central.getCurrentMaximizedMode() && central.isViewMaximized() ) {
                central.switchMaximizedMode( null );
                topComponentClose( tc );
            } else {
                TopComponent recentTc = null;
                if( mode.getKind() == Constants.MODE_KIND_EDITOR && !inCloseAll ) {
                    //an editor document is being closed so let's find the most recent editor to select
                    recentTc = central.getRecentTopComponent( mode, tc );
                }
                mode.close(tc);
                if( !tc.isOpened() && null != recentTc )
                    mode.setSelectedTopComponent(recentTc);
            }
        }
    }
    
    @Override
    protected void topComponentRequestActive(TopComponent tc) {
        warnIfNotInEDT();
        
        ModeImpl mode = getModeForOpenedTopComponent(tc);
        if(mode != null) {
            central.activateModeTopComponent(mode, tc);
        }
    }
    
    @Override
    protected void topComponentRequestVisible(TopComponent tc) {
        warnIfNotInEDT();
        
        ModeImpl mode = getModeForOpenedTopComponent(tc);
        if(mode != null) {
            central.setModeSelectedTopComponent(mode, tc);
            if( mode.getState() == Constants.MODE_STATE_SEPARATED ) {
                tc.toFront();
            }
        }
    }

    @Override
    protected void topComponentDisplayNameChanged(TopComponent tc, String displayName) {
        warnIfNotInEDT();
        
        ModeImpl mode = getModeForOpenedTopComponent(tc);
        if(mode != null) {
            central.topComponentDisplayNameChanged(mode, tc);
        }
    }
    
    @Override
    protected void topComponentHtmlDisplayNameChanged(TopComponent tc, String htmlDisplayName) {
        // do the same thing as for display name, we can because string param is ignored
        topComponentDisplayNameChanged(tc, null);
    }
    
    @Override
    protected void topComponentToolTipChanged(TopComponent tc, String toolTip) {
        warnIfNotInEDT();
        
        ModeImpl mode = getModeForOpenedTopComponent(tc);
        if(mode != null) {
            central.topComponentToolTipChanged(mode, tc);
        }
    }
    
    @Override
    protected void topComponentIconChanged(TopComponent tc, Image icon) {
        warnIfNotInEDT();
        
        ModeImpl mode = getModeForOpenedTopComponent(tc);
        if(mode != null) {
            central.topComponentIconChanged(mode, tc);
        }
    }

    @Override
    protected void topComponentActivatedNodesChanged(TopComponent tc, Node[] activatedNodes) {
        warnIfNotInEDT();
        
        notifyRegistrySelectedNodesChanged(tc, activatedNodes);
    }
    
    @Override
    protected boolean topComponentIsOpened(TopComponent tc) {
        warnIfNotInEDT();
        
        return getModeForOpenedTopComponent(tc) != null;
    }
    
    @Override
    protected Action[] topComponentDefaultActions(TopComponent tc) {
        warnIfNotInEDT();
        
        return ActionUtils.createDefaultPopupActions(tc);
    }
    
    @Override
    protected String topComponentID (TopComponent tc, String preferredID) {
        warnIfNotInEDT();
        
        if (preferredID == null) {
            Logger.getLogger(WindowManagerImpl.class.getName()).log(Level.WARNING, null,
                              new java.lang.IllegalStateException("Assertion failed. " +
                                                                  tc.getClass().getName() +
                                                                  ".preferredID method shouldn\'t be overriden to return null. " +
                                                                  "Please change your impl to return non-null string.")); // NOI18N
        }
        
        return PersistenceManager.getDefault().getGlobalTopComponentID(tc, preferredID);
    }

    @Override
    public void invokeWhenUIReady(Runnable run) {
        getExclusive().register(run);
    }
    
    @Override
    public boolean isEditorTopComponent( TopComponent tc ) {
        if( null == tc )
            return false;
        //check opened TopComponents first to avoid AWT assertion if possible
        for(ModeImpl mode: getModes()) {
            if( mode.getKind() != Constants.MODE_KIND_EDITOR )
                continue;
            if( mode.containsTopComponent( tc ) ) {
                return true;
            }
        }

        //unknown TopComponent
        return false;
    }
    
    @Override
    public boolean isOpenedEditorTopComponent( TopComponent tc ) {
        if( null == tc )
            return false;
        for(ModeImpl mode: getModes()) {
            if( mode.getKind() != Constants.MODE_KIND_EDITOR )
                continue;
            if( mode.getOpenedTopComponents().contains( tc ) ) {
                return true;
            }
        }

        //unknown TopComponent
        return false;
    }
    
    @Override
    public boolean isEditorMode( Mode mode ) {
        if( null == mode )
            return false;
        ModeImpl modeImpl = findModeImpl( mode.getName() );
        return null != modeImpl && modeImpl.getKind() == Constants.MODE_KIND_EDITOR;
    }
    
    public void newTabGroup( TopComponent tc ) {
        assertEventDispatchThread();
        central.newTabGroup( tc );
    }
    
    public void collapseTabGroup( ModeImpl mode ) {
        assertEventDispatchThread();
        central.collapseTabGroup( mode );
    }

    public final void mainWindowPainted () {
        if (!exclusivesCompleted && WindowManagerImpl.getInstance().isVisible()) {
            exclusivesCompleted = true;
            getExclusive().stop();
            getExclusive().register(new Runnable() {
                @Override
                public void run() {
                    FloatingWindowTransparencyManager.getDefault().start();
                }
            });

            SwingUtilities.invokeLater(getExclusive());
        }
    }

    /**
     * #220599
     */
    private void busyIconWarmUp() {
        invokeWhenUIReady( new Runnable() {

            @Override
            public void run() {
                RequestProcessor.getDefault().post( new Runnable() {

                    @Override
                    public void run() {
                        BusyTabsSupport.getDefault().getBusyIcon( false );
                    }
                });
            }
        });
    }

    /** Handles exclusive invocation of Runnables.
     */
    private static final class Exclusive implements Runnable, ActionListener {
        /** lists of runnables to run */
        private ArrayList<Runnable> arr;
        /**
         * timer to ensure exclusive runnables are really invoked in all
         * circumstances
         */
        private javax.swing.Timer paintedTimer;

        public Exclusive() {
            arr = new ArrayList<Runnable>();
            paintedTimer = new javax.swing.Timer(5000, this);
            paintedTimer.setRepeats(false);
        }
        
        final void stop() {
            paintedTimer.stop();
        }
        final void restart() {
            paintedTimer.restart();
        }

        /** Registers given runnable and ensures that it is run when UI 
         * of the system is ready.
         */
        public synchronized void register(Runnable r) {
            arr.add(r);
            SwingUtilities.invokeLater(this);
        }

        @Override
        public void run() {
            if (IDESettings.isGui()) {
                // running in GUI mode, but
                if (!WindowManagerImpl.getInstance().isVisible()) {
                    // window manager isn't yet visible => exit for now
                    return;
                }
            }
            
            synchronized (this) {
                if (arr.isEmpty()) {
                    return;
                }
                
                final Runnable toRun = arr.remove(0);
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        Logger perf = Logger.getLogger("org.netbeans.log.startup"); // NOI18N
                        try {
                            perf.log(Level.FINE, "start", "invokeWhenUIReady: " + toRun.getClass().getName()); // NOI18N
                            toRun.run();
                            perf.log(Level.FINE, "end", "invokeWhenUIReady: " + toRun.getClass().getName()); // NOI18N
                        } catch (RuntimeException ex) {
                            Logger.getLogger(WindowManagerImpl.class.getName()).log(
                                    Level.WARNING, null, ex);
                        }
                        SwingUtilities.invokeLater(Exclusive.this);
                    }
                });
            }
        }

        /** ActionListener implementation - reacts to Timer which ensures
         * invocation of registered exclusive runnables
         */
        @Override
        public void actionPerformed(ActionEvent e) {
            Logger.getLogger(WindowManagerImpl.class.getName()).log(Level.FINE, 
                    "Painted timer action invoked, which probably means that MainWindow.paint was not called!"); //NOI18N
            WindowManagerImpl.getInstance().mainWindowPainted();
        }

    } // end of Exclusive class

    public void resetModel() {
        central.resetModel();
        RegistryImpl rimpl = (RegistryImpl)componentRegistry();
        rimpl.clear();
    }
    
    // Manipulating methods (overriding the superclass dummy ones) <<

    /** Helper only. */
    private ModeImpl getMode(TopComponent tc) {
        return (ModeImpl)findMode(tc);
    }

    // #37561
    /** Helper only */
    private ModeImpl getModeForOpenedTopComponent(TopComponent tc) {
        if(tc == null) {
            // Log something?
            return null;
        }
        
        for(ModeImpl mode: getModes()) {
            if(mode.getOpenedTopComponents().contains(tc)) {
                return mode;
            }
        }
        
        return null;
    }
    
    /**
     * @return The mode where the given TopComponent had been before it was moved to sliding or separate mode.
     */
    public ModeImpl getPreviousModeForTopComponent(String tcID, ModeImpl slidingMode) {
        return getCentral().getModeTopComponentPreviousMode(tcID, slidingMode);
    }
    
    /**
     * @return The position (tab index) of the given TopComponent before it was moved to sliding or separate mode.
     */
    public int getPreviousIndexForTopComponent(String tcID, ModeImpl slidingMode) {
        return getCentral().getModeTopComponentPreviousIndex(tcID, slidingMode);
    
    }
    
    /**
     * Remember the mode and position where the given TopComponent was before moving into sliding or separate mode.
     * 
     * @param tcID TopComponent's id
     * @param currentSlidingMode The mode where the TopComponent is at the moment.
     * @param prevMode The mode where the TopComponent had been before it was moved to the sliding mode.
     * @param prevIndex Tab index of the TopComponent before it was moved to the new mode.
     */
    public void setPreviousModeForTopComponent(String tcID, ModeImpl slidingMode, ModeImpl prevMode, int prevIndex) {
        getCentral().setModeTopComponentPreviousMode(tcID, slidingMode, prevMode, prevIndex);
    }
    
    /**
     * Set the state of the TopComponent when the editor is maximized.
     * 
     * @param tcID TopComponent id
     * @param docked True if the TopComponent should stay docked in maximized editor mode,
     * false if it should slide out when the editor is maximized.
     */
    public void setTopComponentDockedInMaximizedMode( String tcID, boolean docked ) {
        getCentral().setTopComponentDockedInMaximizedMode( tcID, docked );
    }
    
    /**
     * Get the state of the TopComponent when the editor is maximized.
     * 
     * @param tcID TopComponent id.
     * @return True if the TopComponent should stay docked in maximized editor mode,
     * false if it should slide out when the editor is maximized.
     */
    public boolean isTopComponentDockedInMaximizedMode( String tcID ) {
        return getCentral().isTopComponentDockedInMaximizedMode( tcID );
    }
    
    /**
     * Set the state of the TopComponent when no mode is maximized.
     * 
     * @param tcID TopComponent id
     * @param slided True if the TopComponent is slided in the default mode,
     * false if it is docked.
     */
    public void setTopComponentSlidedInDefaultMode( String tcID, boolean slided ) {
        getCentral().setTopComponentSlidedInDefaultMode( tcID, slided );
    }
    
    /**
     * Get the state of the TopComponent when no mode is maximized.
     * 
     * @param tcID TopComponent id.
     * @return True if the TopComponent is slided in the default mode,
     * false if it is docked.
     */
    public boolean isTopComponentSlidedInDefaultMode( String tcID ) {
        return getCentral().isTopComponentSlidedInDefaultMode( tcID );
    }
    
    /**
     * Get the state of the TopComponent when it is slided-in.
     * 
     * @param tcID TopComponent id. 
     * @return true if the TopComponent is maximized when slided-in.
     */
    public boolean isTopComponentMaximizedWhenSlidedIn( String tcID ) {
        return getCentral().isTopComponentMaximizedWhenSlidedIn( tcID );
    }
    
    /**
     * Set the state of the TopComponent when it is slided-in.
     * 
     * @param tcID TopComponent id. 
     * @param maximized true if the TopComponent is maximized when slided-in.
     */
    public void setTopComponentMaximizedWhenSlidedIn( String tcID, boolean maximized ) {
        getCentral().setTopComponentMaximizedWhenSlidedIn( tcID, maximized );
    }
    
    public void userToggledTopComponentSlideInMaximize( String tcID ) {
        getCentral().userToggledTopComponentSlideInMaximize( tcID );
    }

    /** Finds out if given Window is used as separate floating window or not.
     *
     * @return true if Window is separate floating window, false if window
     * is used for other purposes such as independent dialog/window, main window etc. 
     */
    public static boolean isSeparateWindow (Window w) {
        // work only in Swing environment
        if (!(w instanceof RootPaneContainer)) {
            return false;
        }
        // #85089 - getRootPane may return null in some edge situations
        JRootPane rp = ((RootPaneContainer) w).getRootPane();
        if (rp == null) {
            return false;
        }
        return rp.getClientProperty(Constants.SEPARATE_WINDOW_PROPERTY) != null;
    }

    private static final String ASSERTION_ERROR_MESSAGE = "Window System API is required to be called from AWT thread only, see " // NOI18N
        + "http://core.netbeans.org/proposals/threading/"; // NOI18N
    
    static void assertEventDispatchThread() {
        assert SwingUtilities.isEventDispatchThread() : ASSERTION_ERROR_MESSAGE;
    }

    static {
        assertsEnabled = false;
        assert assertsEnabled = true;  // Intentional side-effect!!!
    }

    /** Weaker form of assertion to control if client's code is calling
     * winsys from ED thread. Level of logged exception is lower if
     * assertions are disabled (for releases etc).
     */
    static void warnIfNotInEDT () {
        Level level = assertsEnabled ? Level.WARNING : Level.FINE;
        if(!SwingUtilities.isEventDispatchThread()) {
            // tries to catch known JDK problem, SwingUtilities.isEventDispatchThread()
            // returns false even if it *is* in ED thread.
            // if we find "java.awt.EventDispatchThread" stack line, it's probable
            // that we hit this JDK problem (see links below)
            boolean isJDKProblem = false;
            StackTraceElement[] elems = Thread.currentThread().getStackTrace();
            for (StackTraceElement elem : elems) {
                if ("java.awt.EventDispatchThread".equals(elem.getClassName())) {
                    isJDKProblem = true;
                    break;
                }
            }

            if (!isJDKProblem) {
                // problem somewhere in NetBeans modules' code
                Logger.getLogger(WindowManagerImpl.class.getName()).log(level, null,
                        new java.lang.IllegalStateException(
                        "Problem in some module which uses Window System: "
                        + ASSERTION_ERROR_MESSAGE));
            } else {
                // probably known problem in JDK
                Logger.getLogger(WindowManagerImpl.class.getName()).log(level, null,
                        new java.lang.IllegalStateException(
                        "Known problem in JDK occurred. If you are interested, vote and report at:\n" +
                        "http://bugs.sun.com/view_bug.do?bug_id=6424157, http://bugs.sun.com/view_bug.do?bug_id=6553239 \n" +
                        "Also see related discussion at http://www.netbeans.org/issues/show_bug.cgi?id=90590"));
            }
        }
    }

    /**
     * @return An array of TopComponents that are opened in editor modes (i.e. editor windows).
     */
    public TopComponent[] getEditorTopComponents() {
        TopComponentTracker tcTracker = TopComponentTracker.getDefault();
        ArrayList<TopComponent> editors = new ArrayList<TopComponent>();
        for( TopComponent tc : getRegistry().getOpened() ) {
            if( tcTracker.isViewTopComponent( tc ) )
                continue;
            editors.add( tc );
        }
        return editors.toArray( new TopComponent[editors.size()] );
    }

    /**
     * @return TopComponent that is selected in an arbitrary editor-type mode
     * or null if editor mode(s) is empty.
     */
    public TopComponent getArbitrarySelectedEditorTopComponent() {
        TopComponentTracker tcTracker = TopComponentTracker.getDefault();
        Set modes = getModes();
        for( Iterator i=modes.iterator(); i.hasNext(); ) {
            Mode mode = (Mode)i.next();
            ModeImpl modeImpl = findModeImpl( mode.getName() );
            if( modeImpl.getKind() == Constants.MODE_KIND_EDITOR ) {
                TopComponent tc = mode.getSelectedTopComponent();
                if( null != tc && tcTracker.isEditorTopComponent( tc ) )
                    return tc;
            }
        }
        return null;
    }

    /**
     * Send componentHidden() event to all selected TopComponents in editor modes.
     */
    public void deselectEditorTopComponents() {
        for(ModeImpl modeImpl: getModes()) {
            if( modeImpl.getKind() == Constants.MODE_KIND_EDITOR ) {
                //not a pretty hack - add an empty TopComponent into the mode
                //and make it the selected one so that componentHidden() gets called
                //on the previously selected TopComponent
                TopComponent dummy = new DummyTopComponent();
                modeImpl.addOpenedTopComponent( dummy );
                modeImpl.setSelectedTopComponent( dummy );
            }
        }
    }

    /**
     * Calls close() on all TopComponents that are opened in noneditor-type modes.
     *
     */
    public void closeNonEditorViews() {
        TopComponentTracker tcTracker = TopComponentTracker.getDefault();
        for(ModeImpl modeImpl: getModes()) {
            if( null == modeImpl )
                continue;
            java.util.List tcs = modeImpl.getOpenedTopComponents();
            for( Iterator j=tcs.iterator(); j.hasNext(); ) {
                TopComponent tc = (TopComponent)j.next();
                if( tcTracker.isViewTopComponent( tc ) )
                    tc.close();
            }
        }
    }

    @Override
    public TopComponent[] getOpenedTopComponents(Mode mode) {
        if( mode instanceof ModeImpl ) {
            java.util.List<TopComponent> openedTcs = ((ModeImpl)mode).getOpenedTopComponents();
            return openedTcs.toArray(new TopComponent[openedTcs.size()]);
        }
        return super.getOpenedTopComponents(mode);
    }

    @Override
    public void addWindowSystemListener( WindowSystemListener listener ) {
        synchronized( listeners ) {
            listeners.add( listener );
        }
    }

    @Override
    public void removeWindowSystemListener( WindowSystemListener listener ) {
        synchronized( listeners ) {
            listeners.remove( listener );
        }
    }

    private String currentRole = null;
    
    @Override
    public String getRole() {
        return currentRole;
    }

    @Override
    public void setRole( String roleName ) {
        setRole( roleName, false );
    }
    
    public void setRole( String roleName, boolean keepDocumentWindows ) {
        if( null != roleName && roleName.isEmpty() )
            throw new IllegalArgumentException( "Role name cannot be empty."); //NOI18N
        
        if( !PersistenceHandler.getDefault().isLoaded() ) {
            currentRole = roleName;
            PersistenceManager.getDefault().setRole( currentRole );
        } else {
            if( currentRole == null ? roleName == null : currentRole.equals( roleName ) ) {
                //nothing to do
                return;
            }
            switchRole( roleName, keepDocumentWindows );
        }
    }
    
    /*private*/ boolean switchRole( String newRole, boolean keepDocumentWindows ) {
        final WindowSystemImpl ws = Lookup.getDefault().lookup( WindowSystemImpl.class );
        assert null != ws;
        final PersistenceManager pm = PersistenceManager.getDefault();
        
        PersistenceHandler.getDefault().finishLazyLoading();

        //cancel full-screen mode
        MainWindow.getInstance().setFullScreenMode(false);
        
        //get a list of editor windows that should stay open even after the reset
        final TopComponent[] editors = getEditorTopComponents();
        if( !keepDocumentWindows ) {
            for( TopComponent tc : editors ) {
                if( !tc.canClose() )
                    return false;
            }
        }
        
        final TopComponent prevActiveEditor = getArbitrarySelectedEditorTopComponent();

        Set<TopComponent> openedBefore = new HashSet<TopComponent>( getRegistry().getOpened() );

        boolean hideAndShowWhileSwitching = Switches.isShowAndHideMainWindowWhileSwitchingRole();
        if( hideAndShowWhileSwitching ) {
            ws.hide();
        } else {
            getMainWindow().setCursor( Cursor.getPredefinedCursor( Cursor.WAIT_CURSOR ) );
        }
        
        //save current layout under current role
        ws.save();
        
        deselectEditorTopComponents();

        //reset
        resetModel();
        pm.reset(); //keep mappings to TopComponents created so far
        PersistenceHandler.getDefault().clear();

        this.currentRole = newRole;
        pm.setRole( newRole );

        //load from new role
        ws.load();

        if( keepDocumentWindows ) {
            ModeImpl editorMode = (ModeImpl) findMode("editor"); //NOI18N
            //re-open editor windows that were opened before the reset
            for( int i=0; i<editors.length && null != editorMode; i++ ) {
                TopComponent editor = editors[i];
                if( editor.getPersistenceType() == TopComponent.PERSISTENCE_NEVER )
                    continue;
                ModeImpl mode = ( ModeImpl ) findMode( editor );
                if( null == mode )
                    mode = editorMode;
                if( null != mode ) {
                    String tcId = findTopComponentID( editor );
                    if( !(mode.getOpenedTopComponents().contains( editor ) || (null != tcId && mode.getOpenedTopComponentsIDs().contains( tcId ))) )
                        mode.addOpenedTopComponentNoNotify(editor);
                    openedBefore.remove( editor );
                }
            }
        }
        
        Set<TopComponent> openedAfter = getRegistry().getOpened();
        openedBefore.removeAll( openedAfter );
        for( TopComponent tc : openedBefore ) {
            componentCloseNotify( tc );
        }

        if( hideAndShowWhileSwitching ) {
            ws.show();
        } else {
            getMainWindow().setCursor( null );
        }

        TopComponent editorToActivate = prevActiveEditor;
        if( null != editorToActivate && !editorToActivate.isOpened() )
            editorToActivate = getArbitrarySelectedEditorTopComponent();
        if( null != editorToActivate )
            editorToActivate.requestActive();
        
        SwingUtilities.invokeLater( new Runnable() {
            @Override
            public void run() {
                Frame mainWindow = getMainWindow();
                mainWindow.invalidate();
                mainWindow.repaint();
            }
        });
        
        return true;
    }
    
    //roles
    
    /**
     * 
     * @param draggable 
     * @since 2.37
     */
    public void userStartedKeyboardDragAndDrop( TopComponentDraggable draggable ) {
        central.userStartedKeyboardDragAndDrop( draggable );
    }

    private static final Object BUSY_FLAG = new Object();
    private static final String BUSY_PROP_NAME = "nbwinsys.tc.isbusy"; //NOI18N

    @Override
    protected void topComponentMakeBusy( TopComponent tc, boolean busy ) {
        boolean wasBusy = isTopComponentBusy( tc );
        tc.putClientProperty( BUSY_PROP_NAME, busy ? BUSY_FLAG : null );
        if( busy != wasBusy ) {
            //update winsys
            ModeImpl mode = (ModeImpl) findMode(tc);
            if( null != mode )
                central.topComponentMakeBusy(mode, tc, busy);
        }
    }

    /**
     * Check if the given TopComponent is 'busy'
     * @param tc
     * @return
     * @since 2.45
     */
    public boolean isTopComponentBusy( TopComponent tc ) {
        return tc.getClientProperty( BUSY_PROP_NAME ) == BUSY_FLAG;
    }
    
    void fireEvent( WindowSystemEventType type ) {
        assertEventDispatchThread();
        
        Collection<WindowSystemListener> copy = null;
        synchronized( listeners ) {
            copy = new ArrayList<WindowSystemListener>( listeners );
        }
        WindowSystemEvent e = new WindowSystemEvent( this );
        for( WindowSystemListener listener : copy ) {
            switch( type ) {
                case beforeLoad:
                    listener.beforeLoad( e );
                    break;
                case beforeSave:
                    listener.beforeSave( e );
                    break;
                case afterLoad:
                    listener.afterLoad( e );
                    break;
                case afterSave:
                    listener.afterSave( e );
                    break;
            }
        }
    }

    public boolean isHeavyWeightShowing() {
        TopComponent.Registry registry = TopComponent.getRegistry();
        Set<TopComponent> opened = new HashSet<TopComponent>(registry.getOpened());
        for( TopComponent tc : opened ) {
            if( !tc.isShowing() )
                continue;
            if( isHeavyWeight( tc ) )
                return true;
        }
        return false;
    }

    private boolean isHeavyWeight( java.awt.Component c ) {
        if( null != c && !c.isLightweight() )
            return true;
        if( c instanceof Container ) {
            for( java.awt.Component child : ((Container)c).getComponents() ) {
                if( isHeavyWeight(child) )
                    return true;
            }
        }
        return false;
    }

    /**
     * Checks the floating status of given TopComponent.
     * @return True if the given TopComponent is separated from the main window.
     * @since 2.51
     */
    @Override
    public boolean isTopComponentFloating( TopComponent tc ) {
        assertEventDispatchThread();
        return !isDocked( tc );
    }

    /**
     * Floats the given TopComponent or docks it back to the main window.
     * @param tc
     * @param floating True to separate the given TopComponent from the main window,
     * false to dock it back to the main window.
     * @since 2.51
     */
    @Override
    public void setTopComponentFloating(  TopComponent tc, boolean floating ) {
        assertEventDispatchThread();
        boolean isFloating = !isDocked( tc );
        if( isFloating == floating )
            return;
        ModeImpl mode = (ModeImpl)findMode( tc );
        if( null == mode )
            throw new IllegalStateException( "Cannot find Mode for TopComponent: " + tc );
        if( floating ) {
            userUndockedTopComponent( tc, mode );
        } else {
            userDockedTopComponent( tc, mode );
        }
    }

    /**
     * An empty TopComponent needed for deselectEditorTopComponents()
     */
    private static class DummyTopComponent extends TopComponent {
        @Override
        protected String preferredID() {
            return "temp";
        }

        @Override
        public int getPersistenceType() {
            return PERSISTENCE_NEVER;
        }
    }
}

