diff --git a/source/com/intellij/featureStatistics/ApplicabilityFilter.java b/openapi/src/com/intellij/featureStatistics/ApplicabilityFilter.java similarity index 89% rename from source/com/intellij/featureStatistics/ApplicabilityFilter.java rename to openapi/src/com/intellij/featureStatistics/ApplicabilityFilter.java index 8ac6f4e26da5..54bd2a910288 100644 --- a/source/com/intellij/featureStatistics/ApplicabilityFilter.java +++ b/openapi/src/com/intellij/featureStatistics/ApplicabilityFilter.java @@ -4,4 +4,5 @@ import com.intellij.openapi.project.Project; public interface ApplicabilityFilter { boolean isApplicable(String featureId, Project project); + String getPrefix(); } \ No newline at end of file diff --git a/openapi/src/com/intellij/featureStatistics/FeatureDescriptor.java b/openapi/src/com/intellij/featureStatistics/FeatureDescriptor.java new file mode 100644 index 000000000000..d1916296b680 --- /dev/null +++ b/openapi/src/com/intellij/featureStatistics/FeatureDescriptor.java @@ -0,0 +1,203 @@ +package com.intellij.featureStatistics; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.util.ArrayUtil; +import org.jdom.Element; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +public class FeatureDescriptor{ + private String myId; + private String myGroupId; + private String myTipFileName; + private String myDisplayName; + private int myDaysBeforeFirstShowUp; + private int myDaysBetweenSuccesiveShowUps; + private Set myDependencies; + private int myMinUsageCount; + + private int myUsageCount; + private long myLastTimeShown; + private long myLastTimeUsed; + private long myAverageFrequency; + private int myShownCount; + private ProductivityFeaturesProvider myProvider; + + FeatureDescriptor(GroupDescriptor group) { + myGroupId = group.getId(); + } + + FeatureDescriptor(final String id) { + myId = id; + } + + FeatureDescriptor(String id, String tipFileName, String displayName) { + myId = id; + myTipFileName = tipFileName; + myDisplayName = displayName; + } + + public FeatureDescriptor(String id, + String groupId, + String tipFileName, + String displayName, + int daysBeforeFirstShowUp, + int daysBetweenSuccesiveShowUps, + Set dependencies, + int minUsageCount, + ProductivityFeaturesProvider provider) { + myId = id; + myGroupId = groupId; + myTipFileName = tipFileName; + myDisplayName = displayName; + myDaysBeforeFirstShowUp = daysBeforeFirstShowUp; + myDaysBetweenSuccesiveShowUps = daysBetweenSuccesiveShowUps; + myDependencies = dependencies; + myMinUsageCount = minUsageCount; + myProvider = provider; + } + + void readExternal(Element element) { + myId = element.getAttributeValue("id"); + myTipFileName = element.getAttributeValue("tip-file"); + myDisplayName = element.getAttributeValue("name"); + myDaysBeforeFirstShowUp = Integer.parseInt(element.getAttributeValue("first-show")); + myDaysBetweenSuccesiveShowUps = Integer.parseInt(element.getAttributeValue("successive-show")); + String minUsageCount = element.getAttributeValue("min-usage-count"); + myMinUsageCount = minUsageCount == null ? 1 : Integer.parseInt(minUsageCount); + List depenencies = element.getChildren("dependency"); + if (depenencies != null && depenencies.size() > 0) { + myDependencies = new HashSet(); + for (int i = 0; i < depenencies.size(); i++) { + Element dependencyElement = (Element)depenencies.get(i); + myDependencies.add(dependencyElement.getAttributeValue("id")); + } + } + } + + public String getId() { + return myId; + } + + public String getGroupId() { + return myGroupId; + } + + public String getTipFileName() { + return myTipFileName; + } + + public String getDisplayName() { + return myDisplayName; + } + + public int getUsageCount() { + return myUsageCount; + } + + public Class getProvider() { + if (myProvider == null){ + return null; + } + return myProvider.getClass(); + } + + void triggerUsed() { + long current = System.currentTimeMillis(); + myAverageFrequency *= myUsageCount; + long delta = myUsageCount > 0 ? current - Math.max(myLastTimeUsed, ApplicationManager.getApplication().getStartTime()) : 0; + myLastTimeUsed = current; + myUsageCount++; + myAverageFrequency += delta; + myAverageFrequency /= myUsageCount; + } + + public boolean isUnused() { + return myUsageCount < myMinUsageCount; + } + + public String toString() { + StringBuffer buffer = new StringBuffer(); + + buffer.append("id = ["); + buffer.append(myId); + buffer.append("], displayName = ["); + buffer.append(myDisplayName); + buffer.append("], groupId = ["); + buffer.append(myGroupId); + buffer.append("], usageCount = ["); + buffer.append(myUsageCount); + buffer.append("]"); + + return buffer.toString(); + } + + public int getDaysBeforeFirstShowUp() { + return myDaysBeforeFirstShowUp; + } + + public int getDaysBetweenSuccesiveShowUps() { + return myDaysBetweenSuccesiveShowUps; + } + + public int getMinUsageCount() { + return myMinUsageCount; + } + + public long getLastTimeShown() { + return myLastTimeShown; + } + + public String[] getDependencyFeatures() { + if (myDependencies == null) return ArrayUtil.EMPTY_STRING_ARRAY; + return myDependencies.toArray(new String[myDependencies.size()]); + } + + void triggerShown() { + myLastTimeShown = System.currentTimeMillis(); + myShownCount++; + } + + public long getLastTimeUsed() { + return myLastTimeUsed; + } + + public long getAverageFrequency() { + return myAverageFrequency; + } + + public int getShownCount() { + return myShownCount; + } + + void copyStatistics(FeatureDescriptor statistics){ + myUsageCount = statistics.getUsageCount(); + myLastTimeShown = statistics.getLastTimeShown(); + myLastTimeUsed = statistics.getLastTimeUsed(); + myAverageFrequency = statistics.getAverageFrequency(); + myShownCount = statistics.getShownCount(); + } + + void readStatistics(Element element) { + String count = element.getAttributeValue("count"); + String lastShown = element.getAttributeValue("last-shown"); + String lastUsed = element.getAttributeValue("last-used"); + String averageFrequency = element.getAttributeValue("average-frequency"); + String shownCount = element.getAttributeValue("shown-count"); + + myUsageCount = count == null ? 0 : Integer.parseInt(count); + myLastTimeShown = lastShown == null ? 0 : Long.parseLong(lastShown); + myLastTimeUsed = lastUsed == null ? 0 : Long.parseLong(lastUsed); + myAverageFrequency = averageFrequency == null ? 0 : Long.parseLong(averageFrequency); + myShownCount = shownCount == null ? 0 : Integer.parseInt(shownCount); + } + + void writeStatistics(Element element) { + element.setAttribute("count", String.valueOf(getUsageCount())); + element.setAttribute("last-shown", String.valueOf(getLastTimeShown())); + element.setAttribute("last-used", String.valueOf(getLastTimeUsed())); + element.setAttribute("average-frequency", String.valueOf(getAverageFrequency())); + element.setAttribute("shown-count", String.valueOf(getShownCount())); + } +} \ No newline at end of file diff --git a/openapi/src/com/intellij/featureStatistics/FeatureUsageTracker.java b/openapi/src/com/intellij/featureStatistics/FeatureUsageTracker.java new file mode 100644 index 000000000000..e725e193f4c6 --- /dev/null +++ b/openapi/src/com/intellij/featureStatistics/FeatureUsageTracker.java @@ -0,0 +1,20 @@ +package com.intellij.featureStatistics; + +import com.intellij.openapi.application.ApplicationManager; + +/** + * User: anna + * Date: Jan 28, 2005 + */ +public abstract class FeatureUsageTracker { + public boolean SHOW_IN_COMPILATION_PROGRESS = true; + public boolean SHOW_IN_OTHER_PROGRESS = true; + + public static FeatureUsageTracker getInstance() { + return ApplicationManager.getApplication().getComponent(FeatureUsageTracker.class); + } + + public abstract void triggerFeatureUsed(String featureId); + + public abstract void triggerFeatureShown(String featureId); +} diff --git a/source/com/intellij/featureStatistics/GroupDescriptor.java b/openapi/src/com/intellij/featureStatistics/GroupDescriptor.java similarity index 75% rename from source/com/intellij/featureStatistics/GroupDescriptor.java rename to openapi/src/com/intellij/featureStatistics/GroupDescriptor.java index c5632baabea8..b660f2c092dd 100644 --- a/source/com/intellij/featureStatistics/GroupDescriptor.java +++ b/openapi/src/com/intellij/featureStatistics/GroupDescriptor.java @@ -6,6 +6,14 @@ public class GroupDescriptor { private String myId; private String myDisplayName; + GroupDescriptor() { + } + + public GroupDescriptor(String id, String displayName) { + myId = id; + myDisplayName = displayName; + } + public void readExternal(Element element) { myId = element.getAttributeValue("id"); myDisplayName = element.getAttributeValue("name"); diff --git a/openapi/src/com/intellij/featureStatistics/ProductivityFeaturesProvider.java b/openapi/src/com/intellij/featureStatistics/ProductivityFeaturesProvider.java new file mode 100644 index 000000000000..b581a822b117 --- /dev/null +++ b/openapi/src/com/intellij/featureStatistics/ProductivityFeaturesProvider.java @@ -0,0 +1,16 @@ +package com.intellij.featureStatistics; + +import com.intellij.openapi.components.ApplicationComponent; + +/** + * User: anna + * Date: Jan 30, 2005 + */ +public abstract class ProductivityFeaturesProvider implements ApplicationComponent{ + + public abstract FeatureDescriptor[] getFeatureDescriptors(); + + public abstract GroupDescriptor[] getGroupDescriptors(); + + public abstract ApplicabilityFilter[] getApplicabilityFilters(); +} diff --git a/openapi/src/com/intellij/featureStatistics/ProductivityFeaturesRegistry.java b/openapi/src/com/intellij/featureStatistics/ProductivityFeaturesRegistry.java new file mode 100644 index 000000000000..a327f2db9cfb --- /dev/null +++ b/openapi/src/com/intellij/featureStatistics/ProductivityFeaturesRegistry.java @@ -0,0 +1,24 @@ +package com.intellij.featureStatistics; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.components.ApplicationComponent; + +import java.util.Set; + +/** + * User: anna + * Date: Feb 3, 2005 + */ +public abstract class ProductivityFeaturesRegistry implements ApplicationComponent{ + public abstract Set getFeatureIds(); + + public abstract FeatureDescriptor getFeatureDescriptor(String id); + + public abstract GroupDescriptor getGroupDescriptor(String id); + + public abstract ApplicabilityFilter[] getMatchingFilters(String featureId); + + public static ProductivityFeaturesRegistry getInstance() { + return ApplicationManager.getApplication().getComponent(ProductivityFeaturesRegistry.class); + } +} diff --git a/source/com/intellij/featureStatistics/FeatureUsageTracker.java b/source/com/intellij/featureStatistics/FeatureUsageTrackerImpl.java similarity index 86% rename from source/com/intellij/featureStatistics/FeatureUsageTracker.java rename to source/com/intellij/featureStatistics/FeatureUsageTrackerImpl.java index 516a1771ceee..a4de2b07ad69 100644 --- a/source/com/intellij/featureStatistics/FeatureUsageTracker.java +++ b/source/com/intellij/featureStatistics/FeatureUsageTrackerImpl.java @@ -19,22 +19,17 @@ import java.util.Iterator; import java.util.List; import java.util.Set; -public class FeatureUsageTracker implements ApplicationComponent, NamedJDOMExternalizable { +public class FeatureUsageTrackerImpl extends FeatureUsageTracker implements ApplicationComponent, NamedJDOMExternalizable { private static final Logger LOG = Logger.getInstance("#com.intellij.featureStatistics.FeatureUsageTracker"); private static final long DAY = 1000 * 60 * 60 * 24; private long FIRST_RUN_TIME = 0; private boolean HAVE_BEEN_SHOWN = false; - public boolean SHOW_IN_COMPILATION_PROGRESS = true; - public boolean SHOW_IN_OTHER_PROGRESS = true; + private ProductivityFeaturesRegistry myRegistry; - public static FeatureUsageTracker getInstance() { - return ApplicationManager.getApplication().getComponent(FeatureUsageTracker.class); - } - - public FeatureUsageTracker(ProgressManager progressManager, ProductivityFeaturesRegistry productivityFeaturesRegistry) { + public FeatureUsageTrackerImpl(ProgressManager progressManager, ProductivityFeaturesRegistry productivityFeaturesRegistry) { myRegistry = productivityFeaturesRegistry; progressManager.registerFunComponentProvider(new ProgressFunProvider()); } @@ -105,9 +100,13 @@ public class FeatureUsageTracker implements ApplicationComponent, NamedJDOMExter List featuresList = element.getChildren("feature"); for (int i = 0; i < featuresList.size(); i++) { Element featureElement = (Element)featuresList.get(i); - FeatureDescriptor descriptor = myRegistry.getFeatureDescriptor(featureElement.getAttributeValue("id")); + FeatureDescriptor descriptor = ((ProductivityFeaturesRegistryImpl)myRegistry).getFeatureDescriptorEx(featureElement.getAttributeValue("id")); if (descriptor != null) { descriptor.readStatistics(featureElement); + } else { + descriptor = new FeatureDescriptor(featureElement.getAttributeValue("id")); + descriptor.readStatistics(featureElement); + ((ProductivityFeaturesRegistryImpl)myRegistry).addFeatureStatistics(descriptor); } } @@ -130,7 +129,7 @@ public class FeatureUsageTracker implements ApplicationComponent, NamedJDOMExter String id = iterator.next(); Element featureElement = new Element("feature"); featureElement.setAttribute("id", id); - FeatureDescriptor descriptor = registry.getFeatureDescriptor(id); + FeatureDescriptor descriptor = (FeatureDescriptor)registry.getFeatureDescriptor(id); descriptor.writeStatistics(featureElement); element.addContent(featureElement); } @@ -142,9 +141,8 @@ public class FeatureUsageTracker implements ApplicationComponent, NamedJDOMExter } public void triggerFeatureUsed(String featureId) { - if (ApplicationManager.getApplication().isUnitTestMode()) return; ProductivityFeaturesRegistry registry = ProductivityFeaturesRegistry.getInstance(); - FeatureDescriptor descriptor = registry.getFeatureDescriptor(featureId); + FeatureDescriptor descriptor = (FeatureDescriptor)registry.getFeatureDescriptor(featureId); if (descriptor == null) { // TODO: LOG.error("Feature '" + featureId +"' must be registered prior triggerFeatureUsed() is called"); } @@ -154,7 +152,7 @@ public class FeatureUsageTracker implements ApplicationComponent, NamedJDOMExter } public void triggerFeatureShown(String featureId) { - FeatureDescriptor descriptor = ProductivityFeaturesRegistry.getInstance().getFeatureDescriptor(featureId); + FeatureDescriptor descriptor = (FeatureDescriptor)ProductivityFeaturesRegistry.getInstance().getFeatureDescriptor(featureId); if (descriptor != null) { descriptor.triggerShown(); } @@ -174,7 +172,7 @@ public class FeatureUsageTracker implements ApplicationComponent, NamedJDOMExter if (!HAVE_BEEN_SHOWN) { HAVE_BEEN_SHOWN = true; String[] newFeatures = new String[features.length + 1]; - newFeatures[0] = ProductivityFeaturesRegistry.WELCOME; + newFeatures[0] = ProductivityFeaturesRegistryImpl.WELCOME; System.arraycopy(features, 0, newFeatures, 1, features.length); features = newFeatures; } diff --git a/source/com/intellij/featureStatistics/ProductivityFeaturesRegistryImpl.java b/source/com/intellij/featureStatistics/ProductivityFeaturesRegistryImpl.java new file mode 100644 index 000000000000..551ad92f42b6 --- /dev/null +++ b/source/com/intellij/featureStatistics/ProductivityFeaturesRegistryImpl.java @@ -0,0 +1,167 @@ +package com.intellij.featureStatistics; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.InvalidDataException; +import com.intellij.openapi.util.NamedJDOMExternalizable; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.WriteExternalException; +import org.jdom.Element; + +import java.util.*; + +public class ProductivityFeaturesRegistryImpl extends ProductivityFeaturesRegistry implements NamedJDOMExternalizable { + private static final Logger LOG = Logger.getInstance("#com.intellij.featureStatistics.ProductivityFeaturesRegistry"); + private Map myFeatures = new HashMap(); + private Map myGroups = new HashMap(); + private List> myApplicabilityFilters = new ArrayList>(); + + private boolean myLoadAdditionFeatures = false; + public static final String WELCOME = "features.welcome"; + + public String getComponentName() { + return "ProductivityFeaturesRegistry"; + } + + public void initComponent() { } + + public void disposeComponent() { + } + + public String getExternalFileName() { + return "ProductivityFeaturesRegistry"; + } + + public void readExternal(Element element) throws InvalidDataException { + readGroups(element); + readFilters(element); + } + + private void lazyLoadFromPluginsFeaturesProviders() { + final ProductivityFeaturesProvider[] providers = ApplicationManager.getApplication().getComponents(ProductivityFeaturesProvider.class); + for (int i = 0; providers != null && i < providers.length; i++) { + ProductivityFeaturesProvider provider = providers[i]; + final GroupDescriptor[] groupDescriptors = provider.getGroupDescriptors(); + for (int j = 0; groupDescriptors != null && j < groupDescriptors.length; j++) { + GroupDescriptor groupDescriptor = groupDescriptors[j]; + myGroups.put(groupDescriptor.getId(), groupDescriptor); + } + final FeatureDescriptor[] featureDescriptors = provider.getFeatureDescriptors(); + for (int j = 0; featureDescriptors != null && j < featureDescriptors.length; j++) { + FeatureDescriptor featureDescriptor = (FeatureDescriptor)featureDescriptors[j]; + final FeatureDescriptor featureLoadedStatistics = myFeatures.get(featureDescriptor.getId()); + if (featureLoadedStatistics != null){ + featureDescriptor.copyStatistics(featureLoadedStatistics); + } + myFeatures.put(featureDescriptor.getId(), featureDescriptor); + } + final ApplicabilityFilter[] applicabilityFilters = provider.getApplicabilityFilters(); + for (int j = 0; applicabilityFilters != null && j < applicabilityFilters.length; j++) { + ApplicabilityFilter applicabilityFilter = applicabilityFilters[j]; + myApplicabilityFilters.add(new Pair(applicabilityFilter.getPrefix(), applicabilityFilter)); + } + } + myLoadAdditionFeatures = true; + } + + private void readFilters(Element element) { + List filters = element.getChildren("filter"); + for (int i = 0; i < filters.size(); i++) { + Element filterElement = (Element)filters.get(i); + String className = filterElement.getAttributeValue("class"); + try { + Class klass = Class.forName(className); + if (!ApplicabilityFilter.class.isAssignableFrom(klass)) { + LOG.error("filter class must implement com.intellij.featureSatistics.ApplicabilityFilter"); + continue; + } + + ApplicabilityFilter filter = (ApplicabilityFilter)klass.newInstance(); + myApplicabilityFilters.add(new Pair(filterElement.getAttributeValue("prefix"), filter)); + } + catch (Exception e) { + LOG.error("Cannot instantiate filter " + className, e); + } + } + } + + private void readGroups(Element element) { + List groups = element.getChildren("group"); + for (int i = 0; i < groups.size(); i++) { + Element groupElement = (Element)groups.get(i); + readGroup(groupElement); + } + } + + private void readGroup(Element groupElement) { + GroupDescriptor groupDescriptor = new GroupDescriptor(); + groupDescriptor.readExternal(groupElement); + String groupId = groupDescriptor.getId(); + myGroups.put(groupId, groupDescriptor); + readFeatures(groupElement, groupDescriptor); + } + + private void readFeatures(Element groupElement, GroupDescriptor groupDescriptor) { + List features = groupElement.getChildren("feature"); + for (int i = 0; i < features.size(); i++) { + Element featureElement = (Element)features.get(i); + FeatureDescriptor featureDescriptor = new FeatureDescriptor(groupDescriptor); + featureDescriptor.readExternal(featureElement); + if (!"todo.html".equals(featureDescriptor.getTipFileName())) { + myFeatures.put(featureDescriptor.getId(), featureDescriptor); + } + } + } + + public Set getFeatureIds() { + if (!myLoadAdditionFeatures){ + lazyLoadFromPluginsFeaturesProviders(); + } + return myFeatures.keySet(); + } + + public FeatureDescriptor getFeatureDescriptor(String id) { + if (WELCOME.equals(id)) { + FeatureDescriptor descriptor = new FeatureDescriptor(WELCOME, "AdaptiveWelcome.html", "Productivity Features Guide"); + return descriptor; + } + if (!myLoadAdditionFeatures){ + lazyLoadFromPluginsFeaturesProviders(); + } + return myFeatures.get(id); + } + + public FeatureDescriptor getFeatureDescriptorEx(String id) { + if (WELCOME.equals(id)) { + FeatureDescriptor descriptor = new FeatureDescriptor(WELCOME, "AdaptiveWelcome.html", "Productivity Features Guide"); + return descriptor; + } + return myFeatures.get(id); + } + + public GroupDescriptor getGroupDescriptor(String id) { + return myGroups.get(id); + } + + public ApplicabilityFilter[] getMatchingFilters(String featureId) { + if (!myLoadAdditionFeatures){ + lazyLoadFromPluginsFeaturesProviders(); + } + List filters = new ArrayList(); + for (int i = 0; i < myApplicabilityFilters.size(); i++) { + Pair pair = myApplicabilityFilters.get(i); + if (featureId.startsWith(pair.getFirst())) { + filters.add(pair.getSecond()); + } + } + return filters.toArray(new ApplicabilityFilter[filters.size()]); + } + + public void writeExternal(Element element) throws WriteExternalException { + throw new WriteExternalException(); + } + + public void addFeatureStatistics(final FeatureDescriptor descriptor) { + myFeatures.put(descriptor.getId(), descriptor); + } +} \ No newline at end of file diff --git a/source/com/intellij/featureStatistics/ui/AdaptiveTipDialog.java b/source/com/intellij/featureStatistics/ui/AdaptiveTipDialog.java index 0467ab4fa795..eb3fb09d4b4f 100644 --- a/source/com/intellij/featureStatistics/ui/AdaptiveTipDialog.java +++ b/source/com/intellij/featureStatistics/ui/AdaptiveTipDialog.java @@ -1,8 +1,6 @@ package com.intellij.featureStatistics.ui; -import com.intellij.featureStatistics.FeatureDescriptor; -import com.intellij.featureStatistics.FeatureUsageTracker; -import com.intellij.featureStatistics.ProductivityFeaturesRegistry; +import com.intellij.featureStatistics.*; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; @@ -37,7 +35,7 @@ public class AdaptiveTipDialog extends DialogWrapper { FeatureUsageTracker.getInstance().triggerFeatureShown(id); FeatureDescriptor feature = ProductivityFeaturesRegistry.getInstance().getFeatureDescriptor(id); - TipUIUtil.openTipInBrowser(feature.getTipFileName(), myBrowser); + TipUIUtil.openTipInBrowser(feature.getTipFileName(), myBrowser, feature.getProvider()); } diff --git a/source/com/intellij/featureStatistics/ui/ProgressTipPanel.java b/source/com/intellij/featureStatistics/ui/ProgressTipPanel.java index 1df76316176a..c1e29d1ac017 100644 --- a/source/com/intellij/featureStatistics/ui/ProgressTipPanel.java +++ b/source/com/intellij/featureStatistics/ui/ProgressTipPanel.java @@ -1,8 +1,6 @@ package com.intellij.featureStatistics.ui; -import com.intellij.featureStatistics.FeatureDescriptor; -import com.intellij.featureStatistics.FeatureUsageTracker; -import com.intellij.featureStatistics.ProductivityFeaturesRegistry; +import com.intellij.featureStatistics.*; import com.intellij.ide.util.PropertiesComponent; import com.intellij.ide.util.TipUIUtil; import com.intellij.openapi.application.ModalityState; @@ -144,7 +142,7 @@ public class ProgressTipPanel { FeatureDescriptor feature = ProductivityFeaturesRegistry.getInstance().getFeatureDescriptor(id); final String tipFileName = feature.getTipFileName(); - TipUIUtil.openTipInBrowser(tipFileName, myBrowser); + TipUIUtil.openTipInBrowser(tipFileName, myBrowser, feature.getProvider()); } public JComponent getComponent() { diff --git a/source/com/intellij/ide/util/TipPanel.java b/source/com/intellij/ide/util/TipPanel.java index 9e3c550fb6c2..e26bc4754287 100644 --- a/source/com/intellij/ide/util/TipPanel.java +++ b/source/com/intellij/ide/util/TipPanel.java @@ -1,9 +1,13 @@ package com.intellij.ide.util; import com.intellij.ide.GeneralSettings; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.JDOMUtil; +import com.intellij.featureStatistics.ProductivityFeaturesProvider; +import com.intellij.featureStatistics.FeatureDescriptor; import org.jdom.Document; import org.jdom.Element; @@ -16,6 +20,7 @@ import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.ArrayList; import java.util.Iterator; +import java.util.HashMap; public class TipPanel extends JPanel { private static final Logger LOG = Logger.getInstance("#com.intellij.ide.util.TipPanel"); @@ -23,8 +28,8 @@ public class TipPanel extends JPanel { private static final int DEFAULT_HEIGHT = 200; private JCheckBox myCheckBox; private JEditorPane browser; - private ArrayList myTipPaths = new ArrayList(); - + private ArrayList myTipPaths = new ArrayList(); + private HashMap> myPathsToProviderMap = new HashMap>(); public TipPanel() { setLayout(new BorderLayout()); JLabel jlabel = new JLabel(IconLoader.getIcon("/general/tip.png")); @@ -86,18 +91,18 @@ public class TipPanel extends JPanel { String path; lastTip--; if (lastTip <= 0) { - path = (String) myTipPaths.get(myTipPaths.size() - 1); + path = myTipPaths.get(myTipPaths.size() - 1); lastTip = myTipPaths.size(); } else { - path = (String) myTipPaths.get(lastTip - 1); + path = myTipPaths.get(lastTip - 1); } setTip(path, lastTip, browser, settings); } private void setTip (String path, int lastTip, JEditorPane browser, GeneralSettings settings) { - TipUIUtil.openTipInBrowser(path, browser); + TipUIUtil.openTipInBrowser(path, browser, myPathsToProviderMap.get(path)); settings.setLastTip(lastTip); } @@ -112,11 +117,11 @@ public class TipPanel extends JPanel { String path; lastTip++; if (lastTip - 1 >= myTipPaths.size()) { - path = (String) myTipPaths.get(0); + path = myTipPaths.get(0); lastTip = 1; } else { - path = (String) myTipPaths.get(lastTip - 1); + path = myTipPaths.get(lastTip - 1); } setTip(path, lastTip, browser, settings); @@ -154,5 +159,27 @@ public class TipPanel extends JPanel { Element element = (Element)iterator.next(); myTipPaths.add(element.getAttributeValue("file")); } + final ProductivityFeaturesProvider[] providers = ApplicationManager.getApplication().getComponents(ProductivityFeaturesProvider.class); + for (int i = 0; i < providers.length; i++) { + ProductivityFeaturesProvider provider = providers[i]; + final FeatureDescriptor[] featureDescriptors = provider.getFeatureDescriptors(); + for (int j = 0; featureDescriptors != null && j < featureDescriptors.length; j++) { + FeatureDescriptor featureDescriptor = featureDescriptors[j]; + myPathsToProviderMap.put(featureDescriptor.getTipFileName(), featureDescriptor.getProvider()); + } + } } + + public String getComponentName() { + return "TipPanel"; + } + + public void initComponent() { + + } + + public void disposeComponent() { + + } + } \ No newline at end of file diff --git a/source/com/intellij/ide/util/TipUIUtil.java b/source/com/intellij/ide/util/TipUIUtil.java index c140602d09c7..fd919aece578 100644 --- a/source/com/intellij/ide/util/TipUIUtil.java +++ b/source/com/intellij/ide/util/TipUIUtil.java @@ -9,6 +9,7 @@ import com.intellij.openapi.actionSystem.Shortcut; import com.intellij.openapi.keymap.KeymapManager; import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.util.SystemInfo; +import com.intellij.featureStatistics.ProductivityFeaturesProvider; import javax.swing.*; import javax.swing.text.html.HTMLDocument; @@ -22,10 +23,10 @@ import java.text.MessageFormat; /** * @author dsl */ -public class TipUIUtil { +public class TipUIUtil{ private static final String SHORTCUT_ENTITY = "&shortcut:"; - public static void openTipInBrowser(String tipPath, JEditorPane browser) { + public static void openTipInBrowser(String tipPath, JEditorPane browser, Class provider) { String fileURL = "/tips/" + tipPath; /* TODO: detect that file is not present @@ -35,7 +36,13 @@ public class TipUIUtil { } */ try { - URL url = TipUIUtil.class.getResource(fileURL); + URL url; + if (provider != null){ + url = provider.getResource(fileURL); + } else { + url = TipUIUtil.class.getResource(fileURL); + } + if (url == null) { setCantReadText(browser); return;