From 3ce845ea200f1ad807e005c911dfa656de5e7ae4 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Wed, 2 May 2018 15:04:47 +0200 Subject: [PATCH] =?UTF-8?q?refactor=20=E2=80=94=20get=20rid=20of=20myUnreg?= =?UTF-8?q?isteredIdToInfo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../openapi/wm/impl/DesktopLayout.java | 189 ++++++++---------- .../wm/impl/ToolWindowManagerImpl.java | 8 +- .../openapi/wm/impl/WindowInfoImpl.kt | 45 ++--- 3 files changed, 114 insertions(+), 128 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/DesktopLayout.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/DesktopLayout.java index 48c989b2889d..a6ca46dc8fdd 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/DesktopLayout.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/DesktopLayout.java @@ -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 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 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 myRegisteredIdToInfo = new THashMap<>(); - - /** - * Map between {@code id}s and unregistered {@code WindowInfo}s. - */ - private final Map myUnregisteredIdToInfo = new THashMap<>(); + private final Map myIdToInfo = new THashMap<>(); private final ClearableLazyValue> myRegisteredInfos = new ClearableLazyValue>() { @NotNull @Override protected List compute() { - if (myRegisteredIdToInfo.isEmpty()) { + if (myIdToInfo.isEmpty()) { return Collections.emptyList(); } - return new ArrayList<>(myRegisteredIdToInfo.values()); - } - }; - private final ClearableLazyValue> myUnregisteredInfos = new ClearableLazyValue>() { - @NotNull - @Override - protected List compute() { - if (myUnregisteredIdToInfo.isEmpty()) { - return Collections.emptyList(); + List result = new ArrayList<>(); + for (WindowInfoImpl value : myIdToInfo.values()) { + if (value.isRegistered()) { + result.add(value); + } } - return new ArrayList<>(myUnregisteredIdToInfo.values()); - } - }; - - private final ClearableLazyValue> myAllInfos = new ClearableLazyValue>() { - @NotNull - @Override - protected List 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 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 getUnregisteredInfos() { - return myUnregisteredInfos.getValue(); - } - - /** - * @return {@code WindowInfo}s of all (registered and unregistered) tool windows. - */ - @NotNull - private List 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 getAllInfos(@NotNull ToolWindowAnchor anchor) { - List infos = getAllInfos(); - List list = new ArrayList<>(infos.size()); - for (WindowInfoImpl info : infos) { + List 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 registeredInfos = getInfos(); - final List unregisteredInfos = getUnregisteredInfos(); - if (registeredInfos.isEmpty() || unregisteredInfos.isEmpty()) { + if (myIdToInfo.isEmpty()) { return null; } + List 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 { - private final HashMap myId2Info = new HashMap<>(); + private final Map 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; diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java index 4703e22aca5f..afa67cc757bf 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java @@ -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); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.kt b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.kt index 8e9c299d0b75..07235dcf0029 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.kt +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.kt @@ -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() +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() /** - * @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() {