mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
refactor — get rid of myUnregisteredIdToInfo
This commit is contained in:
@@ -8,12 +8,12 @@ import com.intellij.openapi.util.ClearableLazyValue;
|
||||
import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.openapi.wm.ToolWindowAnchor;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import gnu.trove.THashMap;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.*;
|
||||
|
||||
import static com.intellij.configurationStore.XmlSerializer.serialize;
|
||||
@@ -23,81 +23,86 @@ import static com.intellij.configurationStore.XmlSerializer.serialize;
|
||||
*/
|
||||
public final class DesktopLayout {
|
||||
private static final Logger LOG = Logger.getInstance(DesktopLayout.class);
|
||||
private static final Comparator<WindowInfoImpl> ourWindowInfoComparator = Comparator.comparingInt(WindowInfoImpl::getOrder);
|
||||
|
||||
private static int getAnchorWeight(@NotNull ToolWindowAnchor anchor) {
|
||||
if (anchor == ToolWindowAnchor.TOP) {
|
||||
return SwingConstants.TOP;
|
||||
}
|
||||
if (anchor == ToolWindowAnchor.LEFT) {
|
||||
return SwingConstants.LEFT;
|
||||
}
|
||||
if (anchor == ToolWindowAnchor.BOTTOM) {
|
||||
return SwingConstants.BOTTOM;
|
||||
}
|
||||
if (anchor == ToolWindowAnchor.RIGHT) {
|
||||
return SwingConstants.RIGHT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static final Comparator<WindowInfoImpl> ourWindowInfoComparator = (o1, o2) -> {
|
||||
int d = getAnchorWeight(o1.getAnchor()) - getAnchorWeight(o2.getAnchor());
|
||||
return d == 0 ? o1.getOrder() - o2.getOrder() : d;
|
||||
};
|
||||
|
||||
static final String TAG = "layout";
|
||||
|
||||
/**
|
||||
* Map between {@code id}s and registered {@code WindowInfo}s.
|
||||
* Map between {@code id}s {@code WindowInfo}s.
|
||||
*/
|
||||
private final Map<String, WindowInfoImpl> myRegisteredIdToInfo = new THashMap<>();
|
||||
|
||||
/**
|
||||
* Map between {@code id}s and unregistered {@code WindowInfo}s.
|
||||
*/
|
||||
private final Map<String, WindowInfoImpl> myUnregisteredIdToInfo = new THashMap<>();
|
||||
private final Map<String, WindowInfoImpl> myIdToInfo = new THashMap<>();
|
||||
|
||||
private final ClearableLazyValue<List<WindowInfoImpl>> myRegisteredInfos = new ClearableLazyValue<List<WindowInfoImpl>>() {
|
||||
@NotNull
|
||||
@Override
|
||||
protected List<WindowInfoImpl> compute() {
|
||||
if (myRegisteredIdToInfo.isEmpty()) {
|
||||
if (myIdToInfo.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return new ArrayList<>(myRegisteredIdToInfo.values());
|
||||
}
|
||||
};
|
||||
|
||||
private final ClearableLazyValue<List<WindowInfoImpl>> myUnregisteredInfos = new ClearableLazyValue<List<WindowInfoImpl>>() {
|
||||
@NotNull
|
||||
@Override
|
||||
protected List<WindowInfoImpl> compute() {
|
||||
if (myUnregisteredIdToInfo.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
List<WindowInfoImpl> result = new ArrayList<>();
|
||||
for (WindowInfoImpl value : myIdToInfo.values()) {
|
||||
if (value.isRegistered()) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
return new ArrayList<>(myUnregisteredIdToInfo.values());
|
||||
}
|
||||
};
|
||||
|
||||
private final ClearableLazyValue<List<WindowInfoImpl>> myAllInfos = new ClearableLazyValue<List<WindowInfoImpl>>() {
|
||||
@NotNull
|
||||
@Override
|
||||
protected List<WindowInfoImpl> compute() {
|
||||
return ContainerUtil.concat(getInfos(), getUnregisteredInfos());
|
||||
result.sort(ourWindowInfoComparator);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Copies itself from the passed
|
||||
*
|
||||
* @param layout to be copied.
|
||||
*/
|
||||
public final void copyFrom(@NotNull DesktopLayout layout) {
|
||||
for (WindowInfoImpl info1 : layout.getAllInfos()) {
|
||||
WindowInfoImpl info = myRegisteredIdToInfo.get(info1.getId());
|
||||
if (info != null) {
|
||||
info.copyFrom(info1);
|
||||
continue;
|
||||
}
|
||||
info = myUnregisteredIdToInfo.get(info1.getId());
|
||||
if (info == null) {
|
||||
myUnregisteredIdToInfo.put(info1.getId(), info1.copy());
|
||||
Map<String, WindowInfoImpl> old = new THashMap<>(myIdToInfo);
|
||||
myIdToInfo.clear();
|
||||
for (WindowInfoImpl otherInfo : layout.myIdToInfo.values()) {
|
||||
WindowInfoImpl oldInfo = old.get(otherInfo.getId());
|
||||
if (oldInfo == null) {
|
||||
myIdToInfo.put(otherInfo.getId(), otherInfo.copy());
|
||||
}
|
||||
else {
|
||||
info.copyFrom(info1);
|
||||
oldInfo.copyFrom(otherInfo);
|
||||
myIdToInfo.put(otherInfo.getId(), oldInfo);
|
||||
}
|
||||
}
|
||||
invalidateCaches();
|
||||
// normalize orders
|
||||
|
||||
normalizeOrders();
|
||||
}
|
||||
|
||||
private void normalizeOrders() {
|
||||
normalizeOrder(getAllInfos(ToolWindowAnchor.TOP));
|
||||
normalizeOrder(getAllInfos(ToolWindowAnchor.LEFT));
|
||||
normalizeOrder(getAllInfos(ToolWindowAnchor.BOTTOM));
|
||||
normalizeOrder(getAllInfos(ToolWindowAnchor.RIGHT));
|
||||
|
||||
invalidateCaches();
|
||||
}
|
||||
|
||||
private void invalidateCaches() {
|
||||
myRegisteredInfos.drop();
|
||||
myUnregisteredInfos.drop();
|
||||
myAllInfos.drop();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,26 +113,22 @@ public final class DesktopLayout {
|
||||
* @param anchor the default tool window anchor.
|
||||
*/
|
||||
final WindowInfoImpl register(@NotNull String id, @NotNull ToolWindowAnchor anchor, final boolean splitMode) {
|
||||
WindowInfoImpl info = myUnregisteredIdToInfo.get(id);
|
||||
WindowInfoImpl info = myIdToInfo.get(id);
|
||||
if (info == null) {
|
||||
// tool window is being registered first time
|
||||
info = new WindowInfoImpl();
|
||||
info.setId(id);
|
||||
info.setAnchor(anchor);
|
||||
info.setSplit(splitMode);
|
||||
myIdToInfo.put(id, info);
|
||||
invalidateCaches();
|
||||
}
|
||||
else {
|
||||
// tool window has been already registered some time
|
||||
myUnregisteredIdToInfo.remove(id);
|
||||
}
|
||||
myRegisteredIdToInfo.put(id, info);
|
||||
invalidateCaches();
|
||||
info.setRegistered(true);
|
||||
return info;
|
||||
}
|
||||
|
||||
final void unregister(@NotNull String id) {
|
||||
final WindowInfoImpl info = myRegisteredIdToInfo.remove(id).copy();
|
||||
myUnregisteredIdToInfo.put(id, info);
|
||||
WindowInfoImpl info = myIdToInfo.get(id);
|
||||
info.setRegistered(false);
|
||||
invalidateCaches();
|
||||
}
|
||||
|
||||
@@ -137,17 +138,17 @@ public final class DesktopLayout {
|
||||
* value if and only if window with {@code id} is registered one.
|
||||
*/
|
||||
final WindowInfoImpl getInfo(@NotNull String id, final boolean onlyRegistered) {
|
||||
final WindowInfoImpl info = myRegisteredIdToInfo.get(id);
|
||||
if (onlyRegistered || info != null) {
|
||||
return info;
|
||||
WindowInfoImpl info = myIdToInfo.get(id);
|
||||
if (onlyRegistered && info != null && !info.isRegistered()) {
|
||||
return null;
|
||||
}
|
||||
return myUnregisteredIdToInfo.get(id);
|
||||
return info;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
final String getActiveId() {
|
||||
for (WindowInfoImpl info : getInfos()) {
|
||||
if (info.isActive()) {
|
||||
for (WindowInfoImpl info : myIdToInfo.values()) {
|
||||
if (info.isRegistered() && info.isActive()) {
|
||||
return info.getId();
|
||||
}
|
||||
}
|
||||
@@ -162,37 +163,20 @@ public final class DesktopLayout {
|
||||
return myRegisteredInfos.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code WindowInfos}s for all windows that are currently unregistered.
|
||||
*/
|
||||
@NotNull
|
||||
private List<WindowInfoImpl> getUnregisteredInfos() {
|
||||
return myUnregisteredInfos.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code WindowInfo}s of all (registered and unregistered) tool windows.
|
||||
*/
|
||||
@NotNull
|
||||
private List<WindowInfoImpl> getAllInfos() {
|
||||
return myAllInfos.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return all (registered and not unregistered) {@code WindowInfos} for the specified {@code anchor}.
|
||||
* Returned infos are sorted by order.
|
||||
*/
|
||||
@NotNull
|
||||
private List<WindowInfoImpl> getAllInfos(@NotNull ToolWindowAnchor anchor) {
|
||||
List<WindowInfoImpl> infos = getAllInfos();
|
||||
List<WindowInfoImpl> list = new ArrayList<>(infos.size());
|
||||
for (WindowInfoImpl info : infos) {
|
||||
List<WindowInfoImpl> result = new ArrayList<>();
|
||||
for (WindowInfoImpl info : myIdToInfo.values()) {
|
||||
if (anchor == info.getAnchor()) {
|
||||
list.add(info);
|
||||
result.add(info);
|
||||
}
|
||||
}
|
||||
list.sort(ourWindowInfoComparator);
|
||||
return list;
|
||||
result.sort(ourWindowInfoComparator);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -206,11 +190,13 @@ public final class DesktopLayout {
|
||||
}
|
||||
|
||||
final boolean isToolWindowRegistered(@NotNull String id) {
|
||||
return myRegisteredIdToInfo.containsKey(id);
|
||||
WindowInfoImpl info = myIdToInfo.get(id);
|
||||
return info != null && info.isRegistered();
|
||||
}
|
||||
|
||||
final boolean isToolWindowUnregistered(@NotNull String id) {
|
||||
return myUnregisteredIdToInfo.containsKey(id);
|
||||
WindowInfoImpl info = myIdToInfo.get(id);
|
||||
return info != null && !info.isRegistered();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -228,7 +214,7 @@ public final class DesktopLayout {
|
||||
*/
|
||||
private int getMaxOrder(@NotNull ToolWindowAnchor anchor) {
|
||||
int res = -1;
|
||||
for (final WindowInfoImpl info : getAllInfos()) {
|
||||
for (WindowInfoImpl info : myIdToInfo.values()) {
|
||||
if (anchor == info.getAnchor() && res < info.getOrder()) {
|
||||
res = info.getOrder();
|
||||
}
|
||||
@@ -266,6 +252,8 @@ public final class DesktopLayout {
|
||||
if (oldAnchor != newAnchor) {
|
||||
normalizeOrder(getAllInfos(newAnchor));
|
||||
}
|
||||
|
||||
invalidateCaches();
|
||||
}
|
||||
|
||||
final void setSplitMode(@NotNull String id, boolean split) {
|
||||
@@ -273,7 +261,7 @@ public final class DesktopLayout {
|
||||
}
|
||||
|
||||
public final void readExternal(@NotNull Element layoutElement) {
|
||||
myUnregisteredInfos.drop();
|
||||
myIdToInfo.clear();
|
||||
for (Element e : layoutElement.getChildren(WindowInfoImpl.TAG)) {
|
||||
WindowInfoImpl info = XmlSerializer.deserialize(e, WindowInfoImpl.class);
|
||||
if (info.getId() == null) {
|
||||
@@ -281,30 +269,29 @@ public final class DesktopLayout {
|
||||
continue;
|
||||
}
|
||||
|
||||
myIdToInfo.put(info.getId(), info);
|
||||
}
|
||||
|
||||
for (WindowInfoImpl info : myIdToInfo.values()) {
|
||||
if (info.getOrder() == -1) {
|
||||
// if order isn't defined then window's button will be the last one in the stripe
|
||||
info.setOrder(getMaxOrder(info.getAnchor()) + 1);
|
||||
}
|
||||
myUnregisteredIdToInfo.put(info.getId(), info);
|
||||
}
|
||||
|
||||
normalizeOrders();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public final Element writeExternal(@NotNull String tagName) {
|
||||
final List<WindowInfoImpl> registeredInfos = getInfos();
|
||||
final List<WindowInfoImpl> unregisteredInfos = getUnregisteredInfos();
|
||||
if (registeredInfos.isEmpty() || unregisteredInfos.isEmpty()) {
|
||||
if (myIdToInfo.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<WindowInfoImpl> list = new ArrayList<>(myIdToInfo.values());
|
||||
list.sort(ourWindowInfoComparator);
|
||||
Element state = new Element(tagName);
|
||||
for (WindowInfoImpl info : registeredInfos) {
|
||||
Element element = serialize(info);
|
||||
if (element != null) {
|
||||
state.addContent(element);
|
||||
}
|
||||
}
|
||||
for (WindowInfoImpl info : unregisteredInfos) {
|
||||
for (WindowInfoImpl info : list) {
|
||||
Element element = serialize(info);
|
||||
if (element != null) {
|
||||
state.addContent(element);
|
||||
@@ -327,22 +314,22 @@ public final class DesktopLayout {
|
||||
}
|
||||
|
||||
private final class MyStripeButtonComparator implements Comparator<StripeButton> {
|
||||
private final HashMap<String, WindowInfoImpl> myId2Info = new HashMap<>();
|
||||
private final Map<String, WindowInfoImpl> myIdToInfo = new THashMap<>();
|
||||
|
||||
public MyStripeButtonComparator(@NotNull ToolWindowAnchor anchor) {
|
||||
for (final WindowInfoImpl info : getInfos()) {
|
||||
for (WindowInfoImpl info : DesktopLayout.this.myIdToInfo.values()) {
|
||||
if (anchor == info.getAnchor()) {
|
||||
myId2Info.put(info.getId(), info.copy());
|
||||
myIdToInfo.put(info.getId(), info.copy());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int compare(final StripeButton obj1, final StripeButton obj2) {
|
||||
final WindowInfoImpl info1 = myId2Info.get(obj1.getWindowInfo().getId());
|
||||
final WindowInfoImpl info1 = myIdToInfo.get(obj1.getWindowInfo().getId());
|
||||
final int order1 = info1 != null ? info1.getOrder() : 0;
|
||||
|
||||
final WindowInfoImpl info2 = myId2Info.get(obj2.getWindowInfo().getId());
|
||||
final WindowInfoImpl info2 = myIdToInfo.get(obj2.getWindowInfo().getId());
|
||||
final int order2 = info2 != null ? info2.getOrder() : 0;
|
||||
|
||||
return order1 - order2;
|
||||
|
||||
@@ -510,7 +510,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
|
||||
}
|
||||
|
||||
WindowInfoImpl info = getInfo(bean.id);
|
||||
if (!info.isSplit() && bean.secondary && !info.wasRead()) {
|
||||
if (!info.isSplit() && bean.secondary && !info.isWasRead()) {
|
||||
toolWindow.setSplitMode(true, null);
|
||||
}
|
||||
|
||||
@@ -1808,7 +1808,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
|
||||
@Nullable final Rectangle floatingBounds) {
|
||||
|
||||
final WindowInfoImpl info = getInfo(toolWindow.getId());
|
||||
if (info.wasRead()) return;
|
||||
if (info.isWasRead()) return;
|
||||
|
||||
if (floatingBounds != null) {
|
||||
info.setFloatingBounds(floatingBounds);
|
||||
@@ -1825,7 +1825,9 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
|
||||
|
||||
void setDefaultContentUiType(@NotNull ToolWindowImpl toolWindow, @NotNull ToolWindowContentUiType type) {
|
||||
final WindowInfoImpl info = getInfo(toolWindow.getId());
|
||||
if (info.wasRead()) return;
|
||||
if (info.isWasRead()) {
|
||||
return;
|
||||
}
|
||||
toolWindow.setContentUiType(type, null);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,11 +8,22 @@ import com.intellij.util.xmlb.Converter
|
||||
import com.intellij.util.xmlb.annotations.Attribute
|
||||
import com.intellij.util.xmlb.annotations.Property
|
||||
import com.intellij.util.xmlb.annotations.Tag
|
||||
import com.intellij.util.xmlb.annotations.Transient
|
||||
import org.jdom.Element
|
||||
import java.awt.Rectangle
|
||||
|
||||
private val LOG = logger<WindowInfoImpl>()
|
||||
|
||||
private fun canActivateOnStart(id: String?): Boolean {
|
||||
for (ep in ToolWindowEP.EP_NAME.extensions) {
|
||||
if (id == ep.id) {
|
||||
val factory = ep.toolWindowFactory
|
||||
return !factory!!.isDoNotActivateOnStart
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@Suppress("EqualsOrHashCode")
|
||||
@Tag("window_info")
|
||||
@Property(style = Property.Style.ATTRIBUTE)
|
||||
@@ -20,18 +31,11 @@ class WindowInfoImpl : Cloneable, WindowInfo, BaseState() {
|
||||
companion object {
|
||||
internal const val TAG = "window_info"
|
||||
const val DEFAULT_WEIGHT = 0.33f
|
||||
|
||||
private fun canActivateOnStart(id: String?): Boolean {
|
||||
for (ep in ToolWindowEP.EP_NAME.extensions) {
|
||||
if (id == ep.id) {
|
||||
val factory = ep.toolWindowFactory
|
||||
return !factory!!.isDoNotActivateOnStart
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@get:Transient
|
||||
var isRegistered = false
|
||||
|
||||
override var isActive by property(false)
|
||||
|
||||
@get:Attribute(converter = ToolWindowAnchorConverter::class)
|
||||
@@ -41,14 +45,13 @@ class WindowInfoImpl : Cloneable, WindowInfo, BaseState() {
|
||||
override var isAutoHide by property(false)
|
||||
|
||||
/**
|
||||
* Bounds of window in "floating" mode. It equals to `null` if
|
||||
* floating bounds are undefined.
|
||||
* Bounds of window in "floating" mode. It equals to `null` if floating bounds are undefined.
|
||||
*/
|
||||
@get:Property(flat = true, style = Property.Style.ATTRIBUTE)
|
||||
override var floatingBounds by property<Rectangle?>()
|
||||
|
||||
/**
|
||||
* @return `ID` of the tool window
|
||||
* ID of the tool window
|
||||
*/
|
||||
var id by string()
|
||||
|
||||
@@ -88,11 +91,9 @@ class WindowInfoImpl : Cloneable, WindowInfo, BaseState() {
|
||||
*/
|
||||
var order by property(-1)
|
||||
|
||||
private var wasRead: Boolean = false
|
||||
|
||||
init {
|
||||
this.id = id
|
||||
}
|
||||
@get:Transient
|
||||
var isWasRead: Boolean = false
|
||||
private set
|
||||
|
||||
fun copy(): WindowInfoImpl {
|
||||
val info = WindowInfoImpl()
|
||||
@@ -113,7 +114,7 @@ class WindowInfoImpl : Cloneable, WindowInfo, BaseState() {
|
||||
get() = type == ToolWindowType.SLIDING
|
||||
|
||||
fun readExternal(element: Element) {
|
||||
wasRead = true
|
||||
isWasRead = true
|
||||
|
||||
try {
|
||||
setTypeAndCheck(ToolWindowType.valueOf(element.getAttributeValue("type")))
|
||||
@@ -142,11 +143,7 @@ class WindowInfoImpl : Cloneable, WindowInfo, BaseState() {
|
||||
return anchor.hashCode() + id!!.hashCode() + type.hashCode() + order
|
||||
}
|
||||
|
||||
fun wasRead() = wasRead
|
||||
|
||||
override fun toString(): String {
|
||||
return "id: $id, ${super.toString()}"
|
||||
}
|
||||
override fun toString() = "id: $id, ${super.toString()}"
|
||||
}
|
||||
|
||||
private class ContentUiTypeConverter : Converter<ToolWindowContentUiType>() {
|
||||
|
||||
Reference in New Issue
Block a user