blob: 82cecc43fbc9ac21263bf750012a2bfea18af342 [file] [log] [blame]
/*
* 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;
}
}
}