Browse Source

Track feature use in UDC: snippets, NewLineConsistencyCheck, ClassMemberBookmark menu.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@6298 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
pull/1/head
Daniel Grunwald 15 years ago
parent
commit
6ebd91edac
  1. 5
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs
  2. 2
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs
  3. 18
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/NewLineConsistencyCheck.cs
  4. 4
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.cs
  5. 8
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/CodeSnippet.cs
  6. 2
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/SnippetCompletionItem.cs
  7. 14
      src/Main/Base/Project/Src/Bookmarks/ClassMemberBookmark.cs
  8. 2
      src/Main/Base/Project/Src/Gui/Workbench/WpfWorkbench.cs
  9. 2
      src/Main/Base/Project/Src/Project/BuildEngine.cs
  10. 2
      src/Main/Base/Project/Src/Project/Converter/UpgradeView.xaml.cs
  11. 2
      src/Main/Base/Project/Src/Project/Converter/UpgradeViewContent.cs
  12. 18
      src/Main/Core/Project/Src/Services/AnalyticsMonitor/AnalyticsMonitorService.cs
  13. 7
      src/Main/ICSharpCode.Core.Presentation/Menu/MenuCommand.cs
  14. 18
      src/Main/ICSharpCode.Core.Presentation/Menu/MenuService.cs
  15. 4
      src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarService.cs

5
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs

@ -285,9 +285,14 @@ namespace ICSharpCode.AvalonEdit.AddIn
this.Encoding = reader.CurrentEncoding; this.Encoding = reader.CurrentEncoding;
} }
} }
// raise event which allows removing existing NewLineConsistencyCheck overlays
if (LoadedFileContent != null)
LoadedFileContent(this, EventArgs.Empty);
NewLineConsistencyCheck.StartConsistencyCheck(this); NewLineConsistencyCheck.StartConsistencyCheck(this);
} }
public event EventHandler LoadedFileContent;
public void Save(Stream stream) public void Save(Stream stream)
{ {
// don't use TextEditor.Save here because that would touch the Modified flag, // don't use TextEditor.Save here because that would touch the Modified flag,

2
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs

@ -141,6 +141,8 @@ namespace ICSharpCode.AvalonEdit.AddIn
CodeSnippet snippet = SnippetManager.Instance.FindSnippet(Path.GetExtension(editor.Adapter.FileName), CodeSnippet snippet = SnippetManager.Instance.FindSnippet(Path.GetExtension(editor.Adapter.FileName),
word); word);
if (snippet != null) { if (snippet != null) {
snippet.TrackUsage("CustomTabCommand");
editor.Adapter.Document.Remove(wordStart, editor.CaretOffset - wordStart); editor.Adapter.Document.Remove(wordStart, editor.CaretOffset - wordStart);
snippet.CreateAvalonEditSnippet(editor.Adapter).Insert(editor.TextArea); snippet.CreateAvalonEditSnippet(editor.Adapter).Insert(editor.TextArea);
return; return;

18
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/NewLineConsistencyCheck.cs

@ -115,13 +115,25 @@ namespace ICSharpCode.AvalonEdit.AddIn
}; };
editor.Children.Add(groupBox); editor.Children.Add(groupBox);
cancelButton.Click += delegate { var featureUse = AnalyticsMonitorService.TrackFeature(typeof(NewLineConsistencyCheck));
EventHandler removeWarning = null;
removeWarning = delegate {
editor.Children.Remove(groupBox); editor.Children.Remove(groupBox);
editor.PrimaryTextEditor.TextArea.Focus(); editor.PrimaryTextEditor.TextArea.Focus();
editor.LoadedFileContent -= removeWarning;
featureUse.EndTracking();
};
editor.LoadedFileContent += removeWarning;
cancelButton.Click += delegate {
AnalyticsMonitorService.TrackFeature(typeof(NewLineConsistencyCheck), "cancelButton");
removeWarning(null, null);
}; };
normalizeButton.Click += delegate { normalizeButton.Click += delegate {
editor.Children.Remove(groupBox); AnalyticsMonitorService.TrackFeature(typeof(NewLineConsistencyCheck), "normalizeButton");
editor.PrimaryTextEditor.TextArea.Focus(); removeWarning(null, null);
TextDocument document = editor.Document; TextDocument document = editor.Document;
string newNewLine = (unix.IsChecked == true) ? "\n" : "\r\n"; string newNewLine = (unix.IsChecked == true) ? "\n" : "\r\n";

4
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.cs

@ -9,7 +9,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Media; using System.Windows.Media;
using ICSharpCode.Core;
using ICSharpCode.NRefactory; using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.SharpDevelop.Dom;
@ -242,6 +242,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
} }
memberItems.Sort(); memberItems.Sort();
if (jumpOnSelectionChange) { if (jumpOnSelectionChange) {
AnalyticsMonitorService.TrackFeature(GetType(), "JumpToClass");
JumpTo(item, selectedClass.Region); JumpTo(item, selectedClass.Region);
} }
} }
@ -260,6 +261,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
if (item != null) { if (item != null) {
IMember member = item.Entity as IMember; IMember member = item.Entity as IMember;
if (member != null && jumpOnSelectionChange) { if (member != null && jumpOnSelectionChange) {
AnalyticsMonitorService.TrackFeature(GetType(), "JumpToMember");
JumpTo(item, member.Region); JumpTo(item, member.Region);
} }
} }

8
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/CodeSnippet.cs

@ -240,5 +240,13 @@ namespace ICSharpCode.AvalonEdit.AddIn.Snippets
return function(input); return function(input);
} }
} }
/// <summary>
/// Reports the snippet usage to UDC
/// </summary>
internal void TrackUsage(string activationMethod)
{
Core.AnalyticsMonitorService.TrackFeature(typeof(CodeSnippet), IsUserModified ? "usersnippet" : Name, activationMethod);
}
} }
} }

2
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/SnippetCompletionItem.cs

@ -74,6 +74,8 @@ namespace ICSharpCode.AvalonEdit.AddIn.Snippets
using (context.Editor.Document.OpenUndoGroup()) { using (context.Editor.Document.OpenUndoGroup()) {
if (context.CompletionChar == '\t' || AlwaysInsertSnippet) { if (context.CompletionChar == '\t' || AlwaysInsertSnippet) {
codeSnippet.TrackUsage("SnippetCompletionItem");
context.Editor.Document.Remove(context.StartOffset, context.Length); context.Editor.Document.Remove(context.StartOffset, context.Length);
CreateSnippet().Insert(textArea); CreateSnippet().Insert(textArea);
} else { } else {

14
src/Main/Base/Project/Src/Bookmarks/ClassMemberBookmark.cs

@ -8,7 +8,7 @@
using System; using System;
using System.Windows; using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using ICSharpCode.Core;
using ICSharpCode.Core.Presentation; using ICSharpCode.Core.Presentation;
using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.SharpDevelop.Dom;
@ -36,7 +36,7 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
public const string ContextMenuPath = "/SharpDevelop/ViewContent/DefaultTextEditor/ClassMemberContextMenu"; public const string ContextMenuPath = "/SharpDevelop/ViewContent/DefaultTextEditor/ClassMemberContextMenu";
public virtual IImage Image { public virtual IImage Image {
get { return ClassBrowserIconService.GetIcon(member); } get { return ClassBrowserIconService.GetIcon(member); }
} }
@ -47,7 +47,9 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
public virtual void MouseDown(MouseButtonEventArgs e) public virtual void MouseDown(MouseButtonEventArgs e)
{ {
if (e.ChangedButton == MouseButton.Left) { if (e.ChangedButton == MouseButton.Left) {
MenuService.ShowContextMenu(e.Source as UIElement, this, ContextMenuPath); var f = AnalyticsMonitorService.TrackFeature("ICSharpCode.SharpDevelop.Bookmarks.ClassMemberBookmark.ShowContextMenu");
var ctx = MenuService.ShowContextMenu(e.Source as UIElement, this, ContextMenuPath);
ctx.Closed += delegate { f.EndTracking(); };
e.Handled = true; e.Handled = true;
} }
} }
@ -73,7 +75,7 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
public const string ContextMenuPath = "/SharpDevelop/ViewContent/DefaultTextEditor/ClassBookmarkContextMenu"; public const string ContextMenuPath = "/SharpDevelop/ViewContent/DefaultTextEditor/ClassBookmarkContextMenu";
public virtual IImage Image { public virtual IImage Image {
get { get {
return ClassBrowserIconService.GetIcon(@class); return ClassBrowserIconService.GetIcon(@class);
} }
@ -86,7 +88,9 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
public virtual void MouseDown(MouseButtonEventArgs e) public virtual void MouseDown(MouseButtonEventArgs e)
{ {
if (e.ChangedButton == MouseButton.Left) { if (e.ChangedButton == MouseButton.Left) {
MenuService.ShowContextMenu(e.Source as UIElement, this, ContextMenuPath); var f = AnalyticsMonitorService.TrackFeature("ICSharpCode.SharpDevelop.Bookmarks.ClassBookmark.ShowContextMenu");
var ctx = MenuService.ShowContextMenu(e.Source as UIElement, this, ContextMenuPath);
ctx.Closed += delegate { f.EndTracking(); };
e.Handled = true; e.Handled = true;
} }
} }

2
src/Main/Base/Project/Src/Gui/Workbench/WpfWorkbench.cs

@ -95,7 +95,7 @@ namespace ICSharpCode.SharpDevelop.Gui
} }
} }
mainMenu.ItemsSource = MenuService.CreateMenuItems(this, this, mainMenuPath); mainMenu.ItemsSource = MenuService.CreateMenuItems(this, this, mainMenuPath, "MainMenu");
toolBars = ToolBarService.CreateToolBars(this, "/SharpDevelop/Workbench/ToolBar"); toolBars = ToolBarService.CreateToolBars(this, "/SharpDevelop/Workbench/ToolBar");
foreach (ToolBar tb in toolBars) { foreach (ToolBar tb in toolBars) {

2
src/Main/Base/Project/Src/Project/BuildEngine.cs

@ -55,7 +55,7 @@ namespace ICSharpCode.SharpDevelop.Project
} else { } else {
guiBuildCancellation = new CancellationTokenSource(); guiBuildCancellation = new CancellationTokenSource();
IProgressMonitor progressMonitor = WorkbenchSingleton.StatusBar.CreateProgressMonitor(guiBuildCancellation.Token); IProgressMonitor progressMonitor = WorkbenchSingleton.StatusBar.CreateProgressMonitor(guiBuildCancellation.Token);
guiBuildTrackedFeature = AnalyticsMonitorService.TrackFeature("Build"); guiBuildTrackedFeature = AnalyticsMonitorService.TrackFeature("ICSharpCode.SharpDevelop.Project.BuildEngine.Build");
WorkbenchSingleton.StatusBar.SetMessage(StringParser.Parse("${res:MainWindow.CompilerMessages.BuildVerb}...")); WorkbenchSingleton.StatusBar.SetMessage(StringParser.Parse("${res:MainWindow.CompilerMessages.BuildVerb}..."));
ProjectService.RaiseEventBuildStarted(new BuildEventArgs(project, options)); ProjectService.RaiseEventBuildStarted(new BuildEventArgs(project, options));
StartBuild(project, options, StartBuild(project, options,

2
src/Main/Base/Project/Src/Project/Converter/UpgradeView.xaml.cs

@ -209,7 +209,7 @@ namespace ICSharpCode.SharpDevelop.Project.Converter
void convertButton_Click(object sender, RoutedEventArgs e) void convertButton_Click(object sender, RoutedEventArgs e)
{ {
Core.AnalyticsMonitorService.TrackFeature("UpgradeView.convertButton_Click"); Core.AnalyticsMonitorService.TrackFeature(GetType(), "convertButton_Click");
CompilerVersion selectedCompiler = newVersionComboBox.SelectedValue as CompilerVersion; CompilerVersion selectedCompiler = newVersionComboBox.SelectedValue as CompilerVersion;
TargetFramework selectedFramework = newFrameworkComboBox.SelectedValue as TargetFramework; TargetFramework selectedFramework = newFrameworkComboBox.SelectedValue as TargetFramework;

2
src/Main/Base/Project/Src/Project/Converter/UpgradeViewContent.cs

@ -21,7 +21,7 @@ namespace ICSharpCode.SharpDevelop.Project.Converter
{ {
var projects = solution.Projects.OfType<IUpgradableProject>().ToList(); var projects = solution.Projects.OfType<IUpgradableProject>().ToList();
if (projects.Count > 0 && projects.All(u => u.UpgradeDesired)) { if (projects.Count > 0 && projects.All(u => u.UpgradeDesired)) {
Core.AnalyticsMonitorService.TrackFeature("UpgradeView opened automatically"); Core.AnalyticsMonitorService.TrackFeature(typeof(UpgradeView), "opened automatically");
WorkbenchSingleton.Workbench.ShowView(new UpgradeViewContent(solution)); WorkbenchSingleton.Workbench.ShowView(new UpgradeViewContent(solution));
} }
} }

18
src/Main/Core/Project/Src/Services/AnalyticsMonitor/AnalyticsMonitorService.cs

@ -80,5 +80,23 @@ namespace ICSharpCode.Core
{ {
} }
} }
/// <summary>
/// Tracks a feature use.
/// </summary>
/// <param name="featureClass">Class containing the feature</param>
/// <param name="featureName">Name of the feature</param>
/// <param name="activationMethod">Method used to 'activate' the feature (e.g. Menu, Toolbar, Shortcut, etc.)</param>
/// <returns>Object that can be used to 'end' the feature use, if measuring time spans is desired.</returns>
public static IAnalyticsMonitorTrackedFeature TrackFeature(Type featureClass, string featureName = null, string activationMethod = null)
{
if (featureClass == null)
throw new ArgumentNullException("featureClass");
if (featureName != null)
return TrackFeature(featureClass.FullName + "/" + featureName, activationMethod);
else
return TrackFeature(featureClass.FullName, activationMethod);
}
} }
} }

7
src/Main/ICSharpCode.Core.Presentation/Menu/MenuCommand.cs

@ -123,8 +123,11 @@ namespace ICSharpCode.Core.Presentation
class MenuCommand : CoreMenuItem class MenuCommand : CoreMenuItem
{ {
public MenuCommand(UIElement inputBindingOwner, Codon codon, object caller, bool createCommand) : base(codon, caller) readonly string ActivationMethod;
public MenuCommand(UIElement inputBindingOwner, Codon codon, object caller, bool createCommand, string activationMethod) : base(codon, caller)
{ {
this.ActivationMethod = activationMethod;
this.Command = CommandWrapper.GetCommand(codon, caller, createCommand); this.Command = CommandWrapper.GetCommand(codon, caller, createCommand);
if (!string.IsNullOrEmpty(codon.Properties["shortcut"])) { if (!string.IsNullOrEmpty(codon.Properties["shortcut"])) {
KeyGesture kg = MenuService.ParseShortcut(codon.Properties["shortcut"]); KeyGesture kg = MenuService.ParseShortcut(codon.Properties["shortcut"]);
@ -154,7 +157,7 @@ namespace ICSharpCode.Core.Presentation
base.OnClick(); base.OnClick();
string feature = GetFeatureName(); string feature = GetFeatureName();
if (!string.IsNullOrEmpty(feature)) { if (!string.IsNullOrEmpty(feature)) {
AnalyticsMonitorService.TrackFeature(feature, "Menu"); AnalyticsMonitorService.TrackFeature(feature, ActivationMethod);
} }
} }

18
src/Main/ICSharpCode.Core.Presentation/Menu/MenuService.cs

@ -106,14 +106,14 @@ namespace ICSharpCode.Core.Presentation
public static ContextMenu CreateContextMenu(object owner, string addInTreePath) public static ContextMenu CreateContextMenu(object owner, string addInTreePath)
{ {
IList items = CreateUnexpandedMenuItems(null, AddInTree.BuildItems<MenuItemDescriptor>(addInTreePath, owner, false)); IList items = CreateUnexpandedMenuItems(null, AddInTree.BuildItems<MenuItemDescriptor>(addInTreePath, owner, false), "ContextMenu");
return CreateContextMenu(items); return CreateContextMenu(items);
} }
public static ContextMenu ShowContextMenu(UIElement parent, object owner, string addInTreePath) public static ContextMenu ShowContextMenu(UIElement parent, object owner, string addInTreePath)
{ {
ContextMenu menu = new ContextMenu(); ContextMenu menu = new ContextMenu();
menu.ItemsSource = CreateMenuItems(menu, owner, addInTreePath); menu.ItemsSource = CreateMenuItems(menu, owner, addInTreePath, "ContextMenu");
menu.PlacementTarget = parent; menu.PlacementTarget = parent;
menu.IsOpen = true; menu.IsOpen = true;
return menu; return menu;
@ -131,9 +131,9 @@ namespace ICSharpCode.Core.Presentation
return contextMenu; return contextMenu;
} }
public static IList CreateMenuItems(UIElement inputBindingOwner, object owner, string addInTreePath) public static IList CreateMenuItems(UIElement inputBindingOwner, object owner, string addInTreePath, string activationMethod = null)
{ {
IList items = CreateUnexpandedMenuItems(inputBindingOwner, AddInTree.BuildItems<MenuItemDescriptor>(addInTreePath, owner, false)); IList items = CreateUnexpandedMenuItems(inputBindingOwner, AddInTree.BuildItems<MenuItemDescriptor>(addInTreePath, owner, false), activationMethod);
return ExpandMenuBuilders(items, false); return ExpandMenuBuilders(items, false);
} }
@ -156,12 +156,12 @@ namespace ICSharpCode.Core.Presentation
} }
} }
internal static IList CreateUnexpandedMenuItems(UIElement inputBindingOwner, IEnumerable descriptors) internal static IList CreateUnexpandedMenuItems(UIElement inputBindingOwner, IEnumerable descriptors, string activationMethod)
{ {
ArrayList result = new ArrayList(); ArrayList result = new ArrayList();
if (descriptors != null) { if (descriptors != null) {
foreach (MenuItemDescriptor descriptor in descriptors) { foreach (MenuItemDescriptor descriptor in descriptors) {
result.Add(CreateMenuItemFromDescriptor(inputBindingOwner, descriptor)); result.Add(CreateMenuItemFromDescriptor(inputBindingOwner, descriptor, activationMethod));
} }
} }
return result; return result;
@ -191,7 +191,7 @@ namespace ICSharpCode.Core.Presentation
return result; return result;
} }
static object CreateMenuItemFromDescriptor(UIElement inputBindingOwner, MenuItemDescriptor descriptor) static object CreateMenuItemFromDescriptor(UIElement inputBindingOwner, MenuItemDescriptor descriptor, string activationMethod)
{ {
Codon codon = descriptor.Codon; Codon codon = descriptor.Codon;
string type = codon.Properties.Contains("type") ? codon.Properties["type"] : "Command"; string type = codon.Properties.Contains("type") ? codon.Properties["type"] : "Command";
@ -205,13 +205,13 @@ namespace ICSharpCode.Core.Presentation
//return new MenuCheckBox(codon, descriptor.Caller); //return new MenuCheckBox(codon, descriptor.Caller);
case "Item": case "Item":
case "Command": case "Command":
return new MenuCommand(inputBindingOwner, codon, descriptor.Caller, createCommand); return new MenuCommand(inputBindingOwner, codon, descriptor.Caller, createCommand, activationMethod);
case "Menu": case "Menu":
var item = new CoreMenuItem(codon, descriptor.Caller) { var item = new CoreMenuItem(codon, descriptor.Caller) {
ItemsSource = new object[1], ItemsSource = new object[1],
SetEnabled = true SetEnabled = true
}; };
var subItems = CreateUnexpandedMenuItems(inputBindingOwner, descriptor.SubItems); var subItems = CreateUnexpandedMenuItems(inputBindingOwner, descriptor.SubItems, activationMethod);
item.SubmenuOpened += (sender, args) => { item.SubmenuOpened += (sender, args) => {
item.ItemsSource = ExpandMenuBuilders(subItems, true); item.ItemsSource = ExpandMenuBuilders(subItems, true);
args.Handled = true; args.Handled = true;

4
src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarService.cs

@ -72,9 +72,9 @@ namespace ICSharpCode.Core.Presentation
return "Label"; return "Label";
//return new ToolBarLabel(codon, caller); //return new ToolBarLabel(codon, caller);
case "DropDownButton": case "DropDownButton":
return new ToolBarDropDownButton(codon, caller, MenuService.CreateUnexpandedMenuItems(null, descriptor.SubItems)); return new ToolBarDropDownButton(codon, caller, MenuService.CreateUnexpandedMenuItems(null, descriptor.SubItems, "ToolbarDropDownMenu"));
case "SplitButton": case "SplitButton":
return new ToolBarSplitButton(codon, caller, MenuService.CreateUnexpandedMenuItems(null, descriptor.SubItems)); return new ToolBarSplitButton(codon, caller, MenuService.CreateUnexpandedMenuItems(null, descriptor.SubItems, "ToolbarDropDownMenu"));
case "Builder": case "Builder":
return codon.AddIn.CreateObject(codon.Properties["class"]); return codon.AddIn.CreateObject(codon.Properties["class"]);
default: default:

Loading…
Cancel
Save