/*
* WindowUtils.java
*
* Created on September 21, 2002, 10:57 AM
*/
package cern.gp.windows;
import java.awt.Container;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Iterator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openide.windows.Mode;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;
import org.openide.windows.Workspace;
import cern.gp.util.Assertion;
import cern.gp.util.GPManager;
/**
* Provides utility methods for windowing in NetBeans.
*
* @author Katarina Sigerud
* @version $Revision: 1.2 $ $Date: 2006/09/25 08:52:36 $
*/
public class WindowUtils {
/** A frame that resides in the desktop */
public static final int INTERNAL_FRAME = 0;
/** A frame that resides as a separate window */
public static final int TOP_FRAME = 1;
/** The frame resides docked left, right, top, or bottom */
public static final int DESKTOP_FRAME = 2;
private static final String INTERNAL_FRAME_STRING = "INTERNAL_FRAME";
private static final String TOP_FRAME_STRING = "TOP_FRAME";
private static final String DESKTOP_FRAME_STRING = "DESKTOP_FRAME";
private static final String CONSTRAINT_WEST = "WEST";
/** persist a TopComponent only if it is opened */
public static final int PERSIST_ONLY_OPENED = 1;
/** dont persist the TopComponent */
public static final int PERSIST_NEVER = 0;
/** always persist the TopComponent */
public static final int PERSIST_ALWAYS = 2;
/** unkown persistence mode the TopComponent */
public static final int PERSIST_UNKNOWN = -1;
private static final String PERSISTENCE_TYPE = "PersistenceType";
private static final String PERSIST_NEVER_STR = "Never";
private static final String PERSIST_ONLY_OPENED_STR = "OnlyOpened";
private static final String PERSIST_ALWAYS_STR = null;
/** Indicates the default behavior for windows, MDI or SDI. Default is MDI. */
private static int defaultFrameType = INTERNAL_FRAME;
private static String[] possibleFrameTypes = { INTERNAL_FRAME_STRING, TOP_FRAME_STRING, DESKTOP_FRAME_STRING };
private static Log log = LogFactory.getLog(WindowUtils.class);
//
// -- CONSTRUCTORS ------------------------------------------------
//
/** do not instantiate */
private WindowUtils() {
}
//
// -- PUBLIC METHODS ----------------------------------------------
//
/**
* Utility method: Sets the default windowing behavior, MDI or SDI.
* If set to <code>true</code> the default behavior for new windows is to reside in the desktop.
* @param type indicates that the default windowing behavior,
* should be one of {@link #INTERNAL_FRAME}, {@link #TOP_FRAME}, or {@link #DESKTOP_FRAME}
*/
public static void setFrameType(int frameType) {
defaultFrameType = frameType;
}
/**
* Utility method: opens a topcomponent in the current workspace in a mode with the
* indicated name. This method first looks if the mode already exists, or else
* creates it. Opens the topcomponent in the desktop.
*
* @param component the component to open
* @param modeName the (code) name of the mode
* @return the mode the topcomponent was opened in.
*/
public static Mode openInMode(TopComponent component, String modeName) {
Workspace workspace = WindowManager.getDefault().getCurrentWorkspace();
return openInMode(workspace, component, modeName, defaultFrameType);
}
/**
* Utility method: opens a topcomponent in the given workspace in a mode with the
* indicated name. This method first looks if the mode already exists, or else
* creates it. Opens the topcomponent in the desktop.
*
* @param workspace the workspace top open the component in
* @param component the component to open
* @param modeName the (code) name of the mode
* @return the mode the topcomponent was opened in.
*/
public static Mode openInMode(Workspace workspace, TopComponent component, String modeName) {
return openInMode(workspace, component, modeName, defaultFrameType);
}
/**
* Utility method: opens a topcomponent in the current workspace in a mode with the
* indicated name. This method first looks if the mode already exists, or else
* creates it
*
* @param component the component to open
* @param modeName the (code) name of the mode
* @param frameType indicates the type of the window frame,
* should be one of {@link #INTERNAL_FRAME}, {@link #TOP_FRAME}, or {@link #DESKTOP_FRAME}
* @return the mode the topcomponent was opened in.
*/
public static Mode openInMode(TopComponent component, String modeName, int frameType) {
Workspace workspace = WindowManager.getDefault().getCurrentWorkspace();
return openInMode(workspace, component, modeName, frameType);
}
/**
* Utility method: opens a topcomponent in the given workspace in a mode with the
* indicated name. This method first looks if the mode already exists, or else
* creates it.
* @param workspace the workspace top open the component in
* @param component the component to open
* @param modeName the (code) name of the mode
* @param frameType indicates the type of the window frame,
* should be one of {@link #INTERNAL_FRAME}, {@link #TOP_FRAME}, or {@link #DESKTOP_FRAME}
* @return the mode the topcomponent was opened in.
*/
public static Mode openInMode(Workspace workspace, TopComponent component, String modeName, int frameType) {
Assertion.assertTrue(workspace != null, "workspace != null");
Assertion.assertTrue(component != null, "component != null");
Assertion.assertTrue(modeName != null, "modeName != null");
setPersistMode(component, PERSIST_NEVER);
Mode mode = workspace.findMode(modeName);
if (mode == null) {
mode = workspace.createMode(modeName, modeName, null);
}
mode.dockInto(component);
workspace.activate();
frameResidesInDesktop(mode, frameType);
component.open(workspace);
component.requestFocus();
return mode;
}
/**
* Determine under which conditions the TopComponent is persisted to the NetBeans
* system directory
* @param comp the component
* @param option one of {@link #PERSIST_NEVER} or {@link #PERSIST_ONLY_OPENED}
*/
public static void setPersistMode(TopComponent comp, int option) {
Assertion.assertTrue(comp != null, "comp != null");
Assertion.assertTrue(
(PERSIST_NEVER == option || PERSIST_ALWAYS == option || PERSIST_ONLY_OPENED == option),
"bad option: " + option);
switch (option) {
case PERSIST_NEVER :
comp.putClientProperty(PERSISTENCE_TYPE, PERSIST_NEVER_STR);
break;
case PERSIST_ALWAYS :
comp.putClientProperty(PERSISTENCE_TYPE, PERSIST_ALWAYS_STR);
break;
case PERSIST_ONLY_OPENED :
comp.putClientProperty(PERSISTENCE_TYPE, PERSIST_ONLY_OPENED_STR);
break;
default :
throw new AssertionError("[this should not happen: wrong option " + option);
}
}
/**
* Get the persistence mode of the given TopComponent
* @param comp the component
* @return one of {@link #PERSIST_NEVER} or {@link #PERSIST_ONLY_OPENED}
*/
public static int getPersistMode(TopComponent comp) {
Assertion.assertTrue(comp != null, "comp != null");
String mode = (String) comp.getClientProperty(PERSISTENCE_TYPE);
if (mode == PERSIST_ALWAYS_STR) {
return PERSIST_ALWAYS;
} else if (PERSIST_NEVER_STR.equals(mode)) {
return PERSIST_NEVER;
} else if (PERSIST_ONLY_OPENED_STR.equals(mode)) {
return PERSIST_ONLY_OPENED;
} else {
return PERSIST_UNKNOWN;
}
}
/**
* Utility method: makes the given mode reside in the desktop instead of as a separate window.
* @param mode the mode to make reside in the desktop
*/
public static void frameResidesInDesktop(Mode mode) {
frameResidesInDesktop(mode, defaultFrameType);
}
/**
* Utility method: makes the given mode either reside in the desktop or display a separate window.
* @param mode the mode to make reside in the desktop
* @param frameType indicates the type of frame, MDI or SDI
*/
public static void frameResidesInDesktop(Mode mode, int frameType) {
Assertion.assertTrue(mode != null, "mode != null");
try {
ClassLoader classLoader = Mode.class.getClassLoader();
Class modeImpl = Class.forName("org.netbeans.core.windows.ModeImpl", true, classLoader);
Method getCurrentConstraintsMethod = modeImpl.getMethod("getCurrentConstraints", null);
Object currentConstraints = getCurrentConstraintsMethod.invoke(mode, null);
Method setFrameTypeMethod = modeImpl.getMethod("setFrameType", new Class[] { String.class });
Method setVisibleMethod = modeImpl.getMethod("setVisible", new Class[] { boolean.class });
Method isVisibleMethod = modeImpl.getMethod("isVisible", null);
boolean wasVisible = ((Boolean) isVisibleMethod.invoke(mode, null)).booleanValue();
if (frameType == DESKTOP_FRAME)
currentConstraints = CONSTRAINT_WEST;
Class windowUtils = Class.forName("org.netbeans.core.windows.util.WindowUtils", true, classLoader);
Method findConstrainedModeMethod =
windowUtils.getMethod("findConstrainedMode", new Class[] { Workspace.class, Object.class });
Object constrainedMode =
findConstrainedModeMethod.invoke(null, new Object[] { mode.getWorkspace(), currentConstraints });
String frameTypeName = possibleFrameTypes[frameType];
if (constrainedMode != null && frameType == DESKTOP_FRAME) {
frameType = INTERNAL_FRAME;
frameTypeName = possibleFrameTypes[frameType];
currentConstraints = null;
}
Class windowTypeMgr = Class.forName("org.netbeans.core.windows.frames.WindowTypesManager", true, classLoader);
Field frameFieldMode = windowTypeMgr.getField(frameTypeName);
Method changeModeConstraintsMethod =
windowUtils.getMethod("changeModeConstraints", new Class[] { modeImpl, Object.class });
changeModeConstraintsMethod.invoke(null, new Object[] { mode, currentConstraints });
setFrameTypeMethod.invoke(mode, new Object[] { frameFieldMode.get(windowTypeMgr)});
if (wasVisible) {
setVisibleMethod.invoke(mode, new Object[] { Boolean.TRUE });
Class mainWindow = Class.forName("org.netbeans.core.windows.MainWindow", true, classLoader);
Method getDefaultMethod = mainWindow.getMethod("getDefault", null);
Method getContentPaneMethod = mainWindow.getMethod("getContentPane", null);
Container cp = (Container) getContentPaneMethod.invoke(getDefaultMethod.invoke(null, null), null);
cp.validate();
}
} catch (Exception e) {
GPManager.notify(GPManager.EXCEPTION, e);
}
}
/**
* Utility method: Returns the TopComponent with the given programmatic name in the current workspace,
* or <code>null</code> if there is no such TopComponent.
* @param componentName the programmatic name of the TopComponent
* @return Returns the TopComponent with the given programmatic name,
* or <code>null</code> if there is no such TopComponent
*/
public static TopComponent findTopComponent(String componentName) {
Workspace ws = WindowManager.getDefault().getCurrentWorkspace();
return findTopComponent(ws, componentName);
}
/**
* Utility method: Returns the TopComponent with the given programmatic name in the given workspace,
* or <code>null</code> if there is no such TopComponent.
* @param workspace the workspace in which to look for the TopComponent
* @param componentName the programmatic name of the TopComponent
* @return Returns the TopComponent with the given programmatic name,
* or <code>null</code> if there is no such TopComponent
*/
public static TopComponent findTopComponent(Workspace workspace, String componentName) {
Assertion.assertTrue(workspace != null, "workspace != null");
Assertion.assertTrue(componentName != null, "componentName != null");
Iterator modesIterator = workspace.getModes().iterator();
while (modesIterator.hasNext()) {
Mode mode = (Mode) modesIterator.next();
TopComponent[] tcs = mode.getTopComponents();
for (int i = 0; i < tcs.length; i++) {
TopComponent element = tcs[i];
if (element.getName().equals(componentName)) {
return element;
}
}
}
return null;
}
/**
* Utility method: creates a workspace and adds it to the WindowManager's list of workspaces.
* The new workspace will appear as the last one in the list.
*
* @param codeName the code name of the new workspace
* @param displayName the display name of the new workspace
*/
public static Workspace createWorkspace(String codeName, String displayName) {
Assertion.assertTrue(codeName != null, "codeName != null");
if (displayName == null || displayName.equalsIgnoreCase(""))
displayName = codeName;
Workspace[] workspaces = new Workspace[WindowManager.getDefault().getWorkspaces().length + 1];
Workspace[] currentList = WindowManager.getDefault().getWorkspaces();
int i = 0;
for (; i < currentList.length; i++) {
workspaces[i] = currentList[i];
}
Workspace ws = WindowManager.getDefault().createWorkspace(codeName, displayName);
workspaces[i] = ws;
WindowManager.getDefault().setWorkspaces(workspaces);
return ws;
}
//
// -- implements XXX ----------------------------------------------
//
//
// -- PROTECTED METHODS -------------------------------------------
//
//
// -- PRIVATE METHODS ---------------------------------------------
//
private static boolean performDesktopFrameAction(
Mode mode,
TopComponent comp,
ClassLoader classLoader,
Class modeImplClass,
Class windowUtilsClass)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, ClassNotFoundException {
Workspace ws = mode.getWorkspace();
Object currentConstraints = CONSTRAINT_WEST;
Method findConstrainedModeMethod =
windowUtilsClass.getMethod("findConstrainedMode", new Class[] { Workspace.class, Object.class });
Object constrainedMode = findConstrainedModeMethod.invoke(null, new Object[] { ws, currentConstraints });
if (constrainedMode != null) {
Mode westMode = (Mode) constrainedMode;
Method getContainerInstanceMethod = modeImplClass.getMethod("getContainerInstance", null);
Object tcc = getContainerInstanceMethod.invoke(mode, null);
if (tcc != null) {
Class topComponentContainerClass =
Class.forName("org.netbeans.core.windows.frames.TopComponentContainer", true, classLoader);
Method removeTopComponentMethod =
topComponentContainerClass.getMethod("removeTopComponent", new Class[] { TopComponent.class });
removeTopComponentMethod.invoke(tcc, new Object[] { comp });
Method dockIntoMethod = modeImplClass.getMethod("dockInto", new Class[] { TopComponent.class, Object.class });
dockIntoMethod.invoke(westMode, new Object[] { comp, currentConstraints });
return true;
}
}
return false;
}
}