blob: 3cf33f1e8155287dd07a9346e45f3dd3a1015f44 [file] [log] [blame]
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed 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 com.intellij.execution.ui.layout.impl;
import com.intellij.execution.ui.layout.LayoutAttractionPolicy;
import com.intellij.execution.ui.layout.PlaceInGrid;
import com.intellij.execution.ui.layout.Tab;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.content.Content;
import com.intellij.util.xmlb.XmlSerializer;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.*;
public class RunnerLayout {
public static final Key<Integer> DEFAULT_INDEX = Key.create("RunnerLayoutDefaultIndex");
public static final Key<Integer> DROP_INDEX = Key.create("RunnerLayoutDropIndex");
private final String myID;
protected Map<String, ViewImpl> myViews = new HashMap<String, ViewImpl>();
private final Map<String, ViewImpl.Default> myDefaultViews = new HashMap<String, ViewImpl.Default>();
protected Set<TabImpl> myTabs = new TreeSet<TabImpl>(new Comparator<TabImpl>() {
@Override
public int compare(final TabImpl o1, final TabImpl o2) {
return o1.getIndex() - o2.getIndex();
}
});
private final Map<Integer, TabImpl.Default> myDefaultTabs = new HashMap<Integer, TabImpl.Default>();
protected General myGeneral = new General();
private final Map<String, Pair<String, LayoutAttractionPolicy>> myDefaultFocus = new HashMap<String, Pair<String, LayoutAttractionPolicy>>();
public RunnerLayout(@NotNull String ID) {
myID = ID;
}
@Nullable
public String getDefaultDisplayName(final int defaultIndex) {
final TabImpl.Default tab = myDefaultTabs.get(defaultIndex);
return tab != null ? tab.myDisplayName : null;
}
@NotNull
public TabImpl getOrCreateTab(final int index) {
TabImpl tab = findTab(index);
if (tab != null) return tab;
tab = createNewTab(index);
return tab;
}
@NotNull
private TabImpl createNewTab(final int index) {
final TabImpl.Default defaultTab = getOrCreateDefaultTab(index);
final TabImpl tab = defaultTab.createTab();
myTabs.add(tab);
return tab;
}
@NotNull
private TabImpl.Default getOrCreateDefaultTab(final int index) {
TabImpl.Default tab = myDefaultTabs.get(index);
if (tab == null) {
tab = new TabImpl.Default(index, null, null);
myDefaultTabs.put(index, tab);
}
return tab;
}
@NotNull
public TabImpl createNewTab() {
int index = 0;
for (TabImpl each : myTabs) {
if (!isUsed(each)) return each;
if (each.getIndex() < Integer.MAX_VALUE) {
index = each.getIndex() + 1;
}
else {
break;
}
}
return createNewTab(index);
}
private boolean isUsed(@NotNull TabImpl tab) {
for (ViewImpl each : myViews.values()) {
if (each.getTab() == tab) return true;
}
return false;
}
@Nullable
protected TabImpl findTab(int index) {
for (TabImpl each : myTabs) {
if (index == each.getIndex()) return each;
}
return null;
}
@NotNull
public Element getState() {
return write(new Element("layout"));
}
public void loadState(@NotNull Element state) {
read(state);
}
@NotNull
public Element read(@NotNull Element parentNode) {
List tabs = parentNode.getChildren(StringUtil.getShortName(TabImpl.class.getName()));
for (Object eachTabElement : tabs) {
TabImpl eachTab = new TabImpl((Element)eachTabElement);
getOrCreateTab(eachTab.getIndex()).read((Element)eachTabElement);
}
final List views = parentNode.getChildren(StringUtil.getShortName(ViewImpl.class.getName()));
for (Object content : views) {
final ViewImpl state = new ViewImpl(this, (Element)content);
myViews.put(state.getID(), state);
}
XmlSerializer.deserializeInto(myGeneral, parentNode.getChild(StringUtil.getShortName(myGeneral.getClass().getName(), '$')));
return parentNode;
}
@NotNull
public Element write(@NotNull Element parentNode) {
for (ViewImpl eachState : myViews.values()) {
eachState.write(parentNode);
}
for (TabImpl eachTab : myTabs) {
if (isUsed(eachTab)) {
eachTab.write(parentNode);
}
}
parentNode.addContent(XmlSerializer.serialize(myGeneral));
return parentNode;
}
public void resetToDefault() {
myViews.clear();
myTabs.clear();
}
public boolean isToolbarHorizontal() {
return false;
}
public void setToolbarHorizontal(boolean horizontal) {
myGeneral.horizontalToolbar = horizontal;
}
@NotNull
public ViewImpl getStateFor(@NotNull Content content) {
return getOrCreateView(getOrCreateContentId(content));
}
public void clearStateFor(@NotNull Content content) {
final ViewImpl view = myViews.remove(getOrCreateContentId(content));
if (view != null) {
final Tab tab = view.getTab();
if (tab instanceof TabImpl) {
myTabs.remove(tab);
}
}
}
@NotNull
private static String getOrCreateContentId(@NotNull Content content) {
@NonNls String id = content.getUserData(ViewImpl.ID);
if (id == null) {
id = "UnknownView-" + content.getDisplayName();
content.putUserData(ViewImpl.ID, id);
}
return id;
}
@NotNull
private ViewImpl getOrCreateView(@NotNull String id) {
if (myViews.containsKey(id)) {
return myViews.get(id);
}
final ViewImpl.Default defaultView = getOrCreateDefault(id);
final ViewImpl view = defaultView.createView(this);
myViews.put(id, view);
return view;
}
@NotNull
private ViewImpl.Default getOrCreateDefault(@NotNull String id) {
if (myDefaultViews.containsKey(id)) {
return myDefaultViews.get(id);
}
return setDefault(id, Integer.MAX_VALUE, PlaceInGrid.bottom, false);
}
@NotNull
public TabImpl.Default setDefault(int tabID, String displayName, Icon icon) {
final TabImpl.Default tab = new TabImpl.Default(tabID, displayName, icon);
myDefaultTabs.put(tabID, tab);
return tab;
}
@NotNull
public ViewImpl.Default setDefault(@NotNull String id, int tabIndex, @NotNull PlaceInGrid placeInGrid, boolean isMinimized) {
final ViewImpl.Default view = new ViewImpl.Default(id, tabIndex, placeInGrid, isMinimized);
myDefaultViews.put(id, view);
return view;
}
@NotNull
public PlaceInGrid getDefaultGridPlace(@NotNull Content content) {
return getOrCreateDefault(getOrCreateContentId(content)).getPlaceInGrid();
}
public boolean isToFocus(final String id, @NotNull String condition) {
return Comparing.equal(id, getToFocus(condition));
}
public void setToFocus(final String id, @NotNull String condition) {
myGeneral.focusOnCondition.put(condition, id);
}
public void setDefaultToFocus(@NotNull String id, @NotNull String condition, @NotNull final LayoutAttractionPolicy policy) {
myDefaultFocus.put(condition, Pair.create(id, policy));
}
@Nullable
public String getToFocus(@NotNull String condition) {
return myGeneral.focusOnCondition.containsKey(condition) ? myGeneral.focusOnCondition.get(condition) :
myDefaultFocus.containsKey(condition) ? myDefaultFocus.get(condition).getFirst() : null;
}
@NotNull
public LayoutAttractionPolicy getAttractionPolicy(@NotNull String condition) {
final Pair<String, LayoutAttractionPolicy> pair = myDefaultFocus.get(condition);
return pair == null ? new LayoutAttractionPolicy.FocusOnce() : pair.getSecond();
}
public static class General {
public volatile boolean horizontalToolbar = false;
public volatile Map<String, String> focusOnCondition = new HashMap<String, String>();
}
}