diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapScheme.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapScheme.java index 8b1b1f12cee1..0a08fa3e2148 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapScheme.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapScheme.java @@ -15,49 +15,71 @@ */ package com.intellij.openapi.keymap.impl.ui; -import com.intellij.openapi.actionSystem.Shortcut; import com.intellij.openapi.keymap.Keymap; import com.intellij.openapi.keymap.impl.KeymapImpl; import com.intellij.openapi.options.Scheme; import org.jetbrains.annotations.NotNull; -import static java.util.Objects.deepEquals; - /** + * This class represents a keymap as a mutable or immutable scheme. + * * @author Sergey.Malenkov */ final class KeymapScheme implements Scheme { private final KeymapImpl original; private KeymapImpl mutable; + /** + * @param keymap a loaded keymap + */ KeymapScheme(@NotNull Keymap keymap) { original = (KeymapImpl)keymap; } + /** + * @return a current presentable name of a keymap + */ @NotNull @Override public String getName() { return getCurrent().getPresentableName(); } + /** + * Renames a mutable copy, which is created on demand. + * + * @param name a new name to set + */ void setName(@NotNull String name) { getMutable().setName(name); } + /** + * @return a parent of the original keymap if it is mutable + */ Keymap getParent() { return !isMutable() ? null : original.getParent(); } + /** + * @return a keymap to which this scheme belongs + */ @NotNull Keymap getOriginal() { return original; } + /** + * @return a current state of this scheme + */ @NotNull KeymapImpl getCurrent() { return mutable != null ? mutable : original; } + /** + * @return a mutable copy, which is created on demand + */ @NotNull KeymapImpl getMutable() { if (mutable != null) return mutable; @@ -66,10 +88,17 @@ final class KeymapScheme implements Scheme { return mutable; } + /** + * @return {@code true} if the original keymap can be modified + */ boolean isMutable() { return original.canModify(); } + /** + * @param keymap a keymap to test + * @return {@code true} if the specified keymap belongs to this scheme + */ boolean contains(@NotNull Keymap keymap) { return keymap == original || keymap == mutable; } @@ -78,37 +107,71 @@ final class KeymapScheme implements Scheme { return name.equals(keymap.getName()) || name.equals(keymap.getPresentableName()); } + /** + * @param name a name to test + * @return {@code true} if the specified name is used by this scheme + */ boolean contains(@NotNull String name) { return contains(original, name) || mutable != null && contains(mutable, name); } + /** + * @return {@code true} if the current state of this scheme differs from the parent keymap + * @see #reset() + */ boolean canReset() { return getCurrent().getOwnActionIds().length > 0; } + /** + * Removes from the mutable copy all differences from the parent keymap. + * + * @see #canReset() + */ void reset() { assert canReset() : "reset all modified shortcuts unexpectedly"; getMutable().clearOwnActionsIds(); } + /** + * @param actionId an action identifier to test + * @return {@code true} if the specified action differs from the same action in the parent keymap + * @see #reset(String) + */ boolean canReset(@NotNull String actionId) { return getCurrent().hasOwnActionId(actionId); } + /** + * Removes from the mutable copy all differences for the specified action. + * + * @param actionId an action identifier to reset + * @see #canReset(String) + */ void reset(@NotNull String actionId) { assert canReset(actionId) : "reset modified action shortcuts unexpectedly"; getMutable().clearOwnActionsId(actionId); } + /** + * Applies all changes from the mutable copy to the original one. + * + * @return a keymap to which this scheme belongs + */ @NotNull Keymap apply() { if (mutable != null) mutable.copyTo(original); - mutable = null; return original; } + /** + * @param name a new name to use + * @return a new scheme created from this one + */ @NotNull KeymapScheme copy(@NotNull String name) { - return new KeymapScheme(getCurrent().deriveKeymap(name)); + KeymapImpl keymap = original.deriveKeymap(name); + if (mutable != null) mutable.copyTo(keymap); + return new KeymapScheme(keymap); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapSchemeManager.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapSchemeManager.java index 600dbd1fcb3e..08116cf5a1fa 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapSchemeManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapSchemeManager.java @@ -33,12 +33,18 @@ import static com.intellij.openapi.util.text.StringUtil.naturalCompare; import static java.util.stream.Collectors.toList; /** + * This class operates with the KeymapManager. + * * @author Sergey.Malenkov */ final class KeymapSchemeManager { private static final Condition FILTER = keymap -> !isMac || !KeymapManager.DEFAULT_IDEA_KEYMAP.equals(keymap.getName()); private final ArrayList list = new ArrayList<>(); + /** + * @param predicate a predicate to test a scheme + * @return a first scheme that belongs to the specified predicate, or {@code null} + */ KeymapScheme find(@NotNull Predicate predicate) { for (KeymapScheme scheme : list) { if (predicate.test(scheme)) return scheme; @@ -46,22 +52,41 @@ final class KeymapSchemeManager { return null; } + /** + * @param scheme a scheme to add into the list of schemes + * @return the same scheme to select + */ KeymapScheme add(@NotNull KeymapScheme scheme) { list.add(scheme); return scheme; } + /** + * @param scheme a scheme to remove from the list of schemes + * @return a scheme to select + */ KeymapScheme remove(@NotNull KeymapScheme scheme) { list.remove(scheme); - return getSchemeToSelect(list, scheme.getParent()); + return getSchemeToSelect(scheme.getParent()); } + /** + * Initializes a list of schemes from loaded keymaps. + * + * @return a scheme to select + * @see KeymapSelector#reset() + */ KeymapScheme reset() { list.clear(); getKeymaps().forEach(keymap -> list.add(new KeymapScheme(keymap))); - return getSchemeToSelect(list, null); + return getSchemeToSelect(null); } + /** + * @param selected a selected scheme to activate corresponding keymap + * @return the same scheme to select + * @see KeymapSelector#apply() + */ KeymapScheme apply(KeymapScheme selected) { Keymap active = selected == null ? null : selected.getOriginal(); List keymaps = list.stream().map(scheme -> scheme.apply()).collect(toList()); @@ -70,13 +95,20 @@ final class KeymapSchemeManager { return selected; } + /** + * @return a list of loaded keymaps + */ @NotNull private static List getKeymaps() { KeymapManagerImpl manager = (KeymapManagerImpl)KeymapManager.getInstance(); return manager.getKeymaps(FILTER); } - private static KeymapScheme getSchemeToSelect(@NotNull List list, Keymap active) { + /** + * @param active a keymap or {@code null} if the current active keymap should be used + * @return a scheme to select according to the specified keymap + */ + private KeymapScheme getSchemeToSelect(Keymap active) { if (active == null) active = KeymapManager.getInstance().getActiveKeymap(); KeymapScheme found = null; for (KeymapScheme scheme : list) { @@ -91,6 +123,11 @@ final class KeymapSchemeManager { return found; } + /** + * @param selected a selected scheme to test + * @return {@code true} if the current list of schemes differs from the list of loaded keymaps + * @see KeymapSelector#isModified() + */ boolean isModified(KeymapScheme selected) { Keymap active = selected == null ? null : selected.getOriginal(); if (!Objects.equals(active, KeymapManager.getInstance().getActiveKeymap())) return true; @@ -103,7 +140,7 @@ final class KeymapSchemeManager { return keymaps.hasNext() || schemes.hasNext(); } - List getAll(boolean sorted) { + List getSchemes(boolean sorted) { if (sorted) list.sort(COMPARATOR); return list; } diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapSelector.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapSelector.java index 8f9e883eb3d6..cd3cc6fec0cd 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapSelector.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapSelector.java @@ -44,13 +44,19 @@ final class KeymapSelector extends SimpleSchemesPanel implements S this.consumer = consumer; } + /** + * @see KeymapPanel#reset() + */ void reset() { selectKeymap(manager.reset(), true); } + /** + * @see KeymapPanel#apply() + */ String apply() { HashSet set = new HashSet<>(); - for (KeymapScheme scheme : manager.getAll(false)) { + for (KeymapScheme scheme : manager.getSchemes(false)) { String name = scheme.getName(); if (isEmptyOrSpaces(name)) { return message("configuration.all.keymaps.should.have.non.empty.names.error.message"); @@ -64,12 +70,15 @@ final class KeymapSelector extends SimpleSchemesPanel implements S return null; } + /** + * @see KeymapPanel#isModified() + */ boolean isModified() { return manager.isModified(getSelectedScheme()); } void visitMutableKeymaps(Consumer consumer) { - for (KeymapScheme scheme : manager.getAll(false)) { + for (KeymapScheme scheme : manager.getSchemes(false)) { if (scheme.isMutable()) { consumer.accept(scheme.getMutable()); } @@ -238,7 +247,7 @@ final class KeymapSelector extends SimpleSchemesPanel implements S private void selectKeymap(KeymapScheme scheme, boolean reset) { try { internal = true; - if (reset) resetSchemes(manager.getAll(true)); + if (reset) resetSchemes(manager.getSchemes(true)); if (scheme != null) selectScheme(scheme); } finally {