diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/ShortcutsCollector.java b/platform/platform-impl/src/com/intellij/internal/statistic/ShortcutsCollector.java new file mode 100644 index 000000000000..cabfd17ed1c3 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/internal/statistic/ShortcutsCollector.java @@ -0,0 +1,102 @@ +/* + * Copyright 2000-2017 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.internal.statistic; + +import com.intellij.internal.statistic.beans.GroupDescriptor; +import com.intellij.internal.statistic.beans.UsageDescriptor; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.KeyboardShortcut; +import com.intellij.openapi.components.*; +import com.intellij.openapi.keymap.KeymapUtil; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.xmlb.annotations.MapAnnotation; +import com.intellij.util.xmlb.annotations.Tag; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * @author Konstantin Bulenkov + */ +@State( + name = "ToolbarClicksCollector", + storages = @Storage(value = "statistics.shortcuts.xml", roamingType = RoamingType.DISABLED) +) +public class ShortcutsCollector implements PersistentStateComponent { + final static class MyState { + @Tag("counts") + @MapAnnotation(surroundWithTag = false, keyAttributeName = "shortcut", valueAttributeName = "count") + public final Map myValues = new HashMap<>(); + } + private MyState myState = new MyState(); + + @NotNull + public MyState getState() { + return myState; + } + + public void loadState(final MyState state) { + myState = state; + } + + public static void record(AnActionEvent event) { + InputEvent e = event.getInputEvent(); + if (e instanceof KeyEvent) { + KeyboardShortcut shortcut = new KeyboardShortcut(KeyStroke.getKeyStrokeForEvent((KeyEvent)e), null); + String key = KeymapUtil.getShortcutText(shortcut); + ShortcutsCollector collector = getInstance(); + + if (collector == null) return; //no shortcuts stats for the IDE + + Map values = collector.getState().myValues; + values.put(key, ContainerUtil.getOrElse(values, key, 0) + 1); + } + } + + + private static ShortcutsCollector getInstance() { + return ServiceManager.getService(ShortcutsCollector.class); + } + + final static class ShortcutUsagesCollector extends UsagesCollector { + private static final GroupDescriptor GROUP = GroupDescriptor.create(getGroupName(), GroupDescriptor.HIGHER_PRIORITY); + + private static String getGroupName() { + if (SystemInfo.isMac) return "Shortcuts on Mac"; + if (SystemInfo.isWindows) return "Shortcuts on Windows"; + if (SystemInfo.isLinux) return "Shortcuts on Linux"; + return "Shortcuts on OtherOs"; + } + + @NotNull + public Set getUsages() { + MyState state = getInstance().getState(); + assert state != null; + return ContainerUtil.map2Set(state.myValues.entrySet(), e -> new UsageDescriptor(e.getKey(), e.getValue())); + } + + @NotNull + public GroupDescriptor getGroupId() { + return GROUP; + } + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java index eb72386668d9..2585c2009b33 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java @@ -19,6 +19,7 @@ import com.intellij.ide.DataManager; import com.intellij.ide.IdeEventQueue; import com.intellij.ide.ProhibitAWTEvents; import com.intellij.ide.impl.DataManagerImpl; +import com.intellij.internal.statistic.ShortcutsCollector; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.ActionManagerEx; @@ -562,6 +563,7 @@ public final class IdeKeyEventDispatcher implements Disposable { @Override public void performAction(@NotNull InputEvent e, @NotNull AnAction action, @NotNull AnActionEvent actionEvent) { e.consume(); + ShortcutsCollector.record(actionEvent); DataContext ctx = actionEvent.getDataContext(); if (action instanceof ActionGroup && !((ActionGroup)action).canBePerformed(ctx)) { diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml index 0a383fea75a1..cb4f0a6010ae 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml @@ -195,6 +195,7 @@ + @@ -375,6 +376,7 @@ +