📄 perspectivemanager.java
字号:
/*
* Copyright (c) 2005 FlexDock Development Team. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in the
* Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE.
*/
package org.flexdock.perspective;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.EventQueue;
import java.awt.Window;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import javax.swing.SwingUtilities;
import org.flexdock.docking.Dockable;
import org.flexdock.docking.DockingConstants;
import org.flexdock.docking.DockingManager;
import org.flexdock.docking.DockingPort;
import org.flexdock.docking.event.hierarchy.DockingPortTracker;
import org.flexdock.docking.state.DockingState;
import org.flexdock.docking.state.FloatManager;
import org.flexdock.docking.state.LayoutManager;
import org.flexdock.docking.state.LayoutNode;
import org.flexdock.docking.state.PersistenceException;
import org.flexdock.event.EventManager;
import org.flexdock.event.RegistrationEvent;
import org.flexdock.perspective.event.LayoutEventHandler;
import org.flexdock.perspective.event.PerspectiveEvent;
import org.flexdock.perspective.event.PerspectiveEventHandler;
import org.flexdock.perspective.event.PerspectiveListener;
import org.flexdock.perspective.event.RegistrationHandler;
import org.flexdock.perspective.persist.FilePersistenceHandler;
import org.flexdock.perspective.persist.PersistenceHandler;
import org.flexdock.perspective.persist.PerspectiveModel;
import org.flexdock.util.RootWindow;
import org.flexdock.util.Utilities;
/**
* @author Mateusz Szczap
*/
public class PerspectiveManager implements LayoutManager {
public static final String EMPTY_PERSPECTIVE = "PerspectiveManager.EMPTY_PERSPECTIVE";
public static final String DEFAULT_PERSISTENCE_KEY_VALUE = "perspectiveFile.data";
private static PerspectiveManager SINGLETON = new PerspectiveManager();
private static DockingStateListener UPDATE_LISTENER = new DockingStateListener();
private HashMap m_perspectives = new HashMap();
private PerspectiveFactory perspectiveFactory;
private String m_defaultPerspective;
private String m_currentPerspective;
private PersistenceHandler m_persistHandler;
private boolean restoreFloatingOnLoad;
private String m_defaultPersistenceKey;
static {
initialize();
}
private static void initialize() {
// TODO: Add logic to add and remove event handlers based on whether
// the perspective manager is currently installed. Right now, we're
// just referencing DockingManager.class to ensure the class is properly
// initialized before we add our event handlers. This should be
// called indirectly form within DockingManager, and we should have
// uninstall capability as well.
Class c = DockingManager.class;
EventManager.addHandler(new RegistrationHandler());
EventManager.addHandler(PerspectiveEventHandler.getInstance());
EventManager.addHandler(new LayoutEventHandler());
EventManager.addListener(UPDATE_LISTENER);
String pKey = System.getProperty(DockingConstants.DEFAULT_PERSISTENCE_KEY);
setPersistenceHandler(FilePersistenceHandler.createDefault(DEFAULT_PERSISTENCE_KEY_VALUE));
getInstance().setDefaultPersistenceKey(pKey);
}
public static PerspectiveManager getInstance() {
return SINGLETON;
}
public static void setFactory(PerspectiveFactory factory) {
getInstance().perspectiveFactory = factory;
}
public static void setPersistenceHandler(PersistenceHandler handler) {
getInstance().m_persistHandler = handler;
}
public static PersistenceHandler getPersistenceHandler() {
return getInstance().m_persistHandler;
}
private PerspectiveManager() {
setDefaultPerspective(EMPTY_PERSPECTIVE);
loadPerspective(m_defaultPerspective, (DockingPort)null);
}
public void add(Perspective perspective) {
add(perspective, false);
}
public void add(Perspective perspective, boolean isDefault) {
if (perspective == null) throw new NullPointerException("perspective cannot be null");
m_perspectives.put(perspective.getPersistentId(), perspective);
if(isDefault)
setDefaultPerspective(perspective.getPersistentId());
EventManager.dispatch(new RegistrationEvent(perspective, this, true));
}
public void remove(String perspectiveId) {
if (perspectiveId == null) throw new NullPointerException("perspectiveId cannot be null");
Perspective perspective = getPerspective(perspectiveId);
if (perspective == null)
return;
m_perspectives.remove(perspectiveId);
//set defaultPerspective
if(m_defaultPerspective.equals(perspectiveId))
setDefaultPerspective(EMPTY_PERSPECTIVE);
EventManager.dispatch(new RegistrationEvent(perspective, this, false));
}
public Perspective getPerspective(String perspectiveId) {
if (perspectiveId == null)
return null;
Perspective perspective = (Perspective) m_perspectives.get(perspectiveId);
if(perspective==null) {
perspective = createPerspective(perspectiveId);
if(perspective!=null) {
add(perspective);
}
}
return perspective;
}
public Perspective createPerspective(String perspectiveId) {
if(EMPTY_PERSPECTIVE.equals(perspectiveId))
return new Perspective(EMPTY_PERSPECTIVE, EMPTY_PERSPECTIVE) {
public void load(DockingPort port, boolean defaultSetting) {
// noop
}
};
Perspective p = null;
if (perspectiveFactory != null) {
p = perspectiveFactory.getPerspective(perspectiveId);
//this code ensures that perspective factory create perspectives that return the correct id
//otherwise a NPE appears extremely far away in the code during the first docking operation
if (!p.getPersistentId().equals(perspectiveId)) {
//TODO create a good exception for this
throw new IllegalStateException("Factory created perspective does not match intended ID: " + perspectiveId);
}
}
return p;
}
public Perspective[] getPerspectives() {
synchronized(m_perspectives) {
ArrayList list = new ArrayList(m_perspectives.values());
return (Perspective[])list.toArray(new Perspective[0]);
}
}
public void addListener(PerspectiveListener perspectiveListener) {
EventManager.addListener(perspectiveListener);
}
public void removeListener(PerspectiveListener perspectiveListener) {
EventManager.removeListener(perspectiveListener);
}
public PerspectiveListener[] getPerspectiveListeners() {
return PerspectiveEventHandler.getInstance().getListeners();
}
public void setDefaultPerspective(String perspectiveId) {
m_defaultPerspective = perspectiveId;
}
public void setCurrentPerspective(String perspectiveId) {
setCurrentPerspective(perspectiveId, false);
}
public String getCurrentPerspectiveName() {
return m_currentPerspective;
}
private void setCurrentPerspectiveName(String name) {
m_currentPerspective = "".equals(name)? null: name;
}
public void setCurrentPerspective(String perspectiveId, boolean asDefault) {
perspectiveId = perspectiveId==null? m_defaultPerspective: perspectiveId;
setCurrentPerspectiveName(perspectiveId);
if(asDefault)
setDefaultPerspective(perspectiveId);
}
public Perspective getDefaultPerspective() {
return getPerspective(m_defaultPerspective);
}
public Perspective getCurrentPerspective() {
return getPerspective(getCurrentPerspectiveName());
}
public DockingState getDockingState(Dockable dockable) {
return getCurrentPerspective().getDockingState(dockable);
}
public DockingState getDockingState(String dockable) {
return getCurrentPerspective().getDockingState(dockable);
}
public DockingState getDockingState(Dockable dockable, boolean load) {
return getCurrentPerspective().getDockingState(dockable, load);
}
public DockingState getDockingState(String dockable, boolean load) {
return getCurrentPerspective().getDockingState(dockable, load);
}
public FloatManager getFloatManager() {
return getCurrentPerspective().getLayout();
}
public void reset() {
RootWindow[] windows = DockingManager.getDockingWindows();
if(windows.length!=0)
reset(windows[0].getRootContainer());
}
public void reset(Component window) {
if(window==null) {
reset();
}
else {
DockingPort port = DockingManager.getRootDockingPort(window);
reset(port);
}
}
public void reset(DockingPort rootPort) {
loadPerspectiveImpl(getCurrentPerspectiveName(), rootPort, true);
}
/**
* PerspectiveManager#getMainApplicationWindow returns the first
* window where #getOwner == null. This is especially a problem for apps with
* multiple frames. To display a perspective for a specified window
* it is highly recommended to use #reload(Window w) instead of #reload()
* which is the same as DockingManager#restoreLayout().
* You can use #restoreLayout when the application does not need multiple
* independent docking windows.
*/
public void reload(Window w) {
reload(w, true);
}
// use to load parentless frames
public void reload(Window w, boolean reset) {
String current = getCurrentPerspectiveName();
// if the current perspective is null, use the default value
String key = current == null ? m_defaultPerspective : current;
// null-out the current perspective name to force a reload
// otherwise, the loadPerspective() call will short-circuit since
// it'll detect that the requested perspective is already loaded.
setCurrentPerspectiveName(null);
DockingPort port = DockingManager.getRootDockingPort(w);
Perspective[] perspectives = getPerspectives();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -