Browse Source

Allow shortcuts and categories at root level in ShortcutManagement add-in. Also allow multiple levels of sub-categories.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/shortcuts@4277 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts^2
Sergej Andrejev 16 years ago
parent
commit
11471cd275
  1. BIN
      src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement.suo
  2. 1
      src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/ShortcutsManagement.csproj
  3. 18
      src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/AddIn.cs
  4. 24
      src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/IShortcutTreeEntry.cs
  5. 13
      src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/KeyGestureTemplate.cs
  6. 39
      src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/Shortcut.cs
  7. 21
      src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/ShortcutCategory.cs
  8. 118
      src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/ShortcutsFinder.cs
  9. 28
      src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/Resources.xaml
  10. 28
      src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/ShortcutManagementWindow.xaml.cs
  11. 101
      src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/ShortcutsManagementOptionsPanel.xaml.cs
  12. 2
      src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/ShortcutsTreeView.xaml
  13. 61
      src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/ShortcutsTreeView.xaml.cs

BIN
src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement.suo

Binary file not shown.

1
src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/ShortcutsManagement.csproj

@ -142,6 +142,7 @@
<DependentUpon>Settings.settings</DependentUpon> <DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput> <DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile> </Compile>
<Compile Include="Src\Data\IShortcutTreeEntry.cs" />
<Compile Include="Src\Data\KeyGestureTemplate.cs" /> <Compile Include="Src\Data\KeyGestureTemplate.cs" />
<Compile Include="Src\Data\Shortcut.cs" /> <Compile Include="Src\Data\Shortcut.cs" />
<Compile Include="Src\Data\ShortcutCategory.cs" /> <Compile Include="Src\Data\ShortcutCategory.cs" />

18
src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/AddIn.cs

@ -7,7 +7,7 @@ namespace ICSharpCode.ShortcutsManagement.Data
/// <summary> /// <summary>
/// Add-in where shortcuts were registered /// Add-in where shortcuts were registered
/// </summary> /// </summary>
public class AddIn : INotifyPropertyChanged, ICloneable public class AddIn : INotifyPropertyChanged, IShortcutTreeEntry
{ {
private string name; private string name;
@ -26,7 +26,7 @@ namespace ICSharpCode.ShortcutsManagement.Data
{ {
if (name != value) { if (name != value) {
name = value; name = value;
InvokePropertyChanged("Text"); InvokePropertyChanged("Name");
} }
} }
} }
@ -76,7 +76,7 @@ namespace ICSharpCode.ShortcutsManagement.Data
/// <summary> /// <summary>
/// Invoke dependency property changed event /// Invoke dependency property changed event
/// </summary> /// </summary>
/// <param name="propertyName">Text of dependency property from this classs</param> /// <param name="propertyName">Name of dependency property from this classs</param>
private void InvokePropertyChanged(string propertyName) private void InvokePropertyChanged(string propertyName)
{ {
if (PropertyChanged != null) { if (PropertyChanged != null) {
@ -115,12 +115,12 @@ namespace ICSharpCode.ShortcutsManagement.Data
return clonedAddIn; return clonedAddIn;
} }
public void SortEntries() public void SortSubEntries()
{ {
Categories.Sort((a, b) => a.Name.CompareTo(b.Name)); Categories.Sort((a, b) => a.Name.CompareTo(b.Name));
foreach (var category in Categories) foreach (var category in Categories)
{ {
category.SortEntries(); category.SortSubEntries();
} }
} }
@ -128,5 +128,13 @@ namespace ICSharpCode.ShortcutsManagement.Data
/// Notify observers about property changes /// Notify observers about property changes
/// </summary> /// </summary>
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;
public int CompareTo(object obj) {
if (obj is ShortcutCategory) return 1;
if (obj is Shortcut) return 1;
var addInObj = (AddIn)obj;
return Name.CompareTo(addInObj.Name);
}
} }
} }

24
src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/IShortcutTreeEntry.cs

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ICSharpCode.ShortcutsManagement.Data
{
public interface IShortcutTreeEntry : IComparable, ICloneable
{
string Name
{
get; set;
}
bool IsVisible
{
get; set;
}
void SortSubEntries();
Shortcut FindShortcut(string shortcutId);
}
}

13
src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/KeyGestureTemplate.cs

@ -108,6 +108,19 @@ namespace ICSharpCode.ShortcutsManagement.Data
return modifierMatches && keyMatches; return modifierMatches && keyMatches;
} }
public bool MatchesCollection(InputGestureCollection gestures, bool strictMatch)
{
foreach (InputGesture gesture in gestures)
{
if(gesture is KeyGesture && Matches((KeyGesture)gesture, strictMatch))
{
return true;
}
}
return false;
}
/// <summary> /// <summary>
/// Returns string that represents <see cref="KeyGestureTemplate"/> /// Returns string that represents <see cref="KeyGestureTemplate"/>
/// </summary> /// </summary>

39
src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/Shortcut.cs

@ -9,7 +9,7 @@ namespace ICSharpCode.ShortcutsManagement.Data
/// <summary> /// <summary>
/// Shortcut /// Shortcut
/// </summary> /// </summary>
public class Shortcut : INotifyPropertyChanged, ICloneable public class Shortcut : INotifyPropertyChanged, IShortcutTreeEntry
{ {
/// <summary> /// <summary>
/// List of input gestures which will invoke this action /// List of input gestures which will invoke this action
@ -21,27 +21,32 @@ namespace ICSharpCode.ShortcutsManagement.Data
} }
private string _text; private string _name;
/// <summary> /// <summary>
/// Shortcut action name (displayed to user) /// Shortcut action name (displayed to user)
/// </summary> /// </summary>
public string Text public string Name
{ {
get get
{ {
return _text; return _name;
} }
set set
{ {
if(_text != value) if(_name != value)
{ {
_text = value; _name = value;
InvokePropertyChanged("Text"); InvokePropertyChanged("Name");
} }
} }
} }
public void SortSubEntries()
{
}
/// <summary> /// <summary>
/// Shortcut Id. /// Shortcut Id.
/// ///
@ -83,7 +88,7 @@ namespace ICSharpCode.ShortcutsManagement.Data
{ {
IsVisible = true; IsVisible = true;
Id = Guid.NewGuid().ToString(); Id = Guid.NewGuid().ToString();
Text = shortcutText; Name = shortcutText;
Gestures = new ObservableCollection<InputGesture>(); Gestures = new ObservableCollection<InputGesture>();
if(gestures != null) { if(gestures != null) {
@ -127,7 +132,7 @@ namespace ICSharpCode.ShortcutsManagement.Data
/// <returns>Deep copy of action</returns> /// <returns>Deep copy of action</returns>
public object Clone() public object Clone()
{ {
var clone = new Shortcut(Text, null); var clone = new Shortcut(Name, null);
clone.Id = Id; clone.Id = Id;
foreach (var gesture in Gestures) { foreach (var gesture in Gestures) {
@ -140,7 +145,7 @@ namespace ICSharpCode.ShortcutsManagement.Data
/// <summary> /// <summary>
/// Invoke dependency property changed event /// Invoke dependency property changed event
/// </summary> /// </summary>
/// <param name="propertyName">Text of dependency property from this classs</param> /// <param name="propertyName">Name of dependency property from this classs</param>
private void InvokePropertyChanged(string propertyName) private void InvokePropertyChanged(string propertyName)
{ {
if (PropertyChanged != null) if (PropertyChanged != null)
@ -153,5 +158,19 @@ namespace ICSharpCode.ShortcutsManagement.Data
/// Notify observers about property changes /// Notify observers about property changes
/// </summary> /// </summary>
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;
public int CompareTo(object obj)
{
if (obj is AddIn) return -1;
if (obj is ShortcutCategory) return -1;
var shortcutObj = (Shortcut)obj;
return Name.CompareTo(shortcutObj.Name);
}
public Shortcut FindShortcut(string shortcutId) {
return Id == shortcutId ? this : null;
}
} }
} }

21
src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/ShortcutCategory.cs

@ -7,7 +7,7 @@ namespace ICSharpCode.ShortcutsManagement.Data
/// <summary> /// <summary>
/// Shortcut category /// Shortcut category
/// </summary> /// </summary>
public class ShortcutCategory : INotifyPropertyChanged, ICloneable public class ShortcutCategory : INotifyPropertyChanged, IShortcutTreeEntry
{ {
private string name; private string name;
@ -27,7 +27,7 @@ namespace ICSharpCode.ShortcutsManagement.Data
if (name != value) if (name != value)
{ {
name = value; name = value;
InvokePropertyChanged("Text"); InvokePropertyChanged("Name");
} }
} }
} }
@ -103,14 +103,14 @@ namespace ICSharpCode.ShortcutsManagement.Data
return clonedCategory; return clonedCategory;
} }
public void SortEntries() public void SortSubEntries()
{ {
SubCategories.Sort((a, b) => a.Name.CompareTo(b.Name)); SubCategories.Sort((a, b) => a.Name.CompareTo(b.Name));
Shortcuts.Sort((a, b) => a.Text.CompareTo(b.Text)); Shortcuts.Sort((a, b) => a.Name.CompareTo(b.Name));
foreach (var category in SubCategories) foreach (var category in SubCategories)
{ {
category.SortEntries(); category.SortSubEntries();
} }
} }
@ -142,7 +142,7 @@ namespace ICSharpCode.ShortcutsManagement.Data
/// <summary> /// <summary>
/// Invoke dependency property changed event /// Invoke dependency property changed event
/// </summary> /// </summary>
/// <param name="propertyName">Text of dependency property from this classs</param> /// <param name="propertyName">Name of dependency property from this classs</param>
private void InvokePropertyChanged(string propertyName) private void InvokePropertyChanged(string propertyName)
{ {
if (PropertyChanged != null) { if (PropertyChanged != null) {
@ -154,5 +154,14 @@ namespace ICSharpCode.ShortcutsManagement.Data
/// Notify observers about property changes /// Notify observers about property changes
/// </summary> /// </summary>
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;
public int CompareTo(object obj)
{
if (obj is AddIn) return -1;
if (obj is Shortcut) return 1;
var categoryObj = (ShortcutCategory)obj;
return Name.CompareTo(categoryObj.Name);
}
} }
} }

118
src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Data/ShortcutsFinder.cs

@ -12,7 +12,7 @@ namespace ICSharpCode.ShortcutsManagement.Data
/// <summary> /// <summary>
/// Collection of add-ins containing shortcuts and shortcut categories /// Collection of add-ins containing shortcuts and shortcut categories
/// </summary> /// </summary>
public ICollection<AddIn> AddIns public ICollection<IShortcutTreeEntry> RootEntries
{ {
get; set; get; set;
} }
@ -20,9 +20,9 @@ namespace ICSharpCode.ShortcutsManagement.Data
/// <summary> /// <summary>
/// Create new instance of <see cref="ShortcutsFinder"/> /// Create new instance of <see cref="ShortcutsFinder"/>
/// </summary> /// </summary>
/// <param name="addIns"></param> /// <param name="rootEntries"></param>
public ShortcutsFinder(ICollection<AddIn> addIns) { public ShortcutsFinder(ICollection<IShortcutTreeEntry> rootEntries) {
AddIns = addIns; RootEntries = rootEntries;
} }
/// <summary> /// <summary>
@ -34,16 +34,30 @@ namespace ICSharpCode.ShortcutsManagement.Data
/// <param name="shortcut">Shortcut to be heden</param> /// <param name="shortcut">Shortcut to be heden</param>
public void HideShortcut(Shortcut shortcut) public void HideShortcut(Shortcut shortcut)
{ {
foreach (var addIn in AddIns) { foreach (var entry in RootEntries) {
var subCategoryIsVisible = false; var subCategoryIsVisible = false;
foreach (var category in addIn.Categories) {
if (HideShortcut(category, shortcut)) { var rootAddIn = entry as AddIn;
subCategoryIsVisible = true; if (rootAddIn != null) {
foreach (var category in rootAddIn.Categories) {
if (HideShortcut(category, shortcut)) {
subCategoryIsVisible = true;
}
} }
// Hide add-in if it doesn't have any visible sub-elements
rootAddIn.IsVisible = subCategoryIsVisible;
}
var rootCategory = entry as ShortcutCategory;
if(rootCategory != null) {
HideShortcut(rootCategory, shortcut);
} }
// Hide add-in if it doesn't have any visible sub-elements var rootShortcut = entry as Shortcut;
addIn.IsVisible = subCategoryIsVisible; if (rootShortcut != null) {
shortcut.IsVisible = false;
}
} }
} }
@ -96,16 +110,38 @@ namespace ICSharpCode.ShortcutsManagement.Data
/// <param name="strictMatch">If false filter gestures which with only partial match</param> /// <param name="strictMatch">If false filter gestures which with only partial match</param>
public void FilterGesture(ICollection<KeyGestureTemplate> keyGestureTemplateCollection, bool strictMatch) public void FilterGesture(ICollection<KeyGestureTemplate> keyGestureTemplateCollection, bool strictMatch)
{ {
foreach (var addIn in AddIns) { foreach (var entry in RootEntries)
{
var subCategoryIsVisible = false; var subCategoryIsVisible = false;
foreach (var category in addIn.Categories) {
if (FilterGesture(category, keyGestureTemplateCollection, strictMatch)) { var rootAddIn = entry as AddIn;
subCategoryIsVisible = true; if (rootAddIn != null)
{
foreach (var category in rootAddIn.Categories) {
if (FilterGesture(category, keyGestureTemplateCollection, strictMatch)) {
subCategoryIsVisible = true;
}
} }
// Hide add-in if it doesn't have any visible sub-elements
rootAddIn.IsVisible = subCategoryIsVisible;
}
var rootCategory = entry as ShortcutCategory;
if (rootCategory != null) {
FilterGesture(rootCategory, keyGestureTemplateCollection, strictMatch);
} }
// Hide add-in if it doesn't have any visible sub-elements var rootShortcut = entry as Shortcut;
addIn.IsVisible = subCategoryIsVisible; if (rootShortcut != null) {
rootShortcut.IsVisible = false;
foreach (var template in keyGestureTemplateCollection) {
if (template.MatchesCollection(new InputGestureCollection(rootShortcut.Gestures), strictMatch)) {
rootShortcut.IsVisible = true;
break;
}
}
}
} }
} }
@ -128,13 +164,11 @@ namespace ICSharpCode.ShortcutsManagement.Data
// Apply filter to shortcuts // Apply filter to shortcuts
foreach (var shortcut in category.Shortcuts) { foreach (var shortcut in category.Shortcuts) {
var gestureMatched = false; var gestureMatched = false;
foreach (InputGesture gesture in shortcut.Gestures) { foreach (var template in keyGestureTemplateCollection) {
foreach (var template in keyGestureTemplateCollection) { if (template.MatchesCollection(new InputGestureCollection(shortcut.Gestures), strictMatch)) {
if (template == null || (gesture is KeyGesture && template.Matches((KeyGesture)gesture, strictMatch))) { gestureMatched = true;
gestureMatched = true; break;
break; }
}
}
} }
if (gestureMatched) { if (gestureMatched) {
@ -160,21 +194,35 @@ namespace ICSharpCode.ShortcutsManagement.Data
/// <param name="filterString">Filter string</param> /// <param name="filterString">Filter string</param>
public void Filter(string filterString) public void Filter(string filterString)
{ {
foreach (var addIn in AddIns) { foreach (var entry in RootEntries) {
// If add-in name matches filter string show all sub-elements var rootAddIn = entry as AddIn;
var addInNameContainsFilterString = !string.IsNullOrEmpty(filterString) && addIn.Name.IndexOf(filterString, StringComparison.InvariantCultureIgnoreCase) >= 0; if (rootAddIn != null) {
// If add-in name matches filter string show all sub-elements
var addInNameContainsFilterString = !string.IsNullOrEmpty(filterString) && rootAddIn.Name.IndexOf(filterString, StringComparison.InvariantCultureIgnoreCase) >= 0;
// Apply filter to categories // Apply filter to categories
var subCategoryIsVisible = false; var subCategoryIsVisible = false;
foreach (var category in addIn.Categories) {
if(Filter(category, filterString, addInNameContainsFilterString ? (bool?) true : null)) { foreach (var category in rootAddIn.Categories) {
subCategoryIsVisible = true; if (Filter(category, filterString, addInNameContainsFilterString ? (bool?) true : null)) {
subCategoryIsVisible = true;
}
} }
// If last category in add-in was hidden and addin name does not contain
// part of the filter then hide add-in
rootAddIn.IsVisible = addInNameContainsFilterString || subCategoryIsVisible;
} }
// If last category in add-in was hidden and addin name does not contain var rootCategory = entry as ShortcutCategory;
// part of the filter then hide add-in if (rootCategory != null) {
addIn.IsVisible = addInNameContainsFilterString || subCategoryIsVisible; Filter(rootCategory, filterString, null);
}
var rootShortcut = entry as Shortcut;
if (rootShortcut != null) {
rootShortcut.IsVisible = rootShortcut.Name.IndexOf(filterString, StringComparison.InvariantCultureIgnoreCase) >= 0;
}
} }
} }
@ -204,7 +252,7 @@ namespace ICSharpCode.ShortcutsManagement.Data
// Filter shortcuts which text match the filter // Filter shortcuts which text match the filter
foreach (var shortcut in category.Shortcuts) { foreach (var shortcut in category.Shortcuts) {
if ((forseMatch.HasValue && forseMatch.Value) || shortcut.Text.IndexOf(filterString, StringComparison.InvariantCultureIgnoreCase) >= 0) { if ((forseMatch.HasValue && forseMatch.Value) || shortcut.Name.IndexOf(filterString, StringComparison.InvariantCultureIgnoreCase) >= 0) {
shortcut.IsVisible = true; shortcut.IsVisible = true;
isSubElementVisible = true; isSubElementVisible = true;
} }

28
src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/Resources.xaml

@ -4,9 +4,10 @@
<Converters:GesturesListConverter x:Key="GesturesListConverter" />
<Converters:ShortcutCategorySubElementsMergedConverter x:Key="ShortcutsTreeConverter" />
<Converters:TypeNameConverter x:Key="TypeNameConverter" />
<Converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
@ -75,18 +76,6 @@
</Style> </Style>
<Converters:GesturesListConverter x:Key="GesturesListConverter" />
<Converters:ShortcutCategorySubElementsMergedConverter x:Key="ShortcutsTreeConverter" />
<Converters:TypeNameConverter x:Key="TypeNameConverter" />
<Converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
<Style x:Key="ExpandCollapseToggleStyle" TargetType="ToggleButton"> <Style x:Key="ExpandCollapseToggleStyle" TargetType="ToggleButton">
<Setter Property="Focusable" Value="False"/> <Setter Property="Focusable" Value="False"/>
@ -94,7 +83,7 @@
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="ToggleButton"> <ControlTemplate TargetType="ToggleButton">
<Grid Width="15" Height="13" Background="Transparent"> <Grid Width="15" Height="13" Background="Transparent">
<Path x:Name="expandPath" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="1,1,1,1" Fill="#444" Data="M 4 0 L 8 4 L 4 8 Z"/> <Path x:Name="expandPath" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="1" Fill="#444" Data="M 4 0 L 8 4 L 4 8 Z"/>
</Grid> </Grid>
<ControlTemplate.Triggers> <ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True"> <Trigger Property="IsChecked" Value="True">
@ -110,9 +99,9 @@
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="TreeViewItem"> <ControlTemplate TargetType="TreeViewItem">
<Border Name="OuterBorder" BorderThickness="2" CornerRadius="8" > <Border Name="OuterBorder" BorderThickness="2" CornerRadius="8" Margin="20,0,0,0">
<StackPanel> <StackPanel>
<Border Name="InnerBorder" Background="White" BorderThickness="0.6" CornerRadius="8" Padding="6" > <Border Name="InnerBorder" Background="White" BorderThickness="0.6" CornerRadius="8" Padding="0,6,6,6" >
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="19" /> <ColumnDefinition Width="19" />
@ -135,10 +124,9 @@
<DataTrigger Binding="{Binding Converter={StaticResource TypeNameConverter}}" Value="ShortcutCategory"> <DataTrigger Binding="{Binding Converter={StaticResource TypeNameConverter}}" Value="ShortcutCategory">
<Setter TargetName="InnerBorder" Property="Panel.Background" Value="#DEDE00" /> <Setter TargetName="InnerBorder" Property="Panel.Background" Value="#DEDE00" />
<Setter TargetName="InnerBorder" Property="TextElement.Foreground" Value="#FFFFFF" /> <Setter TargetName="InnerBorder" Property="TextElement.Foreground" Value="#FFFFFF" />
<Setter TargetName="OuterBorder" Property="Margin" Value="20,0,0,0" />
</DataTrigger> </DataTrigger>
<DataTrigger Binding="{Binding Converter={StaticResource TypeNameConverter}}" Value="AddIn"> <DataTrigger Binding="{Binding Converter={StaticResource TypeNameConverter}}" Value="AddIn">
<Setter TargetName="InnerBorder" Property="Panel.Background" Value="#FFFFFF" /> <Setter TargetName="InnerBorder" Property="Panel.Background" Value="#AEFFA8" />
<Setter TargetName="InnerBorder" Property="TextElement.Foreground" Value="#000000" /> <Setter TargetName="InnerBorder" Property="TextElement.Foreground" Value="#000000" />
</DataTrigger> </DataTrigger>
<DataTrigger Binding="{Binding Path=IsVisible}" Value="false"> <DataTrigger Binding="{Binding Path=IsVisible}" Value="false">

28
src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/ShortcutManagementWindow.xaml.cs

@ -29,12 +29,12 @@ namespace ICSharpCode.ShortcutsManagement
/// <summary> /// <summary>
/// Deep copy of addins list (including copies of categories and shortcuts) /// Deep copy of addins list (including copies of categories and shortcuts)
/// </summary> /// </summary>
private readonly ICollection<AddIn> addInsCopy = new ObservableCollection<AddIn>(); private readonly ICollection<IShortcutTreeEntry> rootEntriesCopy = new ObservableCollection<IShortcutTreeEntry>();
/// <summary> /// <summary>
/// List of all addins /// List of all addins
/// </summary> /// </summary>
private readonly ICollection<AddIn> addInsOriginal; private readonly ICollection<IShortcutTreeEntry> rootEntriesOriginal;
/// <summary> /// <summary>
/// List of modified shortcuts. /// List of modified shortcuts.
@ -53,22 +53,20 @@ namespace ICSharpCode.ShortcutsManagement
/// Initializes new <see cref="ShortcutManagementWindow" /> class /// Initializes new <see cref="ShortcutManagementWindow" /> class
/// </summary> /// </summary>
/// <param name="shortcut">Shortcut</param> /// <param name="shortcut">Shortcut</param>
/// <param name="addIns">List of all other add-ins containing shortcuts and categories. This list is used to find dupliate shortcuts</param> /// <param name="rootEntries">List of all other add-ins containing shortcuts and categories. This list is used to find dupliate shortcuts</param>
public ShortcutManagementWindow(Shortcut shortcut, ICollection<AddIn> addIns) public ShortcutManagementWindow(Shortcut shortcut, ICollection<IShortcutTreeEntry> rootEntries)
{ {
shortcutOriginal = shortcut; shortcutOriginal = shortcut;
addInsOriginal = addIns; rootEntriesOriginal = rootEntries;
// Make a deep copy of all add-ins, categories and shortcuts // Make a deep copy of all add-ins, categories and shortcuts
var shortcutCopyFound = false; var shortcutCopyFound = false;
foreach (var addIn in addIns) foreach (var entry in rootEntriesOriginal) {
{ var clonedAddIn = (IShortcutTreeEntry)entry.Clone();
var clonedAddIn = (AddIn) addIn.Clone(); rootEntriesCopy.Add(clonedAddIn);
addInsCopy.Add(clonedAddIn);
// Find copy of modified shortcut in copied add-ins collection // Find copy of modified shortcut in copied add-ins collection
if (shortcutCopyFound == false && (shortcutCopy = clonedAddIn.FindShortcut(shortcutOriginal.Id)) != null) if (shortcutCopyFound == false && (shortcutCopy = clonedAddIn.FindShortcut(shortcutOriginal.Id)) != null) {
{
shortcutCopy.Gestures.CollectionChanged += Gestures_CollectionChanged; shortcutCopy.Gestures.CollectionChanged += Gestures_CollectionChanged;
modifiedShortcuts.Add(shortcutCopy); modifiedShortcuts.Add(shortcutCopy);
DataContext = shortcutCopy; DataContext = shortcutCopy;
@ -79,7 +77,7 @@ namespace ICSharpCode.ShortcutsManagement
InitializeComponent(); InitializeComponent();
// Display similar shortcuts (Shortcuts with the same input gestures assigned to them) // Display similar shortcuts (Shortcuts with the same input gestures assigned to them)
shortcutsManagementOptionsPanel.DataContext = addInsCopy; shortcutsManagementOptionsPanel.DataContext = rootEntriesCopy;
shortcutsManagementOptionsPanel.Loaded += delegate { FilterSimilarShortcuts(); }; shortcutsManagementOptionsPanel.Loaded += delegate { FilterSimilarShortcuts(); };
} }
@ -97,7 +95,7 @@ namespace ICSharpCode.ShortcutsManagement
// Find shortcuts with same gesture and hide them. // Find shortcuts with same gesture and hide them.
// Also hide modified shortcut from this list // Also hide modified shortcut from this list
var finder = new ShortcutsFinder(addInsCopy); var finder = new ShortcutsFinder(rootEntriesCopy);
finder.FilterGesture(templates, true); finder.FilterGesture(templates, true);
finder.HideShortcut(shortcutCopy); finder.HideShortcut(shortcutCopy);
@ -206,8 +204,8 @@ namespace ICSharpCode.ShortcutsManagement
{ {
// Move modifications from shortcut copies to original shortcut objects // Move modifications from shortcut copies to original shortcut objects
foreach (var relatedShortcutCopy in modifiedShortcuts) { foreach (var relatedShortcutCopy in modifiedShortcuts) {
foreach (var addin in addInsOriginal) { foreach (var rootEntry in rootEntriesOriginal) {
var originalRelatedShortcut = addin.FindShortcut(relatedShortcutCopy.Id); var originalRelatedShortcut = rootEntry.FindShortcut(relatedShortcutCopy.Id);
if(originalRelatedShortcut != null) { if(originalRelatedShortcut != null) {
originalRelatedShortcut.Gestures.Clear(); originalRelatedShortcut.Gestures.Clear();
originalRelatedShortcut.Gestures.AddRange(relatedShortcutCopy.Gestures); originalRelatedShortcut.Gestures.AddRange(relatedShortcutCopy.Gestures);

101
src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/ShortcutsManagementOptionsPanel.xaml.cs

@ -33,35 +33,62 @@ namespace ICSharpCode.ShortcutsManagement
InitializeComponent(); InitializeComponent();
// Test data // Test data
var addins = new ObservableCollection<ShortcutManagement.AddIn>(); var rootEntries = new ObservableCollection<IShortcutTreeEntry>();
addins.Add(new ShortcutManagement.AddIn("SharpDevelop"));
addins[0].Categories.Add(new ShortcutCategory("Editing")); var addin1 = new ShortcutManagement.AddIn("SharpDevelop");
addins[0].Categories[0].Shortcuts.Add(new Shortcut("Copy", GetGestures("Ctrl + C"))); rootEntries.Add(addin1);
addins[0].Categories[0].Shortcuts.Add(new Shortcut("Paste", GetGestures("Ctrl + V | Ctrl+Insert"))); addin1.Categories.Add(new ShortcutCategory("Editing"));
addins[0].Categories[0].Shortcuts.Add(new Shortcut("Cut", GetGestures("Ctrl + X"))); addin1.Categories[0].Shortcuts.Add(new Shortcut("Copy", GetGestures("Ctrl + C")));
addins[0].Categories[0].Shortcuts.Add(new Shortcut("Undo", GetGestures("Ctrl + Z"))); addin1.Categories[0].Shortcuts.Add(new Shortcut("Paste", GetGestures("Ctrl + V | Ctrl+Insert")));
addins[0].Categories[0].Shortcuts.Add(new Shortcut("Redo", GetGestures("Ctrl + Y"))); addin1.Categories[0].Shortcuts.Add(new Shortcut("Cut", GetGestures("Ctrl + X")));
addins[0].Categories.Add(new ShortcutCategory("Building")); addin1.Categories[0].Shortcuts.Add(new Shortcut("Undo", GetGestures("Ctrl + Z")));
addins[0].Categories[1].Shortcuts.Add(new Shortcut("Build", GetGestures("Ctrl + Shift+B"))); addin1.Categories[0].Shortcuts.Add(new Shortcut("Redo", GetGestures("Ctrl + Y")));
addins[0].Categories[1].Shortcuts.Add(new Shortcut("Run", GetGestures("F5"))); addin1.Categories.Add(new ShortcutCategory("Building"));
addins[0].Categories[1].Shortcuts.Add(new Shortcut("Run without debuger", GetGestures("Ctrl + F5"))); addin1.Categories[1].Shortcuts.Add(new Shortcut("Build", GetGestures("Ctrl + Shift+B")));
addins[0].Categories[1].Shortcuts.Add(new Shortcut("Attach debuger", GetGestures("Ctrl + F8"))); addin1.Categories[1].Shortcuts.Add(new Shortcut("Run", GetGestures("F5")));
addins[0].Categories.Add(new ShortcutCategory("Uncategorized")); addin1.Categories[1].Shortcuts.Add(new Shortcut("Run without debuger", GetGestures("Ctrl + F5")));
addins[0].Categories[2].Shortcuts.Add(new Shortcut("Attach debuger", GetGestures("Ctrl + F8"))); addin1.Categories[1].Shortcuts.Add(new Shortcut("Attach debuger", GetGestures("Ctrl + F8")));
addin1.Categories.Add(new ShortcutCategory("Uncategorized"));
addins.Add(new ShortcutManagement.AddIn("Search & replace")); addin1.Categories[2].Shortcuts.Add(new Shortcut("Attach debuger", GetGestures("Ctrl + F8")));
addins[1].Categories.Add(new ShortcutCategory("Uncategorized"));
addins[1].Categories[0].Shortcuts.Add(new Shortcut("Quick find", GetGestures("Ctrl + F"))); var addin2 = new ShortcutManagement.AddIn("Search & replace");
addins[1].Categories[0].Shortcuts.Add(new Shortcut("Quick replace", GetGestures("Ctrl + H"))); rootEntries.Add(addin2);
addins[1].Categories[0].Shortcuts.Add(new Shortcut("Find in files", GetGestures("Ctrl + Shift + F | Ctrl + Shift + H | Ctrl + I"))); addin2.Categories.Add(new ShortcutCategory("Uncategorized"));
addins[1].Categories[0].Shortcuts.Add(new Shortcut("Replace in files", GetGestures("Ctrl + Shift + H"))); addin2.Categories[0].Shortcuts.Add(new Shortcut("Quick find", GetGestures("Ctrl + F")));
addins[1].Categories[0].Shortcuts.Add(new Shortcut("Find symbol", null)); addin2.Categories[0].Shortcuts.Add(new Shortcut("Quick replace", GetGestures("Ctrl + H")));
addin2.Categories[0].SubCategories.Add(new ShortcutCategory("Subcategory 3"));
addins.Add(new ShortcutManagement.AddIn("Unspecified")); addin2.Categories[0].SubCategories[0].SubCategories.Add(new ShortcutCategory("Subcategory 4"));
addins[2].Categories.Add(new ShortcutCategory("Uncategorized")); addin2.Categories[0].SubCategories[0].SubCategories[0].Shortcuts.Add(new Shortcut("Shortcut N", GetGestures("Ctrl + N")));
addins[2].Categories[0].Shortcuts.Add(new Shortcut("Test regex expression", null)); addin2.Categories[0].SubCategories[0].SubCategories[0].Shortcuts.Add(new Shortcut("Shortcut O", GetGestures("Ctrl + O")));
addin2.Categories[0].SubCategories[0].Shortcuts.Add(new Shortcut("Shortcut L", GetGestures("Ctrl + L")));
shortcutsManagementOptionsPanel.DataContext = addins; addin2.Categories[0].SubCategories[0].Shortcuts.Add(new Shortcut("Shortcut M", GetGestures("Ctrl + M")));
addin2.Categories[0].Shortcuts.Add(new Shortcut("Find in files", GetGestures("Ctrl + Shift + F | Ctrl + Shift + H | Ctrl + I")));
addin2.Categories[0].Shortcuts.Add(new Shortcut("Replace in files", GetGestures("Ctrl + Shift + H")));
addin2.Categories[0].Shortcuts.Add(new Shortcut("Find symbol", null));
var addin3 = new ShortcutManagement.AddIn("Unspecified");
rootEntries.Add(addin3);
addin3.Categories.Add(new ShortcutCategory("Uncategorized"));
addin3.Categories[0].Shortcuts.Add(new Shortcut("Test regex expression", null));
var rootCategory = new ShortcutCategory("Without addin");
rootEntries.Add(rootCategory);
rootCategory.SubCategories.Add(new ShortcutCategory("Subcategory 1"));
rootCategory.SubCategories[0].Shortcuts.Add(new Shortcut("Shortcut H", GetGestures("Ctrl + H")));
rootCategory.SubCategories[0].Shortcuts.Add(new Shortcut("Shortcut I", GetGestures("Ctrl + I")));
rootCategory.SubCategories.Add(new ShortcutCategory("Subcategory 2"));
rootCategory.SubCategories[0].Shortcuts.Add(new Shortcut("Shortcut J", GetGestures("Ctrl + J")));
rootCategory.SubCategories[0].Shortcuts.Add(new Shortcut("Shortcut K", GetGestures("Ctrl + K")));
rootCategory.Shortcuts.Add(new Shortcut("Shortcut A", GetGestures("Ctrl + A")));
rootCategory.Shortcuts.Add(new Shortcut("Shortcut B", GetGestures("Ctrl + B")));
rootCategory.Shortcuts.Add(new Shortcut("Shortcut C", GetGestures("Ctrl + C")));
rootCategory.Shortcuts.Add(new Shortcut("Shortcut D", GetGestures("Ctrl + D")));
rootCategory.Shortcuts.Add(new Shortcut("Shortcut E", null));
rootEntries.Add(new Shortcut("Shortcut F", GetGestures("Ctrl + F")));
rootEntries.Add(new Shortcut("Shortcut G", GetGestures("Ctrl + G")));
shortcutsManagementOptionsPanel.DataContext = rootEntries;
} }
public void LoadOptions() public void LoadOptions()
@ -70,8 +97,8 @@ namespace ICSharpCode.ShortcutsManagement
var unspecifiedAddInSection = new ShortcutManagement.AddIn("Unspecified"); var unspecifiedAddInSection = new ShortcutManagement.AddIn("Unspecified");
unspecifiedAddInSection.Categories.Add(new ShortcutCategory("Uncategorized")); unspecifiedAddInSection.Categories.Add(new ShortcutCategory("Uncategorized"));
var addIns = new List<ShortcutManagement.AddIn>(); var rootEntries = new List<IShortcutTreeEntry>();
addIns.Add(unspecifiedAddInSection); rootEntries.Add(unspecifiedAddInSection);
var addInsMap = new Dictionary<AddIn, ShortcutManagement.AddIn>(); var addInsMap = new Dictionary<AddIn, ShortcutManagement.AddIn>();
var categoriesMap = new Dictionary<ShortcutManagement.AddIn, Dictionary<string, ShortcutCategory>>(); var categoriesMap = new Dictionary<ShortcutManagement.AddIn, Dictionary<string, ShortcutCategory>>();
@ -88,7 +115,7 @@ namespace ICSharpCode.ShortcutsManagement
addinSection.Categories.Add(new ShortcutCategory("Uncategorized")); addinSection.Categories.Add(new ShortcutCategory("Uncategorized"));
addInsMap.Add(inputBindingInfo.AddIn, addinSection); addInsMap.Add(inputBindingInfo.AddIn, addinSection);
categoriesMap.Add(addinSection, new Dictionary<string, ShortcutCategory>()); categoriesMap.Add(addinSection, new Dictionary<string, ShortcutCategory>());
addIns.Add(addinSection); rootEntries.Add(addinSection);
} }
ShortcutCategory categorySection; ShortcutCategory categorySection;
@ -117,14 +144,14 @@ namespace ICSharpCode.ShortcutsManagement
shortcutsMap.Add(shortcut, inputBindingInfo); shortcutsMap.Add(shortcut, inputBindingInfo);
} }
addIns.Sort((a, b) => a.Name.CompareTo(b.Name)); rootEntries.Sort();
foreach (var addIn in addIns) foreach (var entry in rootEntries)
{ {
addIn.SortEntries(); entry.SortSubEntries();
} }
new ShortcutsFinder(addIns).Filter(""); new ShortcutsFinder(rootEntries).Filter("");
shortcutsManagementOptionsPanel.DataContext = addIns; shortcutsManagementOptionsPanel.DataContext = rootEntries;
} }
public bool SaveOptions() { public bool SaveOptions() {

2
src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/ShortcutsTreeView.xaml

@ -55,7 +55,7 @@
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<TextBlock Text="{Binding Text}" ShortcutsManagement:TextBlockBehavior.SearchedText="{Binding ElementName=searchTextBox, Path=Text}" Grid.Column="0" /> <TextBlock Text="{Binding Name}" ShortcutsManagement:TextBlockBehavior.SearchedText="{Binding ElementName=searchTextBox, Path=Text}" Grid.Column="0" />
<TextBlock Text="{Binding Gestures, Converter={StaticResource GesturesListConverter}}" Grid.Column="1" TextAlignment="Right" Padding="20,0,0,0" /> <TextBlock Text="{Binding Gestures, Converter={StaticResource GesturesListConverter}}" Grid.Column="1" TextAlignment="Right" Padding="20,0,0,0" />
<Button x:Name="removeShortcutButton" Style="{StaticResource RemoveButton}" Visibility="Hidden" Grid.Column="2" Tag="{Binding}" Click="removeShortcutButton_Click" /> <Button x:Name="removeShortcutButton" Style="{StaticResource RemoveButton}" Visibility="Hidden" Grid.Column="2" Tag="{Binding}" Click="removeShortcutButton_Click" />
</Grid> </Grid>

61
src/AddIns/Misc/ShortcutsManagement/ShortcutsManagement/Src/Dialogs/ShortcutsTreeView.xaml.cs

@ -70,10 +70,10 @@ namespace ICSharpCode.ShortcutsManagement
/// <summary> /// <summary>
/// List of add-ins containing shortcut categories and shortcuts /// List of add-ins containing shortcut categories and shortcuts
/// </summary> /// </summary>
private ICollection<AddIn> AddIns private ICollection<IShortcutTreeEntry> RootEntries
{ {
get { get {
return (ICollection<AddIn>)DataContext; return (ICollection<IShortcutTreeEntry>)DataContext;
} }
} }
@ -96,21 +96,54 @@ namespace ICSharpCode.ShortcutsManagement
private void ShowShortcutManagementWindow(Shortcut shortcut) private void ShowShortcutManagementWindow(Shortcut shortcut)
{ {
var shortcutManagementWindow = new ShortcutManagementWindow(shortcut, AddIns); var shortcutManagementWindow = new ShortcutManagementWindow(shortcut, RootEntries);
shortcutManagementWindow.ShowDialog(); shortcutManagementWindow.ShowDialog();
} }
public void SelectFirstVisibleShortcut(bool setFocus) public void SelectFirstVisibleShortcut(bool setFocus)
{ {
// Select first visible shortcut var path = new List<IShortcutTreeEntry>();
var selectedAddIn = AddIns.FirstOrDefault(a => a.IsVisible); foreach (var entry in RootEntries) {
if (selectedAddIn != null) { if (entry != null && entry.IsVisible) {
var selectedCategory = selectedAddIn.Categories.FirstOrDefault(c => c.IsVisible); path.Add(entry);
FindFirstVisibleItemPath(entry, path);
shortcutsTreeView.SelectItem(path.Cast<object>().ToList(), setFocus);
return;
}
}
}
private void FindFirstVisibleItemPath(IShortcutTreeEntry parent, List<IShortcutTreeEntry> path)
{
var addIn = parent as AddIn;
if(addIn != null)
{
var selectedCategory = addIn.Categories.FirstOrDefault(a => a.IsVisible);
if (selectedCategory != null) { if (selectedCategory != null) {
var selectedShortcut = selectedCategory.Shortcuts.FirstOrDefault(s => s.IsVisible); path.Add(selectedCategory);
if (selectedShortcut != null) { FindFirstVisibleItemPath(selectedCategory, path);
shortcutsTreeView.SelectItem(new List<object> { selectedAddIn, selectedCategory, selectedShortcut }, setFocus); return;
} }
}
var category = parent as ShortcutCategory;
if (category != null)
{
var selectedCategory = category.SubCategories.FirstOrDefault(a => a.IsVisible);
if (selectedCategory != null)
{
path.Add(selectedCategory);
FindFirstVisibleItemPath(selectedCategory, path);
return;
}
var selectedShortcut = category.Shortcuts.FirstOrDefault(a => a.IsVisible);
if (selectedShortcut != null)
{
path.Add(selectedShortcut);
FindFirstVisibleItemPath(selectedShortcut, path);
return;
} }
} }
} }
@ -185,7 +218,7 @@ namespace ICSharpCode.ShortcutsManagement
{ {
if (!searchTypeToggleButton.IsChecked.HasValue || searchTypeToggleButton.IsChecked.Value) return; if (!searchTypeToggleButton.IsChecked.HasValue || searchTypeToggleButton.IsChecked.Value) return;
new ShortcutsFinder(AddIns).Filter(searchTextBox.Text); new ShortcutsFinder(RootEntries).Filter(searchTextBox.Text);
if (!string.IsNullOrEmpty(searchTextBox.Text)) { if (!string.IsNullOrEmpty(searchTextBox.Text)) {
SelectFirstVisibleShortcut(false); SelectFirstVisibleShortcut(false);
@ -223,7 +256,7 @@ namespace ICSharpCode.ShortcutsManagement
// Filter shortcuts with similar gestures assigned and display entered gesture inside search textbox // Filter shortcuts with similar gestures assigned and display entered gesture inside search textbox
var keyGestureTemplate = new KeyGestureTemplate(e.Key, Keyboard.Modifiers); var keyGestureTemplate = new KeyGestureTemplate(e.Key, Keyboard.Modifiers);
new ShortcutsFinder(AddIns).FilterGesture(keyGestureTemplate, false); new ShortcutsFinder(RootEntries).FilterGesture(keyGestureTemplate, false);
SelectFirstVisibleShortcut(false); SelectFirstVisibleShortcut(false);
searchTextBox.Text = new KeyGestureTemplate(e).ToString(); searchTextBox.Text = new KeyGestureTemplate(e).ToString();
@ -239,7 +272,7 @@ namespace ICSharpCode.ShortcutsManagement
{ {
searchTextBox.Text = ""; searchTextBox.Text = "";
new ShortcutsFinder(AddIns).Filter(""); new ShortcutsFinder(RootEntries).Filter("");
shortcutsTreeView.SetExpandAll(false); shortcutsTreeView.SetExpandAll(false);
} }
} }

Loading…
Cancel
Save