Reverted some unwanted changes back to the trunk version (e.g. AvalonEdit shouldn't reference Core.Presentation). I'm committing the result of the merge as a new branch because the shortcuts integration breaks some menus. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/shortcuts2@5231 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61shortcuts
@ -0,0 +1,34 @@
@@ -0,0 +1,34 @@
|
||||
using System.Reflection; |
||||
using System.Resources; |
||||
using System.Runtime.CompilerServices; |
||||
using System.Runtime.InteropServices; |
||||
using System.Windows; |
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("ShortcutsManagement")] |
||||
[assembly: AssemblyDescription("")] |
||||
[assembly: AssemblyConfiguration("")] |
||||
[assembly: AssemblyTrademark("")] |
||||
[assembly: AssemblyCulture("")] |
||||
|
||||
//In order to begin building localizable applications, set
|
||||
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
|
||||
//inside a <PropertyGroup>. For example, if you are using US english
|
||||
//in your source files, set the <UICulture> to en-US. Then uncomment
|
||||
//the NeutralResourceLanguage attribute below. Update the "en-US" in
|
||||
//the line below to match the UICulture setting in the project file.
|
||||
|
||||
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
|
||||
|
||||
|
||||
[assembly: ThemeInfo( |
||||
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||
//(used if a resource is not found in the page,
|
||||
// or application resource dictionaries)
|
||||
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||
//(used if a resource is not found in the page,
|
||||
// app, or any theme specific resource dictionaries)
|
||||
)] |
||||
|
@ -0,0 +1,63 @@
@@ -0,0 +1,63 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:2.0.50727.3082
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace ICSharpCode.ShortcutsManagement.Properties { |
||||
using System; |
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] |
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] |
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] |
||||
internal class Resources { |
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan; |
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture; |
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] |
||||
internal Resources() { |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] |
||||
internal static global::System.Resources.ResourceManager ResourceManager { |
||||
get { |
||||
if (object.ReferenceEquals(resourceMan, null)) { |
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ICSharpCode.ShortcutsManagement.Properties.Resources", typeof(Resources).Assembly); |
||||
resourceMan = temp; |
||||
} |
||||
return resourceMan; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] |
||||
internal static global::System.Globalization.CultureInfo Culture { |
||||
get { |
||||
return resourceCulture; |
||||
} |
||||
set { |
||||
resourceCulture = value; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,117 @@
@@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<root> |
||||
<!-- |
||||
Microsoft ResX Schema |
||||
|
||||
Version 2.0 |
||||
|
||||
The primary goals of this format is to allow a simple XML format |
||||
that is mostly human readable. The generation and parsing of the |
||||
various data types are done through the TypeConverter classes |
||||
associated with the data types. |
||||
|
||||
Example: |
||||
|
||||
... ado.net/XML headers & schema ... |
||||
<resheader name="resmimetype">text/microsoft-resx</resheader> |
||||
<resheader name="version">2.0</resheader> |
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> |
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> |
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> |
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> |
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> |
||||
<value>[base64 mime encoded serialized .NET Framework object]</value> |
||||
</data> |
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> |
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> |
||||
<comment>This is a comment</comment> |
||||
</data> |
||||
|
||||
There are any number of "resheader" rows that contain simple |
||||
name/value pairs. |
||||
|
||||
Each data row contains a name, and value. The row also contains a |
||||
type or mimetype. Type corresponds to a .NET class that support |
||||
text/value conversion through the TypeConverter architecture. |
||||
Classes that don't support this are serialized and stored with the |
||||
mimetype set. |
||||
|
||||
The mimetype is used for serialized objects, and tells the |
||||
ResXResourceReader how to depersist the object. This is currently not |
||||
extensible. For a given mimetype the value must be set accordingly: |
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format |
||||
that the ResXResourceWriter will generate, however the reader can |
||||
read any of the formats listed below. |
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64 |
||||
value : The object must be serialized with |
||||
: System.Serialization.Formatters.Binary.BinaryFormatter |
||||
: and then encoded with base64 encoding. |
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64 |
||||
value : The object must be serialized with |
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter |
||||
: and then encoded with base64 encoding. |
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64 |
||||
value : The object must be serialized into a byte array |
||||
: using a System.ComponentModel.TypeConverter |
||||
: and then encoded with base64 encoding. |
||||
--> |
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> |
||||
<xsd:element name="root" msdata:IsDataSet="true"> |
||||
<xsd:complexType> |
||||
<xsd:choice maxOccurs="unbounded"> |
||||
<xsd:element name="metadata"> |
||||
<xsd:complexType> |
||||
<xsd:sequence> |
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" /> |
||||
</xsd:sequence> |
||||
<xsd:attribute name="name" type="xsd:string" /> |
||||
<xsd:attribute name="type" type="xsd:string" /> |
||||
<xsd:attribute name="mimetype" type="xsd:string" /> |
||||
</xsd:complexType> |
||||
</xsd:element> |
||||
<xsd:element name="assembly"> |
||||
<xsd:complexType> |
||||
<xsd:attribute name="alias" type="xsd:string" /> |
||||
<xsd:attribute name="name" type="xsd:string" /> |
||||
</xsd:complexType> |
||||
</xsd:element> |
||||
<xsd:element name="data"> |
||||
<xsd:complexType> |
||||
<xsd:sequence> |
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> |
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> |
||||
</xsd:sequence> |
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" /> |
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> |
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> |
||||
</xsd:complexType> |
||||
</xsd:element> |
||||
<xsd:element name="resheader"> |
||||
<xsd:complexType> |
||||
<xsd:sequence> |
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> |
||||
</xsd:sequence> |
||||
<xsd:attribute name="name" type="xsd:string" use="required" /> |
||||
</xsd:complexType> |
||||
</xsd:element> |
||||
</xsd:choice> |
||||
</xsd:complexType> |
||||
</xsd:element> |
||||
</xsd:schema> |
||||
<resheader name="resmimetype"> |
||||
<value>text/microsoft-resx</value> |
||||
</resheader> |
||||
<resheader name="version"> |
||||
<value>2.0</value> |
||||
</resheader> |
||||
<resheader name="reader"> |
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> |
||||
</resheader> |
||||
<resheader name="writer"> |
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> |
||||
</resheader> |
||||
</root> |
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:2.0.50727.3082
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace ICSharpCode.ShortcutsManagement.Properties { |
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] |
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")] |
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { |
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); |
||||
|
||||
public static Settings Default { |
||||
get { |
||||
return defaultInstance; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='utf-8'?> |
||||
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)"> |
||||
<Profiles> |
||||
<Profile Name="(Default)" /> |
||||
</Profiles> |
||||
<Settings /> |
||||
</SettingsFile> |
After Width: | Height: | Size: 311 B |
@ -0,0 +1,215 @@
@@ -0,0 +1,215 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<root> |
||||
<!-- |
||||
Microsoft ResX Schema |
||||
|
||||
Version 2.0 |
||||
|
||||
The primary goals of this format is to allow a simple XML format |
||||
that is mostly human readable. The generation and parsing of the |
||||
various data types are done through the TypeConverter classes |
||||
associated with the data types. |
||||
|
||||
Example: |
||||
|
||||
... ado.net/XML headers & schema ... |
||||
<resheader name="resmimetype">text/microsoft-resx</resheader> |
||||
<resheader name="version">2.0</resheader> |
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> |
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> |
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> |
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> |
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> |
||||
<value>[base64 mime encoded serialized .NET Framework object]</value> |
||||
</data> |
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> |
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> |
||||
<comment>This is a comment</comment> |
||||
</data> |
||||
|
||||
There are any number of "resheader" rows that contain simple |
||||
name/value pairs. |
||||
|
||||
Each data row contains a name, and value. The row also contains a |
||||
type or mimetype. Type corresponds to a .NET class that support |
||||
text/value conversion through the TypeConverter architecture. |
||||
Classes that don't support this are serialized and stored with the |
||||
mimetype set. |
||||
|
||||
The mimetype is used for serialized objects, and tells the |
||||
ResXResourceReader how to depersist the object. This is currently not |
||||
extensible. For a given mimetype the value must be set accordingly: |
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format |
||||
that the ResXResourceWriter will generate, however the reader can |
||||
read any of the formats listed below. |
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64 |
||||
value : The object must be serialized with |
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter |
||||
: and then encoded with base64 encoding. |
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64 |
||||
value : The object must be serialized with |
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter |
||||
: and then encoded with base64 encoding. |
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64 |
||||
value : The object must be serialized into a byte array |
||||
: using a System.ComponentModel.TypeConverter |
||||
: and then encoded with base64 encoding. |
||||
--> |
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> |
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> |
||||
<xsd:element name="root" msdata:IsDataSet="true"> |
||||
<xsd:complexType> |
||||
<xsd:choice maxOccurs="unbounded"> |
||||
<xsd:element name="metadata"> |
||||
<xsd:complexType> |
||||
<xsd:sequence> |
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" /> |
||||
</xsd:sequence> |
||||
<xsd:attribute name="name" use="required" type="xsd:string" /> |
||||
<xsd:attribute name="type" type="xsd:string" /> |
||||
<xsd:attribute name="mimetype" type="xsd:string" /> |
||||
<xsd:attribute ref="xml:space" /> |
||||
</xsd:complexType> |
||||
</xsd:element> |
||||
<xsd:element name="assembly"> |
||||
<xsd:complexType> |
||||
<xsd:attribute name="alias" type="xsd:string" /> |
||||
<xsd:attribute name="name" type="xsd:string" /> |
||||
</xsd:complexType> |
||||
</xsd:element> |
||||
<xsd:element name="data"> |
||||
<xsd:complexType> |
||||
<xsd:sequence> |
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> |
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> |
||||
</xsd:sequence> |
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> |
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> |
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> |
||||
<xsd:attribute ref="xml:space" /> |
||||
</xsd:complexType> |
||||
</xsd:element> |
||||
<xsd:element name="resheader"> |
||||
<xsd:complexType> |
||||
<xsd:sequence> |
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> |
||||
</xsd:sequence> |
||||
<xsd:attribute name="name" type="xsd:string" use="required" /> |
||||
</xsd:complexType> |
||||
</xsd:element> |
||||
</xsd:choice> |
||||
</xsd:complexType> |
||||
</xsd:element> |
||||
</xsd:schema> |
||||
<resheader name="resmimetype"> |
||||
<value>text/microsoft-resx</value> |
||||
</resheader> |
||||
<resheader name="version"> |
||||
<value>2.0</value> |
||||
</resheader> |
||||
<resheader name="reader"> |
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> |
||||
</resheader> |
||||
<resheader name="writer"> |
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> |
||||
</resheader> |
||||
<data name="ShortcutsManagement.EnterGestureLabel" xml:space="preserve"> |
||||
<value>Add gesture</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.ShortcutGesturesLabel" xml:space="preserve"> |
||||
<value>Shortcut gestures</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.SimilarShortcutsLabel" xml:space="preserve"> |
||||
<value>Shortcuts with same gestures</value> |
||||
</data> |
||||
<data name="Global.CancelButtonText" xml:space="preserve"> |
||||
<value>_Cancel</value> |
||||
<comment>For testing outside SD</comment> |
||||
</data> |
||||
<data name="Global.OKButtonText" xml:space="preserve"> |
||||
<value>_OK</value> |
||||
<comment>For testing outside SD</comment> |
||||
</data> |
||||
<data name="ShortcutsManagement.UnspecifiedAddInName" xml:space="preserve"> |
||||
<value>Unspecified</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.UnspecifiedCategoryName" xml:space="preserve"> |
||||
<value>Uncategorized</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.GestureTextBox.FirstChordIsIncomplete" xml:space="preserve"> |
||||
<value>First chord must have a modifier</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.GestureTextBox.GestureIsValid" xml:space="preserve"> |
||||
<value>Valid gesture</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.GestureTextBox.LastChordIsIncomplete" xml:space="preserve"> |
||||
<value>Multi key gesture is not finished</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.GestureTextBox.SequenceIsNotCoherent" xml:space="preserve"> |
||||
<value>Invalid gesture. Sequence is not coherent.</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.GestureTextBox.TimeExpired" xml:space="preserve"> |
||||
<value>Time given for gesture entry expired</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.ModificationWindow.AdditionFailedFirstChordIsIncomplete" xml:space="preserve"> |
||||
<value>Failed to add a gesture. First chord should contain a modifier</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.ModificationWindow.AdditionFailedLastChordIsIncompete" xml:space="preserve"> |
||||
<value>Failed to add a gesture. Gesture is unfinished. Last chord should have a key</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.ModificationWindow.AdditionFailedNoChords" xml:space="preserve"> |
||||
<value>Failed to add a gesture. Gesture must have atleast one chord</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.ModificationWindow.AdditionIsSuccessfull" xml:space="preserve"> |
||||
<value>Gesture added</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.ModificationWindow.AddingExistingGesture" xml:space="preserve"> |
||||
<value>Failed to add a gesture. Such gesture already exists in shortcut gestures collections</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.CreateNewProfilePrompt.BasedOnLabel" xml:space="preserve"> |
||||
<value>Based on:</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.CreateNewProfilePrompt.SpecifyProfileNameLabel" xml:space="preserve"> |
||||
<value>Please specify profile name</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.ReadOnly" xml:space="preserve"> |
||||
<value>Read-Only</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.ShortcutsManagementOptionsPanel.ConfirmDeleteProfileMessage" xml:space="preserve"> |
||||
<value>Are you sure you want to reset modifications to current profile?</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.ShortcutsManagementOptionsPanel.ConfirmDeleteProfileMessageWindowName" xml:space="preserve"> |
||||
<value>Reset modifications to profile</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.ShortcutsManagementOptionsPanel.NoProfileSelectedMessage" xml:space="preserve"> |
||||
<value>Please select a profile which you wan't to modify.</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.ShortcutsManagementOptionsPanel.ProfileCreateAction" xml:space="preserve"> |
||||
<value>Create</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.ShortcutsManagementOptionsPanel.ProfileDeleteAction" xml:space="preserve"> |
||||
<value>Delete</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.ShortcutsManagementOptionsPanel.ProfileLoadAction" xml:space="preserve"> |
||||
<value>Load</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.ShortcutsManagementOptionsPanel.ProfileRenameAction" xml:space="preserve"> |
||||
<value>Rename</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.ShortcutsManagementOptionsPanel.ProfileResetAction" xml:space="preserve"> |
||||
<value>Reset to defaults</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.ShortcutManagementWindow.ResetToDefaults" xml:space="preserve"> |
||||
<value>Reset</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.ShortcutsManagementOptionsPanel.ProfilesLabel" xml:space="preserve"> |
||||
<value>Profiles:</value> |
||||
</data> |
||||
<data name="ShortcutsManagement.ShortcutsManagementOptionsPanel.SelectedProfileIsReadOnlyMessage" xml:space="preserve"> |
||||
<value>Selected profile is read-only.</value> |
||||
</data> |
||||
</root> |
After Width: | Height: | Size: 318 B |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 6.3 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.2 KiB |
@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
|
||||
<AddIn name = "ShortcutsManagement" |
||||
author = "Sergej Andrejev" |
||||
url = "" |
||||
description = "Addin allows managing application shortcuts"> |
||||
|
||||
<Manifest> |
||||
<Identity name="ICSharpCode.ShortcutsManagement" version = "@SharpDevelopCoreVersion"/> |
||||
</Manifest> |
||||
|
||||
<Runtime> |
||||
<Import assembly = "ICSharpCode.ShortcutsManagement.dll"/> |
||||
</Runtime> |
||||
|
||||
<Path name = "/SharpDevelop/Dialogs/OptionsDialog/TextEditorOptions"> |
||||
<OptionPanel id = "ShortcutsManagement" |
||||
label = "Shortcuts management" |
||||
class = "ICSharpCode.ShortcutsManagement.Dialogs.ShortcutsManagementOptionsPanel" /> |
||||
</Path> |
||||
</AddIn> |
@ -0,0 +1,160 @@
@@ -0,0 +1,160 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build"> |
||||
<PropertyGroup> |
||||
<ProjectGuid>{745869FF-80E9-4589-A366-E775D2103843}</ProjectGuid> |
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
||||
<OutputType>Library</OutputType> |
||||
<RootNamespace>ICSharpCode.ShortcutsManagement</RootNamespace> |
||||
<AssemblyName>ICSharpCode.ShortcutsManagement</AssemblyName> |
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> |
||||
<AppDesignerFolder>Properties</AppDesignerFolder> |
||||
<SignAssembly>True</SignAssembly> |
||||
<AssemblyOriginatorKeyFile>ShortcutsManagement.snk</AssemblyOriginatorKeyFile> |
||||
<DelaySign>False</DelaySign> |
||||
<AssemblyOriginatorKeyMode>File</AssemblyOriginatorKeyMode> |
||||
<AllowUnsafeBlocks>False</AllowUnsafeBlocks> |
||||
<NoStdLib>False</NoStdLib> |
||||
<WarningLevel>4</WarningLevel> |
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors> |
||||
<OutputPath>..\..\..\..\AddIns\AddIns\Misc\ShortcutsManagement\</OutputPath> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> |
||||
<DebugSymbols>true</DebugSymbols> |
||||
<DebugType>Full</DebugType> |
||||
<Optimize>False</Optimize> |
||||
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow> |
||||
<DefineConstants>DEBUG;TRACE</DefineConstants> |
||||
<StartAction>Program</StartAction> |
||||
<StartProgram>..\..\..\..\bin\SharpDevelop.exe</StartProgram> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' "> |
||||
<DebugSymbols>False</DebugSymbols> |
||||
<DebugType>None</DebugType> |
||||
<Optimize>True</Optimize> |
||||
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow> |
||||
<DefineConstants>TRACE</DefineConstants> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition=" '$(Platform)' == 'AnyCPU' "> |
||||
<RegisterForComInterop>False</RegisterForComInterop> |
||||
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies> |
||||
<BaseAddress>4194304</BaseAddress> |
||||
<PlatformTarget>AnyCPU</PlatformTarget> |
||||
<FileAlignment>4096</FileAlignment> |
||||
</PropertyGroup> |
||||
<ItemGroup> |
||||
<Reference Include="PresentationCore"> |
||||
<RequiredTargetFramework>3.0</RequiredTargetFramework> |
||||
</Reference> |
||||
<Reference Include="PresentationFramework"> |
||||
<RequiredTargetFramework>3.0</RequiredTargetFramework> |
||||
</Reference> |
||||
<Reference Include="System" /> |
||||
<Reference Include="System.Core"> |
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework> |
||||
</Reference> |
||||
<Reference Include="System.Data" /> |
||||
<Reference Include="System.Xaml"> |
||||
<RequiredTargetFramework>4.0</RequiredTargetFramework> |
||||
</Reference> |
||||
<Reference Include="System.Xml" /> |
||||
<Reference Include="WindowsBase"> |
||||
<RequiredTargetFramework>3.0</RequiredTargetFramework> |
||||
</Reference> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<Compile Include="..\..\..\Main\GlobalAssemblyInfo.cs"> |
||||
<Link>Properties\GlobalAssemblyInfo.cs</Link> |
||||
</Compile> |
||||
<Compile Include="Properties\AssemblyInfo.cs" /> |
||||
<Compile Include="Src\Converters\AdditionConverter.cs" /> |
||||
<Compile Include="Src\Converters\BoolToVisibilityConverter.cs" /> |
||||
<Compile Include="Src\Converters\GesturesCollectionConverter.cs" /> |
||||
<Compile Include="Src\Converters\InputGestureConverter.cs" /> |
||||
<Compile Include="Src\Converters\NotNullOrEmptyConverter.cs" /> |
||||
<Compile Include="Src\Converters\ProfilesComboBoxItemStyleSelector.cs" /> |
||||
<Compile Include="Src\Converters\ProfileToStringConverter.cs" /> |
||||
<Compile Include="Src\Converters\ShortcutCategorySubElementsMergedConverter.cs" /> |
||||
<Compile Include="Src\Converters\TypeNameConverter.cs" /> |
||||
<Compile Include="Src\Data\AddIn.cs" /> |
||||
<Compile Include="Src\Data\IShortcutTreeEntry.cs" /> |
||||
<Compile Include="Src\Data\IShortcutTreeEntryCloner.cs" /> |
||||
<Compile Include="Src\Data\MapTable.cs" /> |
||||
<Compile Include="Src\Data\SeparatorData.cs" /> |
||||
<Compile Include="Src\Data\Shortcut.cs" /> |
||||
<Compile Include="Src\Data\ShortcutCategory.cs" /> |
||||
<Compile Include="Src\Data\ShortcutsFinder.cs" /> |
||||
<Compile Include="Src\Data\UserGestureProfileAction.cs" /> |
||||
<Compile Include="Src\Dialogs\CreateNewProfilePrompt.xaml.cs"> |
||||
<DependentUpon>CreateNewProfilePrompt.xaml</DependentUpon> |
||||
</Compile> |
||||
<Compile Include="Src\Dialogs\MultiKeyGestureTextBox.xaml.cs"> |
||||
<DependentUpon>MultiKeyGestureTextBox.xaml</DependentUpon> |
||||
</Compile> |
||||
<Compile Include="Src\Dialogs\ShortcutManagementWindow.xaml.cs"> |
||||
<DependentUpon>ShortcutManagementWindow.xaml</DependentUpon> |
||||
</Compile> |
||||
<Compile Include="Src\Dialogs\ShortcutsManagementOptionsPanel.xaml.cs"> |
||||
<DependentUpon>ShortcutsManagementOptionsPanel.xaml</DependentUpon> |
||||
</Compile> |
||||
<Compile Include="Src\Dialogs\ShortcutsTreeView.xaml.cs"> |
||||
<DependentUpon>ShortcutsTreeView.xaml</DependentUpon> |
||||
</Compile> |
||||
<Compile Include="Src\Extensions\TextBlockBehavior.cs" /> |
||||
<Compile Include="Src\Extensions\TreeViewExtensions.cs" /> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<Folder Include="Resources" /> |
||||
<Folder Include="Src" /> |
||||
<Folder Include="Src\Converters" /> |
||||
<Folder Include="Src\Data" /> |
||||
<Folder Include="Src\Dialogs" /> |
||||
<Folder Include="Src\Extensions" /> |
||||
<Folder Include="Themes" /> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<Resource Include="Resources\16-square-red-remove.png" /> |
||||
<Resource Include="Resources\add_correction_16x16.gif" /> |
||||
<Resource Include="Resources\block_small.png" /> |
||||
<Resource Include="Resources\delete_small.png" /> |
||||
<Resource Include="Resources\info_big.png" /> |
||||
<Resource Include="Resources\info_mid.png" /> |
||||
<Resource Include="Resources\info_small.png" /> |
||||
<Resource Include="Resources\key_enter.png" /> |
||||
<Resource Include="Resources\key_enter_pressed.png" /> |
||||
<Resource Include="Resources\plus_small.png" /> |
||||
<Resource Include="Resources\search_small.png" /> |
||||
<Resource Include="Resources\tick_small.png" /> |
||||
<Resource Include="Resources\warning_small.png" /> |
||||
<None Include="ShortcutsManagement.addin"> |
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> |
||||
</None> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<EmbeddedResource Include="Resources\StringResources.resx" /> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<Page Include="Src\Dialogs\CreateNewProfilePrompt.xaml" /> |
||||
<Page Include="Src\Dialogs\MultiKeyGestureTextBox.xaml" /> |
||||
<Page Include="Src\Dialogs\Resources.xaml" /> |
||||
<Page Include="Src\Dialogs\ShortcutManagementWindow.xaml" /> |
||||
<Page Include="Src\Dialogs\ShortcutsManagementOptionsPanel.xaml" /> |
||||
<Page Include="Src\Dialogs\ShortcutsTreeView.xaml" /> |
||||
<Page Include="Themes\Generic.xaml" /> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<ProjectReference Include="..\..\..\Main\Base\Project\ICSharpCode.SharpDevelop.csproj"> |
||||
<Project>{2748AD25-9C63-4E12-877B-4DCE96FBED54}</Project> |
||||
<Name>ICSharpCode.SharpDevelop</Name> |
||||
</ProjectReference> |
||||
<ProjectReference Include="..\..\..\Main\Core\Project\ICSharpCode.Core.csproj"> |
||||
<Project>{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}</Project> |
||||
<Name>ICSharpCode.Core</Name> |
||||
</ProjectReference> |
||||
<ProjectReference Include="..\..\..\Main\ICSharpCode.Core.Presentation\ICSharpCode.Core.Presentation.csproj"> |
||||
<Project>{7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}</Project> |
||||
<Name>ICSharpCode.Core.Presentation</Name> |
||||
</ProjectReference> |
||||
</ItemGroup> |
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" /> |
||||
</Project> |
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
using System; |
||||
using System.Globalization; |
||||
using System.Windows.Data; |
||||
|
||||
namespace ICSharpCode.ShortcutsManagement.Converters |
||||
{ |
||||
/// <summary>
|
||||
/// Converts double value to another double value by adding another value provided in converter parameter
|
||||
/// </summary>
|
||||
class AddidionConverter : IValueConverter |
||||
{ |
||||
/// <summary>
|
||||
/// Convert double value to another double value by adding another value provided in converter parameter
|
||||
/// </summary>
|
||||
/// <param name="value">Original double value</param>
|
||||
/// <param name="targetType">Convertion target type</param>
|
||||
/// <param name="parameter">Another double value to be added to original value</param>
|
||||
/// <param name="culture">Not used</param>
|
||||
/// <returns>New double value</returns>
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) |
||||
{ |
||||
double additionParameter = 0; |
||||
var additionParameterString = parameter as string; |
||||
if (additionParameterString != null) { |
||||
Double.TryParse(additionParameterString, out additionParameter); |
||||
} |
||||
|
||||
if(value is double) { |
||||
var doubleValue = (double)value; |
||||
return doubleValue + additionParameter; |
||||
} |
||||
|
||||
return value; |
||||
} |
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) |
||||
{ |
||||
throw new NotSupportedException(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
using System; |
||||
using System.Globalization; |
||||
using System.Windows; |
||||
using System.Windows.Data; |
||||
|
||||
namespace ICSharpCode.ShortcutsManagement.Converters |
||||
{ |
||||
/// <summary>
|
||||
/// Converts boolean value to <see cref="Visibility" /> enum
|
||||
/// </summary>
|
||||
public class BoolToVisibilityConverter : IValueConverter |
||||
{ |
||||
/// <summary>
|
||||
/// Convert forward
|
||||
/// </summary>
|
||||
/// <param name="value">Boolean value</param>
|
||||
/// <param name="targetType">Target type (Only string is supported)</param>
|
||||
/// <param name="parameter">Hide type (Hidden - reserve space but don't show, Collapse - do not reserve space)</param>
|
||||
/// <param name="culture">Culture info (Invariant culture is used always)</param>
|
||||
/// <returns>Visibility value</returns>
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) |
||||
{ |
||||
if(value is bool) { |
||||
var hidden = parameter ?? "Hidden"; |
||||
return (bool)value ? "Visible" : hidden; |
||||
} |
||||
|
||||
throw new NotSupportedException(); |
||||
} |
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) |
||||
{ |
||||
throw new NotSupportedException(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,46 @@
@@ -0,0 +1,46 @@
|
||||
using System; |
||||
using System.Collections.ObjectModel; |
||||
using System.Globalization; |
||||
using System.Windows.Data; |
||||
using System.Windows.Input; |
||||
using ICSharpCode.Core.Presentation; |
||||
|
||||
namespace ICSharpCode.ShortcutsManagement.Converters |
||||
{ |
||||
/// <summary>
|
||||
/// Converts input gestures collection into string
|
||||
/// </summary>
|
||||
public class GesturesListConverter : IValueConverter |
||||
{ |
||||
/// <summary>
|
||||
/// Convert collection of gestures to a string
|
||||
/// </summary>
|
||||
/// <param name="value">Collection of gestures</param>
|
||||
/// <param name="targetType">Convertion target type (only string is supported)</param>
|
||||
/// <param name="parameter">Not used</param>
|
||||
/// <param name="culture">Not used</param>
|
||||
/// <returns>String representing collection of gestures</returns>
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) |
||||
{ |
||||
string converterValue = ""; |
||||
if (value is InputGestureCollection && (targetType == typeof(string) || targetType.IsSubclassOf(typeof(string)))) { |
||||
converterValue = new InputGestureCollectionConverter().ConvertToInvariantString(value); |
||||
} |
||||
|
||||
if (value is ObservableCollection<InputGesture> && (targetType == typeof(string) || targetType.IsSubclassOf(typeof(string)))) { |
||||
var inputGestureCollection = new InputGestureCollection(); |
||||
foreach (var gesture in (ObservableCollection<InputGesture>)value) { |
||||
inputGestureCollection.Add(gesture); |
||||
} |
||||
converterValue = new InputGestureCollectionConverter().ConvertToInvariantString(inputGestureCollection); |
||||
} |
||||
|
||||
return converterValue.Replace("+", " + ").Replace(",", ", ").Replace(";", "; "); |
||||
} |
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) |
||||
{ |
||||
throw new NotSupportedException(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
using System; |
||||
using System.Globalization; |
||||
using System.Windows.Data; |
||||
using System.Windows.Input; |
||||
using ICSharpCode.Core.Presentation; |
||||
|
||||
namespace ICSharpCode.ShortcutsManagement.Converters |
||||
{ |
||||
/// <summary>
|
||||
/// Converts input gesture to string representation
|
||||
/// </summary>
|
||||
public class InputGestureConverter : IValueConverter |
||||
{ |
||||
/// <summary>
|
||||
/// Convert input gesture to string
|
||||
/// </summary>
|
||||
/// <param name="value">Input gesture</param>
|
||||
/// <param name="targetType">Convertion target type (Only string is supported)</param>
|
||||
/// <param name="parameter">Not used</param>
|
||||
/// <param name="culture">Not used</param>
|
||||
/// <returns>String representing <see cref="InputGesture" /></returns>
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) |
||||
{ |
||||
if (value is KeyGesture && targetType == typeof(string)) { |
||||
var gestures = new InputGestureCollection(new[] {value}); |
||||
return new InputGestureCollectionConverter().ConvertToInvariantString(gestures).Replace("+", " + ").Replace(",", ", "); |
||||
} |
||||
|
||||
if(value is MouseGesture && targetType == typeof(string)) { |
||||
return new MouseGestureConverter().ConvertToInvariantString(value); |
||||
} |
||||
|
||||
return ""; |
||||
} |
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) |
||||
{ |
||||
throw new NotSupportedException(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,34 @@
@@ -0,0 +1,34 @@
|
||||
using System; |
||||
using System.Globalization; |
||||
using System.Windows.Data; |
||||
|
||||
namespace ICSharpCode.ShortcutsManagement.Converters |
||||
{ |
||||
/// <summary>
|
||||
/// Converts null and empty string to true and all other values to false
|
||||
/// </summary>
|
||||
class NotNullOrEmptyConverter : IValueConverter |
||||
{ |
||||
/// <summary>
|
||||
/// Converts null and empty string to true and all other values to false
|
||||
/// </summary>
|
||||
/// <param name="value">String or any other object</param>
|
||||
/// <param name="targetType">Convertion target type</param>
|
||||
/// <param name="parameter">Not used</param>
|
||||
/// <param name="culture">Not used</param>
|
||||
/// <returns>Bool value</returns>
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) |
||||
{ |
||||
if ((value is string && !string.IsNullOrEmpty((string)value)) || (!(value is string) && value != null)) { |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) |
||||
{ |
||||
throw new NotSupportedException(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
using System; |
||||
using System.Globalization; |
||||
using System.Windows.Data; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.Core.Presentation; |
||||
|
||||
namespace ICSharpCode.ShortcutsManagement.Converters |
||||
{ |
||||
/// <summary>
|
||||
/// Converts profile to representing string
|
||||
/// </summary>
|
||||
public class ProfileToStringConverter : IValueConverter |
||||
{ |
||||
/// <summary>
|
||||
/// Converts profile to representing string
|
||||
/// </summary>
|
||||
/// <param name="value">UserGestureProfile instance</param>
|
||||
/// <param name="targetType">Convertion target type (only string is supported)</param>
|
||||
/// <param name="parameter">Not supported</param>
|
||||
/// <param name="culture">Not supported</param>
|
||||
/// <returns>String representing instance of UserGestureProfile</returns>
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) |
||||
{ |
||||
var profile = value as UserGestureProfile; |
||||
if(profile != null) { |
||||
var readOnlyString = ""; |
||||
if(profile.ReadOnly) { |
||||
readOnlyString = string.Format(" ({0})", StringParser.Parse("${res:ShortcutsManagement.ReadOnly}")); |
||||
} |
||||
|
||||
return profile.Text + readOnlyString; |
||||
} |
||||
|
||||
return value; |
||||
} |
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) |
||||
{ |
||||
throw new NotSupportedException(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
|
||||
using System.Windows; |
||||
using System.Windows.Controls; |
||||
using ICSharpCode.ShortcutsManagement.Data; |
||||
|
||||
namespace ICSharpCode.ShortcutsManagement.Converters |
||||
{ |
||||
/// <summary>
|
||||
/// Selects profilesComboBox item style
|
||||
/// </summary>
|
||||
public class ProfilesComboBoxItemStyleSelector : StyleSelector |
||||
{ |
||||
/// <summary>
|
||||
/// Selects profilesComboBox item style
|
||||
/// </summary>
|
||||
/// <param name="item">Item contained in ComboBoxItem</param>
|
||||
/// <param name="container">ComboBoxItem container</param>
|
||||
/// <returns>ComboBoxItem style</returns>
|
||||
public override Style SelectStyle(object item, DependencyObject container) |
||||
{ |
||||
if(item is SeparatorData) { |
||||
return (Style)((FrameworkElement)container).FindResource("SeparatorStyle"); |
||||
} |
||||
|
||||
if(item is UserGestureProfileAction) { |
||||
return (Style)((FrameworkElement)container).FindResource("ProfileActionStyle"); |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,37 @@
@@ -0,0 +1,37 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Globalization; |
||||
using System.Linq; |
||||
using System.Windows.Data; |
||||
using ICSharpCode.ShortcutsManagement.Data; |
||||
|
||||
namespace ICSharpCode.ShortcutsManagement.Converters |
||||
{ |
||||
/// <summary>
|
||||
/// Merges category's sub-categories and shortcuts into one list
|
||||
/// </summary>
|
||||
public class ShortcutCategorySubElementsMergedConverter : IMultiValueConverter |
||||
{ |
||||
/// <summary>
|
||||
/// Merge category's sub-categories and shortcuts into one list
|
||||
/// </summary>
|
||||
/// <param name="values">List of sub-categories and list of shortcuts</param>
|
||||
/// <param name="targetType">Not used</param>
|
||||
/// <param name="parameter">Not used</param>
|
||||
/// <param name="culture">Not used</param>
|
||||
/// <returns>List of objects where objects are either a shortcut category or a shortcut</returns>
|
||||
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) |
||||
{ |
||||
var items = new List<object>(); |
||||
items.AddRange(((IEnumerable<ShortcutCategory>)values[0]).Cast<object>()); |
||||
items.AddRange(((IEnumerable<Shortcut>)values[1]).Cast<object>()); |
||||
|
||||
return items; |
||||
} |
||||
|
||||
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) |
||||
{ |
||||
throw new NotSupportedException(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
using System; |
||||
using System.Globalization; |
||||
using System.Windows.Data; |
||||
|
||||
namespace ICSharpCode.ShortcutsManagement.Converters |
||||
{ |
||||
/// <summary>
|
||||
/// Convert object to its type name
|
||||
/// </summary>
|
||||
class TypeNameConverter : IValueConverter |
||||
{ |
||||
/// <summary>
|
||||
/// Convert object to type name
|
||||
/// </summary>
|
||||
/// <param name="value">Any object</param>
|
||||
/// <param name="targetType">Convertion target type (Only string is supported)</param>
|
||||
/// <param name="parameter">Not used</param>
|
||||
/// <param name="culture">Not used</param>
|
||||
/// <returns>Passed object type name</returns>
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) |
||||
{ |
||||
return value.GetType().Name; |
||||
} |
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) |
||||
{ |
||||
throw new NotSupportedException(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,125 @@
@@ -0,0 +1,125 @@
|
||||
using System.Collections.Generic; |
||||
using System.ComponentModel; |
||||
|
||||
namespace ICSharpCode.ShortcutsManagement.Data |
||||
{ |
||||
/// <summary>
|
||||
/// Add-in where shortcuts were registered
|
||||
/// </summary>
|
||||
public class AddIn : INotifyPropertyChanged, IShortcutTreeEntry |
||||
{ |
||||
private string name; |
||||
|
||||
/// <summary>
|
||||
/// Gets or sets add-in name
|
||||
/// </summary>
|
||||
public string Name |
||||
{ |
||||
get { |
||||
return name; |
||||
} |
||||
set { |
||||
if (name != value) { |
||||
name = value; |
||||
InvokePropertyChanged("Name"); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private bool isVisible; |
||||
|
||||
/// <summary>
|
||||
/// Gets or sets value specifying whether category is visible in shortcuts tree or not
|
||||
/// </summary>
|
||||
public bool IsVisible |
||||
{ |
||||
get { |
||||
return isVisible; |
||||
} |
||||
set { |
||||
if (isVisible != value) { |
||||
isVisible = value; |
||||
InvokePropertyChanged("IsVisible"); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets list of add-in categories
|
||||
/// </summary>
|
||||
public List<ShortcutCategory> Categories |
||||
{ |
||||
get; |
||||
private set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Creates new instance of <see cref="AddIn" />
|
||||
/// </summary>
|
||||
/// <param name="addInName">Add-in name</param>
|
||||
public AddIn(string addInName) |
||||
{ |
||||
IsVisible = true; |
||||
Name = addInName; |
||||
Categories = new List<ShortcutCategory>(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Finds shortcut by shortcut Id in add-in categories
|
||||
/// </summary>
|
||||
/// <param name="shortcutId">Shortcut Id</param>
|
||||
/// <returns>Shortcut with matching Id value</returns>
|
||||
public Shortcut FindShortcut(string shortcutId) |
||||
{ |
||||
foreach (var c in Categories) { |
||||
Shortcut foundShortcut; |
||||
if ((foundShortcut = c.FindShortcut(shortcutId)) != null) { |
||||
return foundShortcut; |
||||
} |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Sorts add-in sub-categories
|
||||
/// </summary>
|
||||
public void SortSubEntries() |
||||
{ |
||||
Categories.Sort((a, b) => a.Name.CompareTo(b.Name)); |
||||
foreach (var category in Categories) { |
||||
category.SortSubEntries(); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Occurs when <see cref="Name" /> or or <see cref="IsVisible" /> property value changes
|
||||
/// </summary>
|
||||
public event PropertyChangedEventHandler PropertyChanged; |
||||
|
||||
/// <summary>
|
||||
/// Compares add-in to other instances of type <see cref="IShortcutTreeEntry"/>
|
||||
/// </summary>
|
||||
/// <param name="obj">Compared object</param>
|
||||
/// <returns>Comparison result</returns>
|
||||
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); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Invoke dependency property changed event
|
||||
/// </summary>
|
||||
/// <param name="propertyName">Name of dependency property from this classs</param>
|
||||
private void InvokePropertyChanged(string propertyName) |
||||
{ |
||||
if (PropertyChanged != null) { |
||||
PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
using System; |
||||
|
||||
namespace ICSharpCode.ShortcutsManagement.Data |
||||
{ |
||||
public interface IShortcutTreeEntry : IComparable |
||||
{ |
||||
/// <summary>
|
||||
/// Gets or sets shortcut entry name displayed in shortcuts tree
|
||||
/// </summary>
|
||||
string Name |
||||
{ |
||||
get; set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Specifies whether shortcut tree entry is visible
|
||||
/// </summary>
|
||||
bool IsVisible |
||||
{ |
||||
get; set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Sort shortcut entry sub elements
|
||||
/// </summary>
|
||||
void SortSubEntries(); |
||||
|
||||
/// <summary>
|
||||
/// Search for shortcut in this shortcut entry and sub-elements
|
||||
/// </summary>
|
||||
/// <param name="shortcutId"></param>
|
||||
/// <returns></returns>
|
||||
Shortcut FindShortcut(string shortcutId); |
||||
} |
||||
} |
@ -0,0 +1,119 @@
@@ -0,0 +1,119 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Windows.Input; |
||||
|
||||
namespace ICSharpCode.ShortcutsManagement.Data |
||||
{ |
||||
/// <summary>
|
||||
/// Creates deep copy of <see cref="Shortcut" />, <see cref="ShortcutTree" /> or <see cref="AddIn" />
|
||||
/// </summary>
|
||||
public class IShortcutTreeEntryCloner |
||||
{ |
||||
/// <summary>
|
||||
/// Creates new instance of <see cref="IShortcutTreeEntryCloner" />
|
||||
/// </summary>
|
||||
public IShortcutTreeEntryCloner() |
||||
{ |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Deep clone collection of <see cref="IShortcutTreeEntry" />
|
||||
///
|
||||
/// Re-uses <see cref="Shortcut" /> instances for similar shortcuts in different categories
|
||||
/// </summary>
|
||||
/// <param name="entries">Collection of <see cref="IShortcutTreeEntry" /></param>
|
||||
/// <returns>Cloned entries</returns>
|
||||
public ICollection<IShortcutTreeEntry> CloneShortcutTree(ICollection<IShortcutTreeEntry> entries) |
||||
{ |
||||
var clonedShortcuts = new Dictionary<string, Shortcut>(); |
||||
var clonedEntries = new List<IShortcutTreeEntry>(); |
||||
|
||||
// Make a deep copy of all add-ins, categories and shortcuts
|
||||
foreach (var entry in entries) { |
||||
var shortcut = entry as Shortcut; |
||||
var category = entry as ShortcutCategory; |
||||
var addin = entry as AddIn; |
||||
|
||||
IShortcutTreeEntry clonedEntry = null; |
||||
if(shortcut != null) { |
||||
clonedEntry = CloneShortcut(shortcut, clonedShortcuts); |
||||
} else if(category != null) { |
||||
clonedEntry = CloneShortutCategory(category, clonedShortcuts); |
||||
} else if(addin != null) { |
||||
clonedEntry = CloneAddin(addin, clonedShortcuts); |
||||
} |
||||
|
||||
clonedEntries.Add(clonedEntry); |
||||
} |
||||
|
||||
return clonedEntries; |
||||
} |
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a deep copy of <see cref="ShortcutCategory" /> instance
|
||||
///
|
||||
/// Re-uses <see cref="Shortcut" /> instances for similar shortcuts in different categories
|
||||
/// </summary>
|
||||
/// <param name="category">Cloned shortcut category</param>
|
||||
/// <param name="clonedShortcuts">Dictionary of shortcuts which should be re-used. If cloned shortcut <see cref="Shortcut.Id" /> property value is already preset in this dictionary instance from dictionary is used instead</param>
|
||||
/// <returns>Deep copy of <see cref="ShortcutCategory" /></returns>
|
||||
public ShortcutCategory CloneShortutCategory(ShortcutCategory category, Dictionary<string, Shortcut> clonedShortcuts) |
||||
{ |
||||
var clonedCategory = new ShortcutCategory(category.Name); |
||||
|
||||
foreach (var subCategory in category.SubCategories) { |
||||
clonedCategory.SubCategories.Add(CloneShortutCategory(subCategory, clonedShortcuts)); |
||||
} |
||||
|
||||
foreach (var shortcut in category.Shortcuts) { |
||||
clonedCategory.Shortcuts.Add(CloneShortcut(shortcut, clonedShortcuts)); |
||||
} |
||||
|
||||
return clonedCategory; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Create a deep copy of <see cref="AddIn" /> instance
|
||||
///
|
||||
/// Re-uses <see cref="Shortcut" /> instances for similar shortcuts in different categories
|
||||
/// </summary>
|
||||
/// <param name="shortcut">Cloned shortcut</param>
|
||||
/// <param name="clonedShortcuts">Dictionary of shortcuts which should be re-used. If cloned shortcut <see cref="Shortcut.Id" /> property value is already preset in this dictionary instance from dictionary is used instead</param>
|
||||
/// <returns>Deep copy of <see cref="Shortcut" /></returns>
|
||||
public Shortcut CloneShortcut(Shortcut shortcut, Dictionary<string, Shortcut> clonedShortcuts) |
||||
{ |
||||
if(clonedShortcuts.ContainsKey(shortcut.Id)) { |
||||
return clonedShortcuts[shortcut.Id]; |
||||
} else { |
||||
var clonedShortcut = new Shortcut( |
||||
shortcut.Id, |
||||
shortcut.Name, |
||||
new InputGestureCollection(shortcut.Gestures), |
||||
new InputGestureCollection(shortcut.DefaultGestures)); |
||||
|
||||
clonedShortcuts.Add(clonedShortcut.Id, clonedShortcut); |
||||
|
||||
return clonedShortcut; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Creates a deep copy of <see cref="AddIn" /> instance
|
||||
///
|
||||
/// Re-uses <see cref="Shortcut" /> instances for similar shortcuts in different categories
|
||||
/// </summary>
|
||||
/// <param name="category">Cloned add-in</param>
|
||||
/// <param name="clonedShortcuts">Dictionary of shortcuts which should be re-used. If cloned shortcut <see cref="Shortcut.Id" /> property value is already preset in this dictionary instance from dictionary is used instead</param>
|
||||
/// <returns>Deep copy of <see cref="AddIn" /> instance</returns>
|
||||
public AddIn CloneAddin(AddIn addin, Dictionary<string, Shortcut> clonedShortcuts) |
||||
{ |
||||
var clonedAddIn = new AddIn(addin.Name); |
||||
foreach (var category in addin.Categories) { |
||||
clonedAddIn.Categories.Add(CloneShortutCategory(category, clonedShortcuts)); |
||||
} |
||||
|
||||
return clonedAddIn; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,87 @@
@@ -0,0 +1,87 @@
|
||||
using System.Collections; |
||||
using System.Collections.Generic; |
||||
|
||||
namespace ICSharpCode.ShortcutsManagement.Data |
||||
{ |
||||
/// <summary>
|
||||
/// Stores one-to-one relationships beween two objects of type T1 and T2
|
||||
/// </summary>
|
||||
public class MapTable<T1, T2> : IEnumerable<KeyValuePair<T1, T2>> |
||||
{ |
||||
private readonly Dictionary<T1, T2> forwardMaping = new Dictionary<T1, T2>(); |
||||
private readonly Dictionary<T2, T1> backwardMaping = new Dictionary<T2, T1>(); |
||||
|
||||
/// <summary>
|
||||
/// Add new relationship between mapped and mapping object
|
||||
/// </summary>
|
||||
/// <param name="mappingObject">Mapping object</param>
|
||||
/// <param name="mappedObject">Mapping object</param>
|
||||
public void Add(T1 mappingObject, T2 mappedObject) |
||||
{ |
||||
forwardMaping.Add(mappingObject, mappedObject); |
||||
backwardMaping.Add(mappedObject, mappingObject); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Tries to find object related to mapping object
|
||||
/// </summary>
|
||||
/// <param name="mappingObject">Mapping object</param>
|
||||
/// <param name="mappedObject">Mapped object</param>
|
||||
public void TryMapForward(T1 mappingObject, out T2 mappedObject) |
||||
{ |
||||
forwardMaping.TryGetValue(mappingObject, out mappedObject); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Tries to find object related to mapped object
|
||||
/// </summary>
|
||||
/// <param name="mappingObject">Mapped object</param>
|
||||
/// <param name="mappedObject">Mapping object</param>
|
||||
public void TryMapBackward(T2 mappedObject, out T1 mappingObject) |
||||
{ |
||||
backwardMaping.TryGetValue(mappedObject, out mappingObject); |
||||
} |
||||
|
||||
|
||||
/// <summary>
|
||||
/// Finds object related to mapping object
|
||||
/// </summary>
|
||||
/// <param name="mappingObject">Mapping object</param>
|
||||
/// <returns>Mapped object</returns>
|
||||
public T2 MapForward(T1 mappingObject) |
||||
{ |
||||
return forwardMaping[mappingObject]; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Finds object related to mapped object
|
||||
/// </summary>
|
||||
/// <param name="mappingObject">Mapped object</param>
|
||||
/// <returns>Mapping object</returns>
|
||||
public T1 MapBackward(T2 mappingObject) |
||||
{ |
||||
return backwardMaping[mappingObject]; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Removes all relationships from map
|
||||
/// </summary>
|
||||
public void Clear() |
||||
{ |
||||
forwardMaping.Clear(); |
||||
backwardMaping.Clear(); |
||||
} |
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerator<KeyValuePair<T1, T2>> GetEnumerator() |
||||
{ |
||||
return forwardMaping.GetEnumerator(); |
||||
} |
||||
|
||||
/// <inheritdoc />
|
||||
IEnumerator IEnumerable.GetEnumerator() |
||||
{ |
||||
return forwardMaping.GetEnumerator(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
|
||||
namespace ICSharpCode.ShortcutsManagement.Data |
||||
{ |
||||
/// <summary>
|
||||
/// Represents a seporator in data binded control
|
||||
/// </summary>
|
||||
class SeparatorData |
||||
{ |
||||
} |
||||
} |
@ -0,0 +1,235 @@
@@ -0,0 +1,235 @@
|
||||
using System; |
||||
using System.Collections.ObjectModel; |
||||
using System.Collections.Generic; |
||||
using System.ComponentModel; |
||||
using System.Windows.Input; |
||||
using ICSharpCode.Core.Presentation; |
||||
using System.Linq; |
||||
using System.Collections.Specialized; |
||||
|
||||
namespace ICSharpCode.ShortcutsManagement.Data |
||||
{ |
||||
/// <summary>
|
||||
/// Shortcut
|
||||
/// </summary>
|
||||
public class Shortcut : INotifyPropertyChanged, IShortcutTreeEntry |
||||
{ |
||||
/// <summary>
|
||||
/// Gets collection of input gestures assigned to this <see cref="Shortcut" /> instance
|
||||
/// </summary>
|
||||
public ObservableCollection<InputGesture> Gestures |
||||
{ |
||||
get; |
||||
private set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets collection of default input suggested assigned by developer
|
||||
/// </summary>
|
||||
public ReadOnlyCollection<InputGesture> DefaultGestures |
||||
{ |
||||
get; |
||||
private set; |
||||
} |
||||
|
||||
private bool _doesUseDefault; |
||||
|
||||
/// <summary>
|
||||
/// Gets or sets value which specifies whether default gestures should be used or those assigned by user
|
||||
/// </summary>
|
||||
public bool DoesUseDefault |
||||
{ |
||||
get { |
||||
return _doesUseDefault; |
||||
} |
||||
} |
||||
|
||||
private string _name; |
||||
|
||||
/// <summary>
|
||||
/// Gets or sets shortcut name (displayed to user)
|
||||
/// </summary>
|
||||
public string Name |
||||
{ |
||||
get { |
||||
return _name; |
||||
} |
||||
set { |
||||
if(_name != value) { |
||||
_name = value; |
||||
InvokePropertyChanged("Name"); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Sorts shortcut sub-elements
|
||||
/// </summary>
|
||||
public void SortSubEntries() |
||||
{ |
||||
|
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets or sets shortcut id.
|
||||
///
|
||||
/// This value is used to identify shortcut clones
|
||||
/// </summary>
|
||||
public string Id |
||||
{ |
||||
get; set; |
||||
} |
||||
|
||||
private bool isVisible; |
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether category is visible in shortcuts tree
|
||||
///
|
||||
/// Dependency property
|
||||
/// </summary>
|
||||
public bool IsVisible |
||||
{ |
||||
get { |
||||
return isVisible; |
||||
} |
||||
set { |
||||
if(isVisible != value) { |
||||
isVisible = value; |
||||
InvokePropertyChanged("IsVisible"); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Notify observers about property changes
|
||||
/// </summary>
|
||||
public event PropertyChangedEventHandler PropertyChanged; |
||||
|
||||
/// <summary>
|
||||
/// Create new instance of <see cref="Shortcut" />
|
||||
/// </summary>
|
||||
/// <param name="id">Shortcut id. Used to identify shortcut clones</param>
|
||||
/// <param name="gestures">Active gestures</param>
|
||||
/// <param name="defaultGestures">Default gestures suggest by developer</param>
|
||||
public Shortcut(string shortcutText, InputGestureCollection gestures, InputGestureCollection defaultGestures) |
||||
: this(Guid.NewGuid().ToString(), shortcutText, gestures, defaultGestures) |
||||
{ |
||||
|
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Create new instance of <see cref="Shortcut" />
|
||||
/// </summary>
|
||||
/// <param name="id">Shortcut id. Used to identify shortcut clones</param>
|
||||
/// <param name="shortcutText">Shortcut action name (displayed to user)</param>
|
||||
/// <param name="gestures">Active gestures</param>
|
||||
/// <param name="defaultGestures">Default gestures suggest by developer</param>
|
||||
public Shortcut(string id, string shortcutText, InputGestureCollection gestures, InputGestureCollection defaultGestures) |
||||
{ |
||||
IsVisible = true; |
||||
Id = id; |
||||
Name = shortcutText; |
||||
|
||||
if(defaultGestures != null) { |
||||
var defaultGesturesArray = new InputGesture[defaultGestures.Count]; |
||||
defaultGestures.CopyTo(defaultGesturesArray, 0); |
||||
DefaultGestures = new ReadOnlyCollection<InputGesture>(defaultGesturesArray); |
||||
} else { |
||||
DefaultGestures = new ReadOnlyCollection<InputGesture>(new List<InputGesture>()); |
||||
} |
||||
|
||||
Gestures = new ObservableCollection<InputGesture>(); |
||||
if(gestures != null) { |
||||
foreach (InputGesture gesture in gestures) { |
||||
Gestures.Add(gesture); |
||||
} |
||||
} |
||||
|
||||
_doesUseDefault = new InputGestureCollection(Gestures).ContainsTemplateForAny(new InputGestureCollection(DefaultGestures), GestureCompareMode.ExactlyMatches); |
||||
Gestures.CollectionChanged += Gestures_CollectionChanged; |
||||
} |
||||
|
||||
void Gestures_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) |
||||
{ |
||||
var newDoesUseDefaultValue = new InputGestureCollection(Gestures).ContainsTemplateForAny(new InputGestureCollection(DefaultGestures), GestureCompareMode.ExactlyMatches); |
||||
if(_doesUseDefault != newDoesUseDefaultValue) { |
||||
_doesUseDefault = newDoesUseDefaultValue; |
||||
InvokePropertyChanged("DoesUseDefault"); |
||||
} |
||||
|
||||
InvokePropertyChanged("Gestures"); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Determines whether provided gesture is already assigned to this action
|
||||
/// </summary>
|
||||
/// <param name="gesture">Input gesture</param>
|
||||
/// <returns>True if provided gesture is assigned to this action. Otherwise false</returns>
|
||||
public bool ContainsGesture(InputGesture gesture) |
||||
{ |
||||
foreach (var existingGesture in Gestures) { |
||||
if(existingGesture == gesture) { |
||||
return true; |
||||
} |
||||
|
||||
if(existingGesture is KeyGesture && gesture is KeyGesture) { |
||||
var existingKeyGesture = (KeyGesture) existingGesture; |
||||
var keyGesture = (KeyGesture) gesture; |
||||
|
||||
if(existingKeyGesture.Key == keyGesture.Key && existingKeyGesture.Modifiers == keyGesture.Modifiers) { |
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Compare shortcut to other instances of <see cref="IShortcutTreeEntry"/>
|
||||
/// </summary>
|
||||
/// <param name="obj">Compared object</param>
|
||||
/// <returns>Comparison result</returns>
|
||||
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); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Returns this <see cref="Shortcut"/> instance if searched id matches
|
||||
/// </summary>
|
||||
/// <param name="shortcutId">Searched shortcut id</param>
|
||||
/// <returns>Found shortcut instance or null</returns>
|
||||
public Shortcut FindShortcut(string shortcutId) { |
||||
return Id == shortcutId ? this : null; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Invoke dependency property changed event
|
||||
/// </summary>
|
||||
/// <param name="propertyName">Name of dependency property from this classs</param>
|
||||
private void InvokePropertyChanged(string propertyName) |
||||
{ |
||||
if (PropertyChanged != null) { |
||||
PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Resets active gestures assigned to this shortcut to default <see cref="InputGestureCollection" /> suggested by developer
|
||||
/// </summary>
|
||||
public void ResetToDefaults() |
||||
{ |
||||
_doesUseDefault = true; |
||||
|
||||
Gestures.Clear(); |
||||
foreach(var gesture in DefaultGestures) { |
||||
Gestures.Add(gesture); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,145 @@
@@ -0,0 +1,145 @@
|
||||
using System.Collections.Generic; |
||||
using System.ComponentModel; |
||||
|
||||
namespace ICSharpCode.ShortcutsManagement.Data |
||||
{ |
||||
/// <summary>
|
||||
/// Stores shortcut category data
|
||||
/// </summary>
|
||||
public class ShortcutCategory : INotifyPropertyChanged, IShortcutTreeEntry |
||||
{ |
||||
private string name; |
||||
|
||||
/// <summary>
|
||||
/// Gets or sets category name
|
||||
/// </summary>
|
||||
public string Name |
||||
{ |
||||
get { |
||||
return name; |
||||
} |
||||
set { |
||||
if (name != value) { |
||||
name = value; |
||||
InvokePropertyChanged("Name"); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private bool isVisible; |
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether category is visible in shortcuts tree
|
||||
/// </summary>
|
||||
public bool IsVisible |
||||
{ |
||||
get { |
||||
return isVisible; |
||||
} |
||||
set { |
||||
if (isVisible != value) { |
||||
isVisible = value; |
||||
InvokePropertyChanged("IsVisible"); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets list of sub-cateories
|
||||
/// </summary>
|
||||
public List<ShortcutCategory> SubCategories |
||||
{ |
||||
get; |
||||
private set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets shortcuts assigned to this category
|
||||
/// </summary>
|
||||
public List<Shortcut> Shortcuts |
||||
{ |
||||
get; |
||||
private set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Occurs when <see cref="Name" /> or <see cref="IsVisible" /> property changes
|
||||
/// </summary>
|
||||
public event PropertyChangedEventHandler PropertyChanged; |
||||
|
||||
/// <summary>
|
||||
/// Creates new instance of <see cref="ShortcutCategory" />
|
||||
/// </summary>
|
||||
/// <param name="categoryName">Category name</param>
|
||||
public ShortcutCategory(string categoryName) |
||||
{ |
||||
IsVisible = true; |
||||
Shortcuts = new List<Shortcut>(); |
||||
SubCategories = new List<ShortcutCategory>(); |
||||
Name = categoryName; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Sorts category shortcuts
|
||||
/// </summary>
|
||||
public void SortSubEntries() |
||||
{ |
||||
SubCategories.Sort((a, b) => a.Name.CompareTo(b.Name)); |
||||
Shortcuts.Sort((a, b) => a.Name.CompareTo(b.Name)); |
||||
|
||||
foreach (var category in SubCategories) { |
||||
category.SortSubEntries(); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// In this category and sub-categories finds shortcut by shortcut ID
|
||||
/// </summary>
|
||||
/// <param name="shortcutId">Shortcut ID</param>
|
||||
/// <returns>Shortcut with ID equal to provided</returns>
|
||||
public Shortcut FindShortcut(string shortcutId) |
||||
{ |
||||
// Search for shortcut in shortcuts assigned to this category
|
||||
foreach (var s in Shortcuts) { |
||||
if(s.Id == shortcutId) { |
||||
return s; |
||||
} |
||||
} |
||||
|
||||
// Search for shortcut in sub categories
|
||||
foreach (var category in SubCategories) { |
||||
Shortcut foundShortcut; |
||||
if ((foundShortcut = category.FindShortcut(shortcutId)) != null) { |
||||
return foundShortcut; |
||||
} |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Compares <see cref="ShortcutCategory" /> instance to another instance of <see cref="IShortcutTreeEntry"/> type
|
||||
/// </summary>
|
||||
/// <param name="obj">Compared object</param>
|
||||
/// <returns>Comparison result</returns>
|
||||
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); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Invoke dependency property changed event
|
||||
/// </summary>
|
||||
/// <param name="propertyName">Name of dependency property from this classs</param>
|
||||
private void InvokePropertyChanged(string propertyName) |
||||
{ |
||||
if (PropertyChanged != null) { |
||||
PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,264 @@
@@ -0,0 +1,264 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Diagnostics; |
||||
using System.Windows.Input; |
||||
using ICSharpCode.Core.Presentation; |
||||
using ICSharpCode.ShortcutsManagement.Extensions; |
||||
|
||||
namespace ICSharpCode.ShortcutsManagement.Data |
||||
{ |
||||
/// <summary>
|
||||
/// Filters and hides shortcuts from add-in collection
|
||||
/// </summary>
|
||||
public class ShortcutsFinder |
||||
{ |
||||
/// <summary>
|
||||
/// Gets and sets collection of add-ins, shortcut categories and shortcuts from shortcuts tree root level
|
||||
/// </summary>
|
||||
public ICollection<IShortcutTreeEntry> RootEntries |
||||
{ |
||||
get; set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Create new instance of <see cref="ShortcutsFinder"/>
|
||||
/// </summary>
|
||||
/// <param name="rootEntries"></param>
|
||||
public ShortcutsFinder(ICollection<IShortcutTreeEntry> rootEntries) |
||||
{ |
||||
RootEntries = rootEntries; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Hides shortcut by setting <see cref="Shortcut.IsVisible"/> to false
|
||||
///
|
||||
/// This also function hides parent categories and Add-in if it has no sub-elements
|
||||
/// left
|
||||
/// </summary>
|
||||
/// <param name="shortcut">Shortcut to be hidden</param>
|
||||
public void HideShortcut(Shortcut shortcut) |
||||
{ |
||||
foreach (var entry in RootEntries) { |
||||
var subCategoryIsVisible = false; |
||||
|
||||
var rootAddIn = entry as AddIn; |
||||
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); |
||||
} |
||||
|
||||
var rootShortcut = entry as Shortcut; |
||||
if (rootShortcut != null) { |
||||
shortcut.IsVisible = false; |
||||
} |
||||
} |
||||
} |
||||
|
||||
private static bool HideShortcut(ShortcutCategory category, Shortcut filteredShortcut) |
||||
{ |
||||
// Check if this shortcut is in subcategories
|
||||
var isSubElementVisible = false; |
||||
foreach (var subCategory in category.SubCategories) { |
||||
if (HideShortcut(subCategory, filteredShortcut)) { |
||||
isSubElementVisible = true; |
||||
} |
||||
} |
||||
|
||||
// Determine whether provided shortcut is in provided category and
|
||||
// hide it if so
|
||||
foreach (var shortcut in category.Shortcuts) { |
||||
if (shortcut.Id == filteredShortcut.Id) { |
||||
shortcut.IsVisible = false; |
||||
} |
||||
|
||||
if(shortcut.IsVisible) { |
||||
isSubElementVisible = true; |
||||
} |
||||
} |
||||
|
||||
// Hide category if it doesn't have any visible sub-elements
|
||||
category.IsVisible = isSubElementVisible; |
||||
|
||||
return category.IsVisible; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Filters gestures matching provided key gesture template
|
||||
///
|
||||
/// Hides add-ins and sub-categories if there are no sub-elements left
|
||||
/// </summary>
|
||||
/// <param name="inputGestureTemplate">Gesture template which should match shortcut gesture partly to make it visible</param>
|
||||
/// <param name="mode">Filtering mode</param>
|
||||
public void FilterGesture(InputGesture inputGestureTemplate, GestureCompareMode mode) |
||||
{ |
||||
FilterGesture(new InputGestureCollection(new[] { inputGestureTemplate }), mode); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Filter gestures matching one of provided gesture templates
|
||||
///
|
||||
/// Hides add-ins and sub-categories if there are no sub-elements left
|
||||
/// </summary>
|
||||
/// <param name="inputGestureTemplateCollection">Collection of gesture templates which (atleast one) should match shortcut gesture partly to make it visible</param>
|
||||
/// <param name="mode">Filtering mode</param>
|
||||
public void FilterGesture(InputGestureCollection inputGestureTemplateCollection, GestureCompareMode mode) |
||||
{ |
||||
foreach (var entry in RootEntries) { |
||||
var subCategoryIsVisible = false; |
||||
|
||||
// Filter root addin and sub-elements
|
||||
var rootAddIn = entry as AddIn; |
||||
if (rootAddIn != null) { |
||||
foreach (var category in rootAddIn.Categories) { |
||||
if (FilterGesture(category, inputGestureTemplateCollection, mode)) { |
||||
subCategoryIsVisible = true; |
||||
} |
||||
} |
||||
|
||||
// Hide add-in if it doesn't have any visible sub-elements
|
||||
rootAddIn.IsVisible = subCategoryIsVisible; |
||||
} |
||||
|
||||
// Filter root category and sub-elements
|
||||
var rootCategory = entry as ShortcutCategory; |
||||
if (rootCategory != null) { |
||||
FilterGesture(rootCategory, inputGestureTemplateCollection, mode); |
||||
} |
||||
|
||||
// Filter root shortcut
|
||||
var rootShortcut = entry as Shortcut; |
||||
if (rootShortcut != null) { |
||||
rootShortcut.IsVisible = false; |
||||
foreach (InputGesture template in inputGestureTemplateCollection) { |
||||
if (template.IsTemplateForAny(new InputGestureCollection(rootShortcut.Gestures), mode)) { |
||||
rootShortcut.IsVisible = true; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Filter gestures matching one of provided gesture templates from templates collection
|
||||
/// </summary>
|
||||
/// <param name="category">Category to filter</param>
|
||||
/// <param name="inputGestureTemplateCollection">Collection of gesture templates which (atleast one) should match shortcut gesture partly to make it visible</param>
|
||||
/// <param name="mode">Filtering mode</param>
|
||||
/// <returns><code>true</code> if found any gestur matching provided template; otherwise <code>false</code></returns>
|
||||
private static bool FilterGesture(ShortcutCategory category, InputGestureCollection inputGestureTemplateCollection, GestureCompareMode mode) |
||||
{ |
||||
// Apply filter to sub-categories
|
||||
var isSubElementVisible = false; |
||||
foreach (var subCategory in category.SubCategories) { |
||||
if (FilterGesture(subCategory, inputGestureTemplateCollection, mode)) { |
||||
isSubElementVisible = true; |
||||
} |
||||
} |
||||
|
||||
// Apply filter to shortcuts
|
||||
foreach (var shortcut in category.Shortcuts) { |
||||
var gestureMatched = inputGestureTemplateCollection.ContainsTemplateForAny(new InputGestureCollection(shortcut.Gestures), mode); |
||||
|
||||
if (gestureMatched) { |
||||
shortcut.IsVisible = true; |
||||
isSubElementVisible = true; |
||||
} else { |
||||
shortcut.IsVisible = false; |
||||
} |
||||
} |
||||
|
||||
// Hide category if it doesn't have any visible sub-elements
|
||||
category.IsVisible = isSubElementVisible; |
||||
return category.IsVisible; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Filter addins, child categories and shortcuts where item name
|
||||
/// contains filter string
|
||||
///
|
||||
/// Hides add-ins and sub-categories if there are no sub-elements left
|
||||
/// </summary>
|
||||
/// <param name="filterString">Filter string</param>
|
||||
public void Filter(string filterString) |
||||
{ |
||||
foreach (var entry in RootEntries) { |
||||
var rootAddIn = entry as AddIn; |
||||
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
|
||||
var subCategoryIsVisible = false; |
||||
|
||||
foreach (var category in rootAddIn.Categories) { |
||||
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; |
||||
} |
||||
|
||||
var rootCategory = entry as ShortcutCategory; |
||||
if (rootCategory != null) { |
||||
Filter(rootCategory, filterString, null); |
||||
} |
||||
|
||||
var rootShortcut = entry as Shortcut; |
||||
if (rootShortcut != null) { |
||||
rootShortcut.IsVisible = filterString == null || rootShortcut.Name.IndexOf(filterString, StringComparison.InvariantCultureIgnoreCase) >= 0; |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Filter categorys and child elements where item name contains filter string
|
||||
/// </summary>
|
||||
/// <param name="category">Category to filter</param>
|
||||
/// <param name="filterString">Filter string</param>
|
||||
/// <param name="forseMatch">If set to true all sub-elements are visible</param>
|
||||
/// <returns></returns>
|
||||
private static bool Filter(ShortcutCategory category, string filterString, bool? forseMatch) |
||||
{ |
||||
// If category name matches filter show all sub-categories and shortcuts
|
||||
if (!string.IsNullOrEmpty(filterString) && category.Name.IndexOf(filterString, StringComparison.InvariantCultureIgnoreCase) >= 0) { |
||||
forseMatch = true; |
||||
} |
||||
|
||||
// Apply filter to sub-categories
|
||||
var isSubElementVisible = false; |
||||
foreach (var subCategory in category.SubCategories) { |
||||
if(Filter(subCategory, filterString, forseMatch)) { |
||||
isSubElementVisible = true; |
||||
} |
||||
} |
||||
|
||||
// Filter shortcuts which text match the filter
|
||||
foreach (var shortcut in category.Shortcuts) { |
||||
if ((forseMatch.HasValue && forseMatch.Value) || filterString == null || shortcut.Name.IndexOf(filterString, StringComparison.InvariantCultureIgnoreCase) >= 0) { |
||||
shortcut.IsVisible = true; |
||||
isSubElementVisible = true; |
||||
} else { |
||||
shortcut.IsVisible = false; |
||||
} |
||||
} |
||||
|
||||
// Show category if has sub elements, forced or matches search filter
|
||||
return category.IsVisible = (forseMatch.HasValue && forseMatch.Value && (category.SubCategories.Count > 0 || category.Shortcuts.Count > 0)) || isSubElementVisible; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
namespace ICSharpCode.ShortcutsManagement.Data |
||||
{ |
||||
/// <summary>
|
||||
/// Represents action <see cref="UserGestureProfile" /> action
|
||||
/// </summary>
|
||||
class UserGestureProfileAction |
||||
{ |
||||
/// <summary>
|
||||
/// Gets or sets action name
|
||||
/// </summary>
|
||||
public string Name |
||||
{ |
||||
get; |
||||
set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets or sets action text
|
||||
/// </summary>
|
||||
public object Text |
||||
{ |
||||
get; |
||||
set; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,57 @@
@@ -0,0 +1,57 @@
|
||||
<Window x:Class="ICSharpCode.ShortcutsManagement.Dialogs.CreateNewProfilePrompt" |
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
xmlns:core="http://icsharpcode.net/sharpdevelop/core" |
||||
xmlns:Presentation="clr-namespace:ICSharpCode.Core.Presentation;assembly=ICSharpCode.Core.Presentation" |
||||
Title="InputMessageBox" |
||||
ResizeMode="NoResize" |
||||
x:Name="_this" |
||||
SizeToContent="WidthAndHeight" > |
||||
<Window.Resources> |
||||
<ResourceDictionary> |
||||
<ResourceDictionary.MergedDictionaries> |
||||
<ResourceDictionary Source="Resources.xaml" /> |
||||
<ResourceDictionary> |
||||
<DataTemplate DataType="{x:Type Presentation:UserGestureProfile}"> |
||||
<TextBlock Text="{Binding Path=Text}" /> |
||||
</DataTemplate> |
||||
</ResourceDictionary> |
||||
</ResourceDictionary.MergedDictionaries> |
||||
</ResourceDictionary> |
||||
</Window.Resources> |
||||
<Grid> |
||||
<Grid.RowDefinitions> |
||||
<RowDefinition MinHeight="42" Height="42" /> |
||||
<RowDefinition Height="30" /> |
||||
<RowDefinition Height="Auto" /> |
||||
<RowDefinition Height="30" /> |
||||
</Grid.RowDefinitions> |
||||
<Grid.ColumnDefinitions> |
||||
<ColumnDefinition Width="Auto" MinWidth="52" /> |
||||
<ColumnDefinition /> |
||||
</Grid.ColumnDefinitions> |
||||
|
||||
<Image Grid.Column="0" Grid.Row="0" Source="../../Resources/info_mid.png" Height="32" Margin="5" /> |
||||
|
||||
<Label Grid.Column="1" Grid.Row="0" VerticalAlignment="Center" Padding="5"> |
||||
<TextBlock Text="{core:Localize ShortcutsManagement.CreateNewProfilePrompt.SpecifyProfileNameLabel}" /> |
||||
</Label> |
||||
<TextBox Grid.Column="1" Grid.Row="1" x:Name="profileNameTextBox" Text="{Binding Path=Text, ElementName=_this}" HorizontalAlignment="Stretch" Padding="3" Margin="5,5,20,5" /> |
||||
|
||||
<Grid Grid.Column="1" Grid.Row="2"> |
||||
<Grid.ColumnDefinitions> |
||||
<ColumnDefinition Width="Auto" /> |
||||
<ColumnDefinition Width="200" /> |
||||
</Grid.ColumnDefinitions> |
||||
<Label Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="3" Visibility="{Binding Path=BaseProfilesVisibility, ElementName=_this}" > |
||||
<TextBlock Text="{core:Localize ShortcutsManagement.CreateNewProfilePrompt.BasedOnLabel}" /> |
||||
</Label> |
||||
<ComboBox Grid.Column="1" Margin="5,5,20,5" ItemsSource="{Binding Path=AvailableBaseProfiles, ElementName=_this}" SelectedItem="{Binding Path=BaseProfile, ElementName=_this}" Visibility="{Binding Path=BaseProfilesVisibility, ElementName=_this}" /> |
||||
</Grid> |
||||
|
||||
<WrapPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="3" HorizontalAlignment="Center" Margin="5"> |
||||
<Button Content="{core:Localize Global.OKButtonText}" Width="70" Padding="15,0" Margin="5,0" Click="OkButton_Click" IsEnabled="{Binding Text, ElementName=profileNameTextBox, Converter={StaticResource NotNullOrEmptyConverter}}" /> |
||||
<Button Content="{core:Localize Global.CancelButtonText}" Padding="15,0" Margin="5,0" Click="CancelButton_Click" /> |
||||
</WrapPanel> |
||||
</Grid> |
||||
</Window> |
@ -0,0 +1,131 @@
@@ -0,0 +1,131 @@
|
||||
using System.Collections.Generic; |
||||
using System.Windows; |
||||
using ICSharpCode.Core.Presentation; |
||||
|
||||
namespace ICSharpCode.ShortcutsManagement.Dialogs |
||||
{ |
||||
/// <summary>
|
||||
/// Window prompting user to enter new or existing profile name
|
||||
/// and base profile
|
||||
/// </summary>
|
||||
public partial class CreateNewProfilePrompt : Window |
||||
{ |
||||
/// <summary>
|
||||
/// Identifies <see cref="BaseProfile"/> dependency property
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty BaseProfileProperty = DependencyProperty.Register( |
||||
"BaseProfile", |
||||
typeof(UserGestureProfile), |
||||
typeof(CreateNewProfilePrompt), |
||||
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender)); |
||||
|
||||
/// <summary>
|
||||
/// Gets or sets profile which new profile will be based on
|
||||
/// </summary>
|
||||
public UserGestureProfile BaseProfile |
||||
{ |
||||
get { |
||||
return (UserGestureProfile)GetValue(BaseProfileProperty); |
||||
} |
||||
set { |
||||
SetValue(BaseProfileProperty, value); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Identifies <see cref="BaseProfilesVisibility"/> dependency property
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty BaseProfilesVisibilityProperty = DependencyProperty.Register( |
||||
"BaseProfilesVisibility", |
||||
typeof(Visibility), |
||||
typeof(CreateNewProfilePrompt), |
||||
new FrameworkPropertyMetadata(Visibility.Visible, FrameworkPropertyMetadataOptions.AffectsRender)); |
||||
|
||||
/// <summary>
|
||||
/// Gets or sets base profiles combo box visibility
|
||||
/// </summary>
|
||||
public Visibility BaseProfilesVisibility |
||||
{ |
||||
get { |
||||
return (Visibility)GetValue(BaseProfilesVisibilityProperty); |
||||
} |
||||
set { |
||||
SetValue(BaseProfilesVisibilityProperty, value); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Identifies <see cref="AvailableBaseProfiles"/> dependency property
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty AvailableBaseProfilesProperty = DependencyProperty.Register( |
||||
"AvailableBaseProfiles", |
||||
typeof(ICollection<UserGestureProfile>), |
||||
typeof(CreateNewProfilePrompt), |
||||
new FrameworkPropertyMetadata(new List<UserGestureProfile>(), FrameworkPropertyMetadataOptions.AffectsRender)); |
||||
|
||||
/// <summary>
|
||||
/// Profiles user can choose from when selecting base profile
|
||||
/// </summary>
|
||||
public ICollection<UserGestureProfile> AvailableBaseProfiles |
||||
{ |
||||
get { |
||||
return (ICollection<UserGestureProfile>)GetValue(AvailableBaseProfilesProperty); |
||||
} |
||||
set { |
||||
SetValue(AvailableBaseProfilesProperty, value); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Identifies <see cref="Text"/> dependency property
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty TextProperty = DependencyProperty.Register( |
||||
"Text", |
||||
typeof(string), |
||||
typeof(CreateNewProfilePrompt), |
||||
new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsRender)); |
||||
|
||||
/// <summary>
|
||||
/// Gets or sets text entered in window text box
|
||||
/// </summary>
|
||||
public string Text |
||||
{ |
||||
get { |
||||
return (string)GetValue(TextProperty); |
||||
} |
||||
set { |
||||
SetValue(TextProperty, value); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Creates new instance of <see cref="CreateNewProfilePrompt"/>
|
||||
/// </summary>
|
||||
public CreateNewProfilePrompt() |
||||
{ |
||||
InitializeComponent(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Executed when user clicks on OK button
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender object</param>
|
||||
/// <param name="e">Event argument</param>
|
||||
private void OkButton_Click(object sender, RoutedEventArgs e) |
||||
{ |
||||
DialogResult = true; |
||||
Close(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Executed when user clicks on Cancel buttons
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender obect</param>
|
||||
/// <param name="e">Event argument</param>
|
||||
private void CancelButton_Click(object sender, RoutedEventArgs e) |
||||
{ |
||||
DialogResult = false; |
||||
Close(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,92 @@
@@ -0,0 +1,92 @@
|
||||
<UserControl x:Class="ICSharpCode.ShortcutsManagement.Dialogs.MultiKeyGestureTextBox" |
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
xmlns:Dialogs="clr-namespace:ICSharpCode.ShortcutsManagement.Dialogs" |
||||
x:Name="_this" > |
||||
|
||||
<UserControl.Resources> |
||||
<ResourceDictionary> |
||||
<ResourceDictionary.MergedDictionaries> |
||||
<ResourceDictionary Source="Resources.xaml" /> |
||||
</ResourceDictionary.MergedDictionaries> |
||||
</ResourceDictionary> |
||||
</UserControl.Resources> |
||||
|
||||
<Grid> |
||||
<Grid.RowDefinitions> |
||||
<RowDefinition /> |
||||
<RowDefinition Height="Auto" /> |
||||
</Grid.RowDefinitions> |
||||
|
||||
<Border Grid.Row="0" BorderThickness="{Binding ElementName=_this, Path=TextBoxBorderThickness}" SnapsToDevicePixels="True" BorderBrush="{x:Static SystemColors.ControlDarkBrush}"> |
||||
<Grid> |
||||
<Grid.ColumnDefinitions> |
||||
<ColumnDefinition /> |
||||
<ColumnDefinition Width="Auto" /> |
||||
</Grid.ColumnDefinitions> |
||||
|
||||
<TextBox Grid.Column="0" x:Name="shortcutTextBox" PreviewKeyDown="TextBox_PreviewKeyDown" TextChanged="shortcutTextBox_TextChanged" AcceptsTab="True" AcceptsReturn="True" VerticalAlignment="Top" Padding="5" BorderThickness="0" /> |
||||
<Button Grid.Column="1" x:Name="clearTextBox" VerticalAlignment="Center" Margin="5,0" Click="clearTextBox_Click"> |
||||
<Button.Template> |
||||
<ControlTemplate> |
||||
<Image Source="../../Resources/delete_small.png" Width="16" /> |
||||
</ControlTemplate> |
||||
</Button.Template> |
||||
</Button> |
||||
</Grid> |
||||
</Border> |
||||
|
||||
<!-- Notification panel under the textbox --> |
||||
<StackPanel Grid.Row="1" Orientation="Horizontal" Visibility="{Binding ElementName=_this, Path=NotificationVisibility}" Height="16" Margin="0"> |
||||
<Image Height="16" Margin="5,0,10,0"> |
||||
<Image.Style> |
||||
<Style> |
||||
<Style.Triggers> |
||||
<DataTrigger Value="{x:Static Dialogs:NotificationType.Valid}" Binding="{Binding ElementName=_this, Path=NotificationType}"> |
||||
<Setter Property="Image.Source" Value="../../Resources/tick_small.png" /> |
||||
</DataTrigger> |
||||
<DataTrigger Value="{x:Static Dialogs:NotificationType.Invalid}" Binding="{Binding ElementName=_this, Path=NotificationType}"> |
||||
<Setter Property="Image.Source" Value="../../Resources/warning_small.png" /> |
||||
</DataTrigger> |
||||
<DataTrigger Value="{x:Static Dialogs:NotificationType.Added}" Binding="{Binding ElementName=_this, Path=NotificationType}"> |
||||
<Setter Property="Image.Source" Value="../../Resources/plus_small.png" /> |
||||
</DataTrigger> |
||||
<DataTrigger Value="{x:Static Dialogs:NotificationType.Failed}" Binding="{Binding ElementName=_this, Path=NotificationType}"> |
||||
<Setter Property="Image.Source" Value="../../Resources/block_small.png"/> |
||||
</DataTrigger> |
||||
</Style.Triggers> |
||||
</Style> |
||||
</Image.Style> |
||||
</Image> |
||||
<TextBlock Text="{Binding ElementName=_this, Path=NotificationText}" VerticalAlignment="Center"> |
||||
<TextBlock.Style> |
||||
<Style> |
||||
<Style.Triggers> |
||||
<DataTrigger Value="{x:Static Dialogs:NotificationType.Valid}" Binding="{Binding ElementName=_this, Path=NotificationType}"> |
||||
<Setter Property="TextBlock.Foreground" Value="Green"/> |
||||
</DataTrigger> |
||||
<DataTrigger Value="{x:Static Dialogs:NotificationType.Invalid}" Binding="{Binding ElementName=_this, Path=NotificationType}"> |
||||
<Setter Property="TextBlock.Foreground" Value="Red"/> |
||||
</DataTrigger> |
||||
<DataTrigger Value="{x:Static Dialogs:NotificationType.Added}" Binding="{Binding ElementName=_this, Path=NotificationType}"> |
||||
<Setter Property="TextBlock.Foreground" Value="Green"/> |
||||
</DataTrigger> |
||||
<DataTrigger Value="{x:Static Dialogs:NotificationType.Failed}" Binding="{Binding ElementName=_this, Path=NotificationType}"> |
||||
<Setter Property="TextBlock.Foreground" Value="Red"/> |
||||
</DataTrigger> |
||||
</Style.Triggers> |
||||
</Style> |
||||
</TextBlock.Style> |
||||
</TextBlock> |
||||
<StackPanel.Style> |
||||
<Style> |
||||
<Style.Triggers> |
||||
<DataTrigger Value="{x:Static Dialogs:NotificationType.None}" Binding="{Binding ElementName=_this, Path=NotificationType}"> |
||||
<Setter Property="TextBlock.Visibility" Value="Hidden"/> |
||||
</DataTrigger> |
||||
</Style.Triggers> |
||||
</Style> |
||||
</StackPanel.Style> |
||||
</StackPanel> |
||||
</Grid> |
||||
</UserControl> |
@ -0,0 +1,294 @@
@@ -0,0 +1,294 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using System.Windows; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Input; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.Core.Presentation; |
||||
|
||||
namespace ICSharpCode.ShortcutsManagement.Dialogs |
||||
{ |
||||
/// <summary>
|
||||
/// Notification type enumeration
|
||||
/// </summary>
|
||||
public enum NotificationType |
||||
{ |
||||
/// <summary>
|
||||
/// A valid gesture is entered so far
|
||||
/// </summary>
|
||||
Valid, |
||||
|
||||
/// <summary>
|
||||
/// Gesture is being entered, but is not valid yet
|
||||
/// </summary>
|
||||
Invalid, |
||||
|
||||
/// <summary>
|
||||
/// Gesture was successfully added to gestures collection
|
||||
/// </summary>
|
||||
Added, |
||||
|
||||
/// <summary>
|
||||
/// Failed to add gesture to gestures collection
|
||||
/// </summary>
|
||||
Failed, |
||||
|
||||
/// <summary>
|
||||
/// Notification message is not displayed
|
||||
/// </summary>
|
||||
None |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Represents a textbox suited for entering key gestures
|
||||
/// </summary>
|
||||
public partial class MultiKeyGestureTextBox : UserControl |
||||
{ |
||||
/// <summary>
|
||||
/// Identifies <see cref="TextBoxBorderThickness"/> dependency property
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty TextBoxBorderThicknessProperty = DependencyProperty.Register( |
||||
"TextBoxBorderThickness", |
||||
typeof(int), |
||||
typeof(MultiKeyGestureTextBox), |
||||
new FrameworkPropertyMetadata(1, FrameworkPropertyMetadataOptions.AffectsRender)); |
||||
|
||||
/// <summary>
|
||||
/// Gets or sets text box border thickness
|
||||
/// </summary>
|
||||
public int TextBoxBorderThickness |
||||
{ |
||||
get { |
||||
return (int)GetValue(TextBoxBorderThicknessProperty); |
||||
} |
||||
set { |
||||
SetValue(TextBoxBorderThicknessProperty, value); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets <see cref="KeyGesture" /> entered in text box
|
||||
/// </summary>
|
||||
public KeyGesture Gesture |
||||
{ |
||||
get { |
||||
if (enteredKeyGestureSequence == null || enteredKeyGestureSequence.Count == 0) { |
||||
return null; |
||||
} |
||||
|
||||
if (enteredKeyGestureSequence.Count == 1) { |
||||
return new PartialKeyGesture(enteredKeyGestureSequence.First()); |
||||
} |
||||
|
||||
return new MultiKeyGesture(enteredKeyGestureSequence); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Occurs when gesture entered in text box changes
|
||||
/// </summary>
|
||||
public event EventHandler GestureChanged; |
||||
|
||||
/// <summary>
|
||||
/// Identifies <see cref="NotificationVisibility"/> dependency property
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty NotificationVisibilityProperty = DependencyProperty.Register( |
||||
"NotificationVisibility", |
||||
typeof(Visibility), |
||||
typeof(MultiKeyGestureTextBox), |
||||
new FrameworkPropertyMetadata(Visibility.Visible, FrameworkPropertyMetadataOptions.AffectsRender)); |
||||
|
||||
/// <summary>
|
||||
/// Gets or sets value which specifies whether notifications are displayed under textbox control
|
||||
/// </summary>
|
||||
public Visibility NotificationVisibility |
||||
{ |
||||
get { |
||||
return (Visibility)GetValue(NotificationVisibilityProperty); |
||||
} |
||||
set { |
||||
SetValue(NotificationVisibilityProperty, value); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Identifies <see cref="NotificationType"/> dependency property
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty NotificationTypeProperty = DependencyProperty.Register( |
||||
"NotificationType", |
||||
typeof(NotificationType), |
||||
typeof(MultiKeyGestureTextBox), |
||||
new FrameworkPropertyMetadata(NotificationType.None, FrameworkPropertyMetadataOptions.AffectsRender)); |
||||
|
||||
/// <summary>
|
||||
/// Gets or sets notification type
|
||||
/// </summary>
|
||||
public NotificationType NotificationType |
||||
{ |
||||
get { |
||||
return (NotificationType)GetValue(NotificationTypeProperty); |
||||
} |
||||
set { |
||||
SetValue(NotificationTypeProperty, value); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Identifies <see cref="NotificationText"/> dependency property
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty NotificationTextProperty = DependencyProperty.Register( |
||||
"NotificationText", |
||||
typeof(string), |
||||
typeof(MultiKeyGestureTextBox), |
||||
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender)); |
||||
|
||||
/// <summary>
|
||||
/// Gets or sets displayed notification text
|
||||
/// </summary>
|
||||
public string NotificationText |
||||
{ |
||||
get { |
||||
return (string)GetValue(NotificationTextProperty); |
||||
} |
||||
set { |
||||
SetValue(NotificationTextProperty, value); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Last entered chords
|
||||
/// </summary>
|
||||
private List<PartialKeyGesture> enteredKeyGestureSequence = new List<PartialKeyGesture>(); |
||||
|
||||
/// <summary>
|
||||
/// Time when last successfull chord was entered
|
||||
/// </summary>
|
||||
private DateTime lastEnterTime = DateTime.Now; |
||||
|
||||
/// <summary>
|
||||
/// Creates instance of <see cref="MultiKeyGestureTextBox"/>
|
||||
/// </summary>
|
||||
public MultiKeyGestureTextBox() |
||||
{ |
||||
InitializeComponent(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Displays notifications under gesture text box
|
||||
/// </summary>
|
||||
/// <param name="notificationText">Notification text</param>
|
||||
/// <param name="type">Notification type</param>
|
||||
public void DisplayNotification(string notificationText, NotificationType type) |
||||
{ |
||||
NotificationText = notificationText; |
||||
NotificationType = type; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Clears all text area, chords and hides notification
|
||||
/// </summary>
|
||||
public void Clear() |
||||
{ |
||||
enteredKeyGestureSequence = new List<PartialKeyGesture>(); |
||||
shortcutTextBox.Text = ""; |
||||
DisplayNotification("", NotificationType.None); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Executed when clicked on "Clear" button to the right from gesture text box
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender object</param>
|
||||
/// <param name="e"><see cref="RoutedEvent" /> supporting data</param>
|
||||
private void clearTextBox_Click(object sender, RoutedEventArgs e) |
||||
{ |
||||
Clear(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Executed when text inside textbox changes
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender object</param>
|
||||
/// <param name="e">Event arguments</param>
|
||||
void shortcutTextBox_TextChanged(object sender, TextChangedEventArgs e) |
||||
{ |
||||
if (GestureChanged != null) { |
||||
GestureChanged.Invoke(sender, new EventArgs()); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Raised before user presses any key inside text box
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender object</param>
|
||||
/// <param name="e">Event argument</param>
|
||||
private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e) |
||||
{ |
||||
e.Handled = true; |
||||
|
||||
// If a key is holded for a longer time key event is raised repeatedly.
|
||||
// We don't want to handle this kind of events
|
||||
if (e.IsRepeat) { |
||||
return; |
||||
} |
||||
|
||||
// If delete or backspace button is pressed
|
||||
if (e.Key == Key.Back || e.Key == Key.Delete) { |
||||
Clear(); |
||||
return; |
||||
} |
||||
|
||||
// Check whether time given for chord entry haven't expired yet
|
||||
if (DateTime.Now - lastEnterTime > MultiKeyGesture.DelayBetweenChords) { |
||||
if (enteredKeyGestureSequence.Count > 0) { |
||||
DisplayNotification(StringParser.Parse("${res:ShortcutsManagement.GestureTextBox.TimeExpired}"), NotificationType.Invalid); |
||||
} |
||||
|
||||
Clear(); |
||||
lastEnterTime = DateTime.Now; |
||||
} |
||||
|
||||
var partialKeyGesture = new PartialKeyGesture(e); |
||||
|
||||
var lastGesture = enteredKeyGestureSequence.Count > 0 ? enteredKeyGestureSequence.LastOrDefault() : null; |
||||
var isLastGestureSpecialKey = lastGesture != null && (lastGesture.Key >= Key.F1) && (lastGesture.Key <= Key.F24); |
||||
|
||||
var isLastGestureComplete = lastGesture != null && (lastGesture.Key != Key.None || isLastGestureSpecialKey); |
||||
var isContinuedGesture = lastGesture != null && partialKeyGesture.Modifiers - (partialKeyGesture.Modifiers ^ lastGesture.Modifiers) >= 0; |
||||
|
||||
// If continuing previous chord
|
||||
if (!isLastGestureComplete && isContinuedGesture) { |
||||
enteredKeyGestureSequence.RemoveAt(enteredKeyGestureSequence.Count - 1); |
||||
} else if (!isLastGestureComplete) { |
||||
// If previous chord is unfinished and second chord is already entered
|
||||
// start from scratch.
|
||||
DisplayNotification(StringParser.Parse("${res:ShortcutsManagement.GestureTextBox.SequenceIsNotCoherent}"), NotificationType.Invalid); |
||||
Clear(); |
||||
} |
||||
|
||||
// If successfully finished another chord give more time
|
||||
if (partialKeyGesture.Key != Key.None) { |
||||
lastEnterTime = DateTime.Now; |
||||
} |
||||
|
||||
enteredKeyGestureSequence.Add(partialKeyGesture); |
||||
|
||||
// Create a multi key gesture if entered more than one chord
|
||||
if (enteredKeyGestureSequence.Count > 0) { |
||||
var multiKeyGesture = new MultiKeyGesture(enteredKeyGestureSequence); |
||||
var multiKeyGestureString = new MultiKeyGestureConverter().ConvertToInvariantString(multiKeyGesture); |
||||
shortcutTextBox.Text = multiKeyGestureString; |
||||
} else { |
||||
Clear(); |
||||
} |
||||
|
||||
if (!enteredKeyGestureSequence[0].IsFull) { |
||||
DisplayNotification(StringParser.Parse("${res:ShortcutsManagement.GestureTextBox.FirstChordIsIncomplete}"), NotificationType.Invalid); |
||||
} else if (partialKeyGesture.Key == Key.None) { |
||||
DisplayNotification(StringParser.Parse("${res:ShortcutsManagement.GestureTextBox.LastChordIsIncomplete}"), NotificationType.Invalid); |
||||
} else { |
||||
DisplayNotification(StringParser.Parse("${res:ShortcutsManagement.GestureTextBox.GestureIsValid}"), NotificationType.Valid); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,181 @@
@@ -0,0 +1,181 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
xmlns:Converters="clr-namespace:ICSharpCode.ShortcutsManagement.Converters"> |
||||
|
||||
<Converters:GesturesListConverter x:Key="GesturesListConverter" /> |
||||
<Converters:ShortcutCategorySubElementsMergedConverter x:Key="ShortcutsTreeConverter" /> |
||||
<Converters:TypeNameConverter x:Key="TypeNameConverter" /> |
||||
<Converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" /> |
||||
<Converters:NotNullOrEmptyConverter x:Key="NotNullOrEmptyConverter" /> |
||||
<Converters:ProfileToStringConverter x:Key="ProfileToStringConverter" /> |
||||
<Converters:InputGestureConverter x:Key="InputGestureConverter" /> |
||||
<Converters:AddidionConverter x:Key="AddidionConverter" /> |
||||
|
||||
<LinearGradientBrush x:Key="SelectedItemBackground" StartPoint="0,0" EndPoint="0,1"> |
||||
<GradientStop Color="#3194FF" Offset="0" /> |
||||
<GradientStop Color="#3984F7" Offset="1" /> |
||||
</LinearGradientBrush> |
||||
<SolidColorBrush x:Key="SelectedItemForeground" Color="#FFF" /> |
||||
|
||||
<Style x:Key="RemoveButton" TargetType="Button"> |
||||
<Setter Property="Template"> |
||||
<Setter.Value> |
||||
<ControlTemplate TargetType="{x:Type Button}"> |
||||
<Image Source="..\..\Resources\16-square-red-remove.png" Width="16" SnapsToDevicePixels="True" /> |
||||
</ControlTemplate> |
||||
</Setter.Value> |
||||
</Setter> |
||||
</Style> |
||||
|
||||
<Style x:Key="AddButton" TargetType="Button"> |
||||
<Setter Property="ContentTemplate"> |
||||
<Setter.Value> |
||||
<DataTemplate> |
||||
<Image Source="..\..\Resources\add_correction_16x16.gif" Width="16" /> |
||||
</DataTemplate> |
||||
</Setter.Value> |
||||
</Setter> |
||||
</Style> |
||||
|
||||
|
||||
<Style x:Key="GesturesListBox" TargetType="{x:Type ListBoxItem}"> |
||||
<Setter Property="Template"> |
||||
<Setter.Value> |
||||
<ControlTemplate TargetType="ListBoxItem"> |
||||
<StackPanel> |
||||
<Border x:Name="ListBoxItemBorder" CornerRadius="6" Padding="10, 5" Background="{TemplateBinding Background}"> |
||||
<ContentPresenter /> |
||||
</Border> |
||||
</StackPanel> |
||||
<ControlTemplate.Triggers> |
||||
<Trigger Property="IsSelected" Value="True"> |
||||
<Setter TargetName="ListBoxItemBorder" Property="Panel.Background" Value="{StaticResource SelectedItemBackground}" /> |
||||
<Setter TargetName="ListBoxItemBorder" Property="TextElement.Foreground" Value="{StaticResource SelectedItemForeground}" /> |
||||
</Trigger> |
||||
</ControlTemplate.Triggers> |
||||
</ControlTemplate> |
||||
</Setter.Value> |
||||
</Setter> |
||||
</Style> |
||||
|
||||
|
||||
<Style x:Key="KeyToggleButton" TargetType="ToggleButton"> |
||||
<Setter Property="Focusable" Value="False"/> |
||||
<Setter Property="Template"> |
||||
<Setter.Value> |
||||
<ControlTemplate TargetType="ToggleButton"> |
||||
<Image x:Name="searchTypeImage" Source="..\..\Resources\key_enter.png" /> |
||||
<ControlTemplate.Triggers> |
||||
<Trigger Property="IsChecked" Value="True"> |
||||
<Setter Property="Source" TargetName="searchTypeImage" Value="..\..\Resources\key_enter_pressed.png"/> |
||||
</Trigger> |
||||
</ControlTemplate.Triggers> |
||||
</ControlTemplate> |
||||
</Setter.Value> |
||||
</Setter> |
||||
</Style> |
||||
|
||||
|
||||
|
||||
<Style x:Key="ExpandCollapseToggleStyle" TargetType="ToggleButton"> |
||||
<Setter Property="Focusable" Value="False"/> |
||||
<Setter Property="Template"> |
||||
<Setter.Value> |
||||
<ControlTemplate TargetType="ToggleButton"> |
||||
<Grid Width="15" Height="13" Background="Transparent"> |
||||
<Path x:Name="expandPath" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="1" Fill="#444" Data="M 4 0 L 8 4 L 4 8 Z"/> |
||||
</Grid> |
||||
<ControlTemplate.Triggers> |
||||
<Trigger Property="IsChecked" Value="True"> |
||||
<Setter Property="Data" TargetName="expandPath" Value="M 0 4 L 8 4 L 4 8 Z"/> |
||||
</Trigger> |
||||
</ControlTemplate.Triggers> |
||||
</ControlTemplate> |
||||
</Setter.Value> |
||||
</Setter> |
||||
</Style> |
||||
|
||||
<Style x:Key="ShortcutsTreeItem" TargetType="{x:Type TreeViewItem}"> |
||||
<Setter Property="Template"> |
||||
<Setter.Value> |
||||
<ControlTemplate TargetType="TreeViewItem"> |
||||
<Border Name="OuterBorder" BorderThickness="2" CornerRadius="8"> |
||||
<StackPanel> |
||||
<Border Name="InnerBorder" Background="White" BorderThickness="0.6" CornerRadius="8" Padding="0,6,6,6" > |
||||
<Grid> |
||||
<Grid.ColumnDefinitions> |
||||
<ColumnDefinition Width="19" /> |
||||
<ColumnDefinition /> |
||||
</Grid.ColumnDefinitions> |
||||
<ToggleButton Grid.Column="0" x:Name="treeViewItemToggleButton" Style="{StaticResource ExpandCollapseToggleStyle}" IsChecked="{Binding Path=IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press" /> |
||||
<ContentPresenter Name="PART_Header" ContentSource="Header" VerticalAlignment="Center" Grid.Column="1" /> |
||||
</Grid> |
||||
</Border> |
||||
<Border Name="ItemsBorder" Margin="20,0,0,0" > |
||||
<ItemsPresenter x:Name="ItemsHost" /> |
||||
</Border> |
||||
</StackPanel> |
||||
</Border> |
||||
<ControlTemplate.Triggers> |
||||
<Trigger Property="IsExpanded" Value="false"> |
||||
<Setter TargetName="ItemsHost" Property="Visibility" Value="Collapsed"/> |
||||
</Trigger> |
||||
<Trigger Property="HasItems" Value="false"> |
||||
<Setter TargetName="treeViewItemToggleButton" Property="Visibility" Value="Hidden"/> |
||||
</Trigger> |
||||
<DataTrigger Binding="{Binding Converter={StaticResource TypeNameConverter}}" Value="ShortcutCategory"> |
||||
<Setter TargetName="InnerBorder" Property="Panel.Background" Value="#DEDE00" /> |
||||
<Setter TargetName="InnerBorder" Property="TextElement.Foreground" Value="#FFFFFF" /> |
||||
</DataTrigger> |
||||
<DataTrigger Binding="{Binding Converter={StaticResource TypeNameConverter}}" Value="AddIn"> |
||||
<Setter TargetName="InnerBorder" Property="Panel.Background" Value="#AEFFA8" /> |
||||
<Setter TargetName="InnerBorder" Property="TextElement.Foreground" Value="#000000" /> |
||||
<Setter TargetName="OuterBorder" Property="Margin" Value="0" /> |
||||
</DataTrigger> |
||||
<DataTrigger Binding="{Binding Path=IsVisible}" Value="false"> |
||||
<Setter Property="Visibility" Value="Collapsed" /> |
||||
<Setter Property="IsEnabled" Value="False" /> |
||||
</DataTrigger> |
||||
<Trigger Property="IsSelected" Value="True"> |
||||
<Setter TargetName="InnerBorder" Property="Panel.Background" Value="{StaticResource SelectedItemBackground}" /> |
||||
<Setter TargetName="InnerBorder" Property="TextElement.Foreground" Value="{StaticResource SelectedItemForeground}" /> |
||||
</Trigger> |
||||
</ControlTemplate.Triggers> |
||||
</ControlTemplate> |
||||
</Setter.Value> |
||||
</Setter> |
||||
</Style> |
||||
|
||||
|
||||
<Style TargetType="{x:Type ListBoxItem}" x:Key="SeparatorStyle"> |
||||
<Setter Property="Template"> |
||||
<Setter.Value> |
||||
<ControlTemplate TargetType="{x:Type ListBoxItem}"> |
||||
<Separator HorizontalAlignment="Stretch" IsEnabled="false" Margin="5"/> |
||||
</ControlTemplate> |
||||
</Setter.Value> |
||||
</Setter> |
||||
</Style> |
||||
|
||||
<Style TargetType="{x:Type ListBoxItem}" x:Key="ProfileActionStyle"> |
||||
<Setter Property="Template"> |
||||
<Setter.Value> |
||||
<ControlTemplate TargetType="{x:Type ListBoxItem}"> |
||||
<TextBlock x:Name="textBlock" TextDecorations="Underline" Foreground="Blue" Margin="5" HorizontalAlignment="Left" TextAlignment="Left" > |
||||
<TextBlock.Style> |
||||
<Style> |
||||
<Style.Triggers> |
||||
<Trigger Property="TextBlock.IsMouseOver" Value="True"> |
||||
<Setter Property="TextBlock.Background" Value="{StaticResource SelectedItemBackground}" /> |
||||
</Trigger> |
||||
</Style.Triggers> |
||||
</Style> |
||||
</TextBlock.Style> |
||||
<ContentPresenter /> |
||||
</TextBlock> |
||||
</ControlTemplate> |
||||
</Setter.Value> |
||||
</Setter> |
||||
</Style> |
||||
|
||||
</ResourceDictionary> |
@ -0,0 +1,104 @@
@@ -0,0 +1,104 @@
|
||||
<Window x:Class="ICSharpCode.ShortcutsManagement.Dialogs.ShortcutManagementWindow" |
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
xmlns:core="http://icsharpcode.net/sharpdevelop/core" |
||||
xmlns:Dialogs="clr-namespace:ICSharpCode.ShortcutsManagement.Dialogs" |
||||
Title="{Binding Text}" |
||||
MinHeight="400" |
||||
MinWidth="400" |
||||
x:Name="_this"> |
||||
|
||||
<Window.Resources> |
||||
<ResourceDictionary> |
||||
<ResourceDictionary.MergedDictionaries> |
||||
<ResourceDictionary Source="Resources.xaml" /> |
||||
<ResourceDictionary> |
||||
<Style x:Key="ValidationTextBox" TargetType="TextBlock"></Style> |
||||
</ResourceDictionary> |
||||
</ResourceDictionary.MergedDictionaries> |
||||
</ResourceDictionary> |
||||
</Window.Resources> |
||||
|
||||
<Grid Margin="8"> |
||||
<Grid.ColumnDefinitions> |
||||
<ColumnDefinition Width="100" /> |
||||
<ColumnDefinition /> |
||||
</Grid.ColumnDefinitions> |
||||
<Grid.RowDefinitions> |
||||
<RowDefinition Height="50" /> |
||||
<RowDefinition /> |
||||
<RowDefinition Height="2" /> |
||||
<RowDefinition /> |
||||
<RowDefinition Height="30" /> |
||||
</Grid.RowDefinitions> |
||||
|
||||
<!-- Field for entering a gesture --> |
||||
<Label x:Name="shortcutLabel" Grid.Column="0" Grid.Row="0" Target="{Binding ElementName=gestureTextBox}" HorizontalAlignment="Right" VerticalAlignment="Top"> |
||||
<TextBlock TextWrapping="Wrap" Text="{core:Localize ShortcutsManagement.EnterGestureLabel}" /> |
||||
</Label> |
||||
<Grid Grid.Column="2" Grid.Row="0"> |
||||
<Grid.ColumnDefinitions> |
||||
<ColumnDefinition /> |
||||
<ColumnDefinition Width="40" /> |
||||
</Grid.ColumnDefinitions> |
||||
|
||||
<Dialogs:MultiKeyGestureTextBox x:Name="gestureTextBox" Grid.Column="0" Margin="3" TextBoxBorderThickness="1" /> |
||||
<Button x:Name="addGestureButton" Grid.Column="1" Style="{StaticResource AddButton}" Height="25" VerticalAlignment="Top" Margin="3" Click="addGestureButton_Click" /> |
||||
</Grid> |
||||
|
||||
<!-- List of gestures assigned to modified shortcut --> |
||||
<Label x:Name="otherShortcutsLabel" Grid.Column="0" Grid.Row="1" Target="{Binding ElementName=otherShortcutsListBox}" HorizontalAlignment="Right" VerticalAlignment="Top"> |
||||
<TextBlock TextWrapping="Wrap" Text="{core:Localize ShortcutsManagement.ShortcutGesturesLabel}" /> |
||||
</Label> |
||||
<ListBox x:Name="otherShortcutsListBox" Grid.Column="1" Grid.Row="1" ItemContainerStyle="{StaticResource GesturesListBox}" ItemsSource="{Binding Path=Gestures}" Margin="3" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> |
||||
<ListBox.ItemTemplate> |
||||
<DataTemplate DataType="{x:Type InputGesture}"> |
||||
<Grid> |
||||
<Grid.ColumnDefinitions> |
||||
<ColumnDefinition /> |
||||
<ColumnDefinition Width="20" /> |
||||
</Grid.ColumnDefinitions> |
||||
|
||||
<TextBlock Text="{Binding Converter={StaticResource InputGestureConverter}}" Grid.Column="0" /> |
||||
<Button x:Name="removeGestureButton" Style="{StaticResource RemoveButton}" Grid.Column="1" Visibility="Hidden" Click="removeGestureButton_Click" Tag="{Binding}" /> |
||||
</Grid> |
||||
<DataTemplate.Triggers> |
||||
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource TemplatedParent}}" Value="True"> |
||||
<Setter Property="Visibility" TargetName="removeGestureButton" Value="Visible" /> |
||||
</DataTrigger> |
||||
</DataTemplate.Triggers> |
||||
</DataTemplate> |
||||
</ListBox.ItemTemplate> |
||||
</ListBox> |
||||
|
||||
<GridSplitter Grid.Row="2" Grid.Column="2" ResizeDirection="Rows" |
||||
Width="Auto" |
||||
Height="2" |
||||
HorizontalAlignment="Stretch" |
||||
VerticalAlignment="Stretch" |
||||
Background="White" |
||||
Margin="0"/> |
||||
|
||||
<!-- List of shortcuts which have same gestures assigned to them --> |
||||
<Label x:Name="otherCommandsLabel" Grid.Row="3" Grid.Column="0" Target="{Binding ElementName=shortcutsManagementOptionsPanel}" HorizontalAlignment="Right" VerticalAlignment="Top"> |
||||
<TextBlock TextWrapping="Wrap" Text="{core:Localize ShortcutsManagement.SimilarShortcutsLabel}" /> |
||||
</Label> |
||||
<Dialogs:ShortcutsTreeView Grid.Row="3" Grid.Column="1" x:Name="shortcutsManagementOptionsPanel" IsSearchable="False" Padding="3" RemoveShortcutClick="shortcutsManagementOptionsPanel_RemoveShortcutClick" IsRemovableShortcutsEnabled="True" /> |
||||
|
||||
<!-- Defaults/Ok/Cancel buttons --> |
||||
|
||||
<!-- Reset/Ok/Cancel buttons --> |
||||
<Grid Grid.Column="2" Grid.Row="4"> |
||||
<Grid.ColumnDefinitions> |
||||
<ColumnDefinition Width="Auto" /> |
||||
<ColumnDefinition /> |
||||
<ColumnDefinition Width="Auto" /> |
||||
<ColumnDefinition Width="Auto" /> |
||||
</Grid.ColumnDefinitions> |
||||
|
||||
<Button Grid.Column="0" Click="DefaultButton_Click" x:Name="defaultButton" Margin="3" Width="80" Content="{core:Localize ShortcutsManagement.ShortcutManagementWindow.ResetToDefaults}" /> |
||||
<Button Grid.Column="2" Click="saveButton_Click" x:Name="saveButton" Margin="3" Width="80" Content="{core:Localize Global.OKButtonText}" /> |
||||
<Button Grid.Column="3" Click="resetButton_Click" x:Name="resetButton" Margin="3" Width="80" Content="{core:Localize Global.CancelButtonText}" /> |
||||
</Grid> |
||||
</Grid> |
||||
</Window> |
@ -0,0 +1,225 @@
@@ -0,0 +1,225 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using System.Windows; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Input; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.Core.Presentation; |
||||
using ICSharpCode.ShortcutsManagement.Data; |
||||
|
||||
namespace ICSharpCode.ShortcutsManagement.Dialogs |
||||
{ |
||||
/// <summary>
|
||||
/// This window allows user to modify shortcuts registered in application
|
||||
/// </summary>
|
||||
public partial class ShortcutManagementWindow : Window |
||||
{ |
||||
private HashSet<Shortcut> modifiedShortcuts = new HashSet<Shortcut>(); |
||||
|
||||
/// <summary>
|
||||
/// Gets modified shortcut copy
|
||||
/// </summary>
|
||||
public Shortcut Shortcut |
||||
{ |
||||
get; private set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets deep copy of addins list (including copies of categories and shortcuts)
|
||||
/// </summary>
|
||||
public ICollection<IShortcutTreeEntry> RootEntries |
||||
{ |
||||
get; private set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets list of modified shortcuts.
|
||||
///
|
||||
/// This list is used to optimize performance. Shortcuts not in this list are not saved.
|
||||
/// Allways add modified shortcut to this list.
|
||||
/// </summary>
|
||||
public ICollection<Shortcut> ModifiedShortcuts |
||||
{ |
||||
get { |
||||
return modifiedShortcuts; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Initializes new <see cref="ShortcutManagementWindow" /> class
|
||||
/// </summary>
|
||||
/// <param name="shortcut">Shortcut</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<IShortcutTreeEntry> rootEntries) |
||||
{ |
||||
Shortcut = shortcut; |
||||
RootEntries = rootEntries; |
||||
|
||||
shortcut.Gestures.CollectionChanged += Gestures_CollectionChanged; |
||||
ModifiedShortcuts.Add(shortcut); |
||||
DataContext = shortcut; |
||||
|
||||
InitializeComponent(); |
||||
|
||||
// Display similar shortcuts (Shortcuts with the same input gestures assigned to them)
|
||||
shortcutsManagementOptionsPanel.DataContext = rootEntries; |
||||
shortcutsManagementOptionsPanel.Loaded += delegate { FilterSimilarShortcuts(); }; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Filter shortcuts using same gestures as modified shortcut
|
||||
/// </summary>
|
||||
private void FilterSimilarShortcuts() |
||||
{ |
||||
var templates = new InputGestureCollection(Shortcut.Gestures); |
||||
|
||||
// Find shortcuts with same gesture and hide them.
|
||||
// Also hide modified shortcut from this list
|
||||
var finder = new ShortcutsFinder(RootEntries); |
||||
finder.FilterGesture(templates, GestureCompareMode.Conflicting); |
||||
finder.HideShortcut(Shortcut); |
||||
|
||||
shortcutsManagementOptionsPanel.ExpandAll(); |
||||
shortcutsManagementOptionsPanel.SelectFirstVisibleShortcut(false); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Executed when adding or removing gestures used to call modified shortcut
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender object</param>
|
||||
/// <param name="e">Event arguments</param>
|
||||
void Gestures_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) |
||||
{ |
||||
FilterSimilarShortcuts(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Executed when "Remove" button next to gesture is pressed
|
||||
/// </summary>
|
||||
/// <param name="sender">Object sender</param>
|
||||
/// <param name="e">Event arguments</param>
|
||||
private void removeGestureButton_Click(object sender, RoutedEventArgs e) |
||||
{ |
||||
var tag = ((Button) sender).Tag as InputGesture; |
||||
Shortcut.Gestures.Remove(tag); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Executed when "Add Gesture" button is clicked
|
||||
/// </summary>
|
||||
/// <param name="sender">Object sender</param>
|
||||
/// <param name="e">Event arguments</param>
|
||||
private void addGestureButton_Click(object sender, RoutedEventArgs e) |
||||
{ |
||||
// Check if any chords are entered
|
||||
if (gestureTextBox.Gesture == null) { |
||||
DisplayNotification(StringParser.Parse("${res:ShortcutsManagement.ModificationWindow.AdditionFailedNoChords}"), NotificationType.Failed); |
||||
return; |
||||
} |
||||
|
||||
// Check whether first chord is unfinished
|
||||
var partialKeyGesture = gestureTextBox.Gesture as PartialKeyGesture; |
||||
if (partialKeyGesture != null && !partialKeyGesture.IsFull) { |
||||
DisplayNotification(StringParser.Parse("${res:ShortcutsManagement.ModificationWindow.AdditionFailedFirstChordIsIncomplete}"), NotificationType.Failed); |
||||
return; |
||||
} |
||||
|
||||
// Check whether last chord is finished
|
||||
var multiKeyGesture = gestureTextBox.Gesture as MultiKeyGesture; |
||||
if (multiKeyGesture != null && multiKeyGesture.Chords.Last().Key == Key.None) { |
||||
DisplayNotification(StringParser.Parse("${res:ShortcutsManagement.ModificationWindow.AdditionFailedLastChordIsIncompete}"), NotificationType.Failed); |
||||
return; |
||||
} |
||||
|
||||
// Check whether gesture exist in shortcut gestures collection
|
||||
foreach (var existingGesture in Shortcut.Gestures) { |
||||
if (gestureTextBox.Gesture.IsTemplateFor(existingGesture, GestureCompareMode.ExactlyMatches)) { |
||||
DisplayNotification(StringParser.Parse("${res:ShortcutsManagement.ModificationWindow.AddingExistingGesture}"), NotificationType.Failed); |
||||
return; |
||||
} |
||||
} |
||||
|
||||
// Add gesture
|
||||
if (partialKeyGesture != null) { |
||||
try { |
||||
var keyGesture = new KeyGesture(partialKeyGesture.Key, partialKeyGesture.Modifiers); |
||||
Shortcut.Gestures.Add(keyGesture); |
||||
} catch (NotSupportedException) { |
||||
Shortcut.Gestures.Add(partialKeyGesture); |
||||
} |
||||
} else { |
||||
Shortcut.Gestures.Add(gestureTextBox.Gesture); |
||||
} |
||||
|
||||
DisplayNotification(StringParser.Parse("${res:ShortcutsManagement.ModificationWindow.AdditionIsSuccessfull}"), NotificationType.Added); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Executed when "Remove" button next to similar shortcut is pressed
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender object</param>
|
||||
/// <param name="e">Event argument</param>
|
||||
private void shortcutsManagementOptionsPanel_RemoveShortcutClick(object sender, RoutedRemoveShortcutEventArgs e) |
||||
{ |
||||
e.Handled = true; |
||||
|
||||
// Remove gestures registered in modified shortcut from deleted shortcut
|
||||
var removedShortcutGestures = e.RemovedShortcut.Gestures; |
||||
|
||||
for (int i = removedShortcutGestures.Count - 1; i >= 0; i--) { |
||||
foreach (var modifiedInputGesture in Shortcut.Gestures) { |
||||
if (removedShortcutGestures[i].IsTemplateFor(modifiedInputGesture, GestureCompareMode.StartsWith)) { |
||||
removedShortcutGestures.RemoveAt(i); |
||||
|
||||
modifiedShortcuts.Add(e.RemovedShortcut); |
||||
|
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
FilterSimilarShortcuts(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Save changes to shortcuts
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender object</param>
|
||||
/// <param name="e">Event arguments</param>
|
||||
private void saveButton_Click(object sender, RoutedEventArgs e) |
||||
{ |
||||
DialogResult = true; |
||||
|
||||
Close(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Display message describing shortcut addition result
|
||||
/// </summary>
|
||||
/// <param name="notificationText">Displayed message text</param>
|
||||
/// <param name="type">Message type</param>
|
||||
public void DisplayNotification(string notificationText, NotificationType type) |
||||
{ |
||||
gestureTextBox.NotificationText = notificationText; |
||||
gestureTextBox.NotificationType = type; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Execute this method when Reset button is clicked.
|
||||
///
|
||||
/// Modifications are not saved
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender object</param>
|
||||
/// <param name="e">Event arguments</param>
|
||||
private void resetButton_Click(object sender, RoutedEventArgs e) |
||||
{ |
||||
Close(); |
||||
} |
||||
|
||||
void DefaultButton_Click(object sender, RoutedEventArgs e) |
||||
{ |
||||
Shortcut.ResetToDefaults(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,52 @@
@@ -0,0 +1,52 @@
|
||||
<UserControl x:Class="ICSharpCode.ShortcutsManagement.Dialogs.ShortcutsManagementOptionsPanel" |
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
xmlns:core="http://icsharpcode.net/sharpdevelop/core" |
||||
xmlns:Dialogs="clr-namespace:ICSharpCode.ShortcutsManagement.Dialogs" |
||||
xmlns:Converters="clr-namespace:ICSharpCode.ShortcutsManagement.Converters" |
||||
xmlns:Presentation="clr-namespace:ICSharpCode.Core.Presentation;assembly=ICSharpCode.Core.Presentation" |
||||
xmlns:Data="clr-namespace:ICSharpCode.ShortcutsManagement.Data" |
||||
x:Name="_this"> |
||||
|
||||
<UserControl.Resources> |
||||
<ResourceDictionary> |
||||
<ResourceDictionary.MergedDictionaries> |
||||
<ResourceDictionary Source="Resources.xaml" /> |
||||
</ResourceDictionary.MergedDictionaries> |
||||
<Converters:ProfilesComboBoxItemStyleSelector x:Key="ProfilesComboBoxItemStyleSelector" /> |
||||
|
||||
<DataTemplate DataType="{x:Type Presentation:UserGestureProfile}"> |
||||
<TextBlock Text="{Binding Converter={StaticResource ProfileToStringConverter}}" Margin="5" /> |
||||
</DataTemplate> |
||||
|
||||
<DataTemplate DataType="{x:Type Data:UserGestureProfileAction}"> |
||||
<TextBlock Text="{Binding Path=Text}" /> |
||||
</DataTemplate> |
||||
</ResourceDictionary> |
||||
</UserControl.Resources> |
||||
|
||||
<Grid> |
||||
<Grid.RowDefinitions> |
||||
<RowDefinition Height="Auto" /> |
||||
<RowDefinition /> |
||||
</Grid.RowDefinitions> |
||||
|
||||
<WrapPanel HorizontalAlignment="Right" Grid.Row="0" Margin="0,3"> |
||||
<Label Content="{core:Localize ShortcutsManagement.ShortcutsManagementOptionsPanel.ProfilesLabel}" /> |
||||
<ComboBox |
||||
ItemContainerStyleSelector="{StaticResource ProfilesComboBoxItemStyleSelector}" |
||||
x:Name="profilesTextBox" |
||||
Width="150" |
||||
Height="30" |
||||
ItemsSource="{Binding}" |
||||
SelectionChanged="profilesTextBox_SelectionChanged" |
||||
/> |
||||
</WrapPanel> |
||||
|
||||
<Dialogs:ShortcutsTreeView Grid.Row="1" |
||||
x:Name="shortcutsManagementOptionsPanel" |
||||
IsSearchable="True" |
||||
ShortcutModified="shortcutsManagementOptionsPanel_ShortcutModified" |
||||
Height="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContentPresenter}}, Path=ActualHeight, Converter={StaticResource AddidionConverter}, ConverterParameter=-40}" /> |
||||
</Grid> |
||||
</UserControl> |
@ -0,0 +1,384 @@
@@ -0,0 +1,384 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Collections; |
||||
using System.Collections.ObjectModel; |
||||
using System.IO; |
||||
using System.Text.RegularExpressions; |
||||
using System.Windows; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Input; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.Core.Presentation; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.ShortcutsManagement.Data; |
||||
using Microsoft.Win32; |
||||
using ShortcutManagement=ICSharpCode.ShortcutsManagement.Data; |
||||
using MessageBox=System.Windows.MessageBox; |
||||
using Shortcut=ICSharpCode.ShortcutsManagement.Data.Shortcut; |
||||
using UserControl=System.Windows.Controls.UserControl; |
||||
|
||||
namespace ICSharpCode.ShortcutsManagement.Dialogs |
||||
{ |
||||
/// <summary>
|
||||
/// Interaction logic for ShortcutsManagementOptionsPanel.xaml
|
||||
/// </summary>
|
||||
public partial class ShortcutsManagementOptionsPanel : UserControl, IOptionPanel |
||||
{ |
||||
/// <summary>
|
||||
/// Identifies <see cref="SelectedProfile"/> dependency property
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty SelectedProfileProperty = DependencyProperty.Register( |
||||
"SelectedProfile", |
||||
typeof(UserGestureProfile), |
||||
typeof(ShortcutsManagementOptionsPanel), |
||||
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender)); |
||||
|
||||
/// <summary>
|
||||
/// Specifies text box border thickness
|
||||
/// </summary>
|
||||
public UserGestureProfile SelectedProfile |
||||
{ |
||||
get { |
||||
return (UserGestureProfile)GetValue(SelectedProfileProperty); |
||||
} |
||||
set { |
||||
SetValue(SelectedProfileProperty, value); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Stores shortcut entry to input binding convertion map
|
||||
/// </summary>
|
||||
private readonly MapTable<Shortcut, InputBindingInfo> shortcutsMap = new MapTable<Shortcut, InputBindingInfo>(); |
||||
|
||||
private List<IShortcutTreeEntry> rootEntries; |
||||
|
||||
private readonly List<UserGestureProfile> profiles = new List<UserGestureProfile>(); |
||||
|
||||
private readonly List<UserGestureProfile> removedProfiles = new List<UserGestureProfile>(); |
||||
|
||||
public ShortcutsManagementOptionsPanel() |
||||
{ |
||||
ResourceService.RegisterStrings("ICSharpCode.ShortcutsManagement.Resources.StringResources", GetType().Assembly); |
||||
|
||||
InitializeComponent(); |
||||
} |
||||
|
||||
public void LoadOptions() |
||||
{ |
||||
shortcutsManagementOptionsPanel.searchTextBox.Focus(); |
||||
|
||||
if (Directory.Exists(UserGestureProfileManager.UserGestureProfilesDirectory)) { |
||||
var dirInfo = new DirectoryInfo(UserGestureProfileManager.UserGestureProfilesDirectory); |
||||
var xmlFiles = dirInfo.GetFiles("*.xml"); |
||||
|
||||
foreach (var fileInfo in xmlFiles) { |
||||
var path = Path.Combine(UserGestureProfileManager.UserGestureProfilesDirectory, fileInfo.Name); |
||||
var profile = new UserGestureProfile(path); |
||||
profile.Load(); |
||||
profiles.Add(profile); |
||||
|
||||
if (UserGestureProfileManager.CurrentProfile != null && profile.Name == UserGestureProfileManager.CurrentProfile.Name) { |
||||
SelectedProfile = profile; |
||||
} |
||||
} |
||||
} |
||||
|
||||
BindProfiles(); |
||||
BindShortcuts(); |
||||
} |
||||
|
||||
private void BindProfiles() |
||||
{ |
||||
var profilesTextBoxItemsSource = new ArrayList(profiles); |
||||
|
||||
profilesTextBoxItemsSource.Add(new SeparatorData()); |
||||
|
||||
var deleteItem = new UserGestureProfileAction(); |
||||
deleteItem.Name = "Delete"; |
||||
deleteItem.Text = StringParser.Parse("${res:ShortcutsManagement.ShortcutsManagementOptionsPanel.ProfileDeleteAction}"); |
||||
profilesTextBoxItemsSource.Add(deleteItem); |
||||
|
||||
var loadItem = new UserGestureProfileAction(); |
||||
loadItem.Name = "Load"; |
||||
loadItem.Text = StringParser.Parse("${res:ShortcutsManagement.ShortcutsManagementOptionsPanel.ProfileLoadAction}"); |
||||
profilesTextBoxItemsSource.Add(loadItem); |
||||
|
||||
var createItem = new UserGestureProfileAction(); |
||||
createItem.Name = "Create"; |
||||
createItem.Text = StringParser.Parse("${res:ShortcutsManagement.ShortcutsManagementOptionsPanel.ProfileCreateAction}"); |
||||
profilesTextBoxItemsSource.Add(createItem); |
||||
|
||||
var renameItem = new UserGestureProfileAction(); |
||||
renameItem.Name = "Rename"; |
||||
renameItem.Text = StringParser.Parse("${res:ShortcutsManagement.ShortcutsManagementOptionsPanel.ProfileRenameAction}"); |
||||
profilesTextBoxItemsSource.Add(renameItem); |
||||
|
||||
var resetItem = new UserGestureProfileAction(); |
||||
resetItem.Name = "Reset"; |
||||
resetItem.Text = StringParser.Parse("${res:ShortcutsManagement.ShortcutsManagementOptionsPanel.ProfileResetAction}"); |
||||
profilesTextBoxItemsSource.Add(resetItem); |
||||
|
||||
profilesTextBox.DataContext = profilesTextBoxItemsSource; |
||||
|
||||
if (SelectedProfile != null) { |
||||
if(profilesTextBox.SelectedItem != SelectedProfile) { |
||||
profilesTextBox.Text = SelectedProfile.Text; |
||||
profilesTextBox.SelectedItem = SelectedProfile; |
||||
} |
||||
} else { |
||||
profilesTextBox.SelectedIndex = -1; |
||||
profilesTextBox.Text = ""; |
||||
} |
||||
} |
||||
|
||||
private void BindShortcuts() |
||||
{ |
||||
shortcutsMap.Clear(); |
||||
|
||||
// Root shortcut tree entries
|
||||
rootEntries = new List<IShortcutTreeEntry>(); |
||||
|
||||
// Stores SD input binding category to category section convertion map
|
||||
var categoriesMap = new MapTable<InputBindingCategory, ShortcutCategory>(); |
||||
|
||||
var unspecifiedCategory = new ShortcutCategory(StringParser.Parse("${res:ShortcutsManagement.UnspecifiedCategoryName}")); |
||||
rootEntries.Add(unspecifiedCategory); |
||||
|
||||
SDCommandManager.InputBindingCategories.Sort((c1, c2) => c1.Path.CompareTo(c2.Path)); |
||||
var parentCategories = new LinkedList<ShortcutCategory>(); |
||||
var previousDepth = 0; |
||||
foreach(var bindingCategory in SDCommandManager.InputBindingCategories) { |
||||
var categoryName = Regex.Replace(StringParser.Parse(bindingCategory.Text), @"&([^\s])", @"$1"); |
||||
var shortcutCategory = new ShortcutCategory(categoryName); |
||||
categoriesMap.Add(bindingCategory, shortcutCategory); |
||||
|
||||
AddCategory: |
||||
var currentDepth = bindingCategory.Path.Split('/').Length - 1; |
||||
if (currentDepth > previousDepth) { |
||||
previousDepth++; |
||||
|
||||
if (previousDepth > 1) { |
||||
parentCategories.Last.Value.SubCategories.Add(shortcutCategory); |
||||
} else { |
||||
rootEntries.Add(shortcutCategory); |
||||
} |
||||
|
||||
parentCategories.AddLast(shortcutCategory); |
||||
} else { |
||||
while (previousDepth >= currentDepth) { |
||||
parentCategories.RemoveLast(); |
||||
previousDepth--; |
||||
} |
||||
|
||||
goto AddCategory; |
||||
} |
||||
} |
||||
|
||||
var inputBindingInfos = SDCommandManager.FindInputBindingInfos(new BindingInfoTemplate(), null); |
||||
foreach (var inputBindingInfo in inputBindingInfos) { |
||||
// Get shortcut entry text. Normaly shortcut entry text is equal to routed command text
|
||||
// but this value can be overriden through InputBindingInfo.RoutedCommandText value
|
||||
var shortcutText = inputBindingInfo.RoutedCommand.Text; |
||||
if (!string.IsNullOrEmpty(inputBindingInfo.RoutedCommandText)) { |
||||
shortcutText = inputBindingInfo.RoutedCommandText; |
||||
} |
||||
|
||||
shortcutText = StringParser.Parse(shortcutText); |
||||
|
||||
// Some commands have "&" sign to mark alternative key used to call this command from menu
|
||||
// Strip this sign from shortcut entry text
|
||||
shortcutText = Regex.Replace(shortcutText, @"&([^\s])", @"$1"); |
||||
|
||||
var shortcut = new Shortcut(shortcutText, inputBindingInfo.ActiveGestures, inputBindingInfo.DefaultGestures.InputGesturesCollection); |
||||
shortcutsMap.Add(shortcut, inputBindingInfo); |
||||
|
||||
// Assign shortcut to all categories it is registered in
|
||||
var isAnyCategoriesResolved = true; |
||||
if (inputBindingInfo.Categories != null && inputBindingInfo.Categories.Count > 0) { |
||||
foreach (var bindingCategory in inputBindingInfo.Categories) { |
||||
ShortcutCategory shortcutCategory; |
||||
categoriesMap.TryMapForward(bindingCategory, out shortcutCategory); |
||||
if(shortcutCategory != null) { |
||||
shortcutCategory.Shortcuts.Add(shortcut); |
||||
isAnyCategoriesResolved = true; |
||||
} |
||||
} |
||||
} else { |
||||
isAnyCategoriesResolved = false; |
||||
} |
||||
|
||||
if(!isAnyCategoriesResolved) { |
||||
rootEntries.Add(shortcut); |
||||
} |
||||
} |
||||
|
||||
rootEntries.Sort(); |
||||
|
||||
foreach (var entry in rootEntries) { |
||||
entry.SortSubEntries(); |
||||
} |
||||
|
||||
new ShortcutsFinder(rootEntries).Filter(""); |
||||
shortcutsManagementOptionsPanel.DataContext = rootEntries; |
||||
} |
||||
|
||||
public bool SaveOptions() |
||||
{ |
||||
foreach (var profile in removedProfiles) { |
||||
if(File.Exists(profile.Path)) { |
||||
File.Delete(profile.Path); |
||||
} |
||||
} |
||||
|
||||
UserGestureProfileManager.CurrentProfile = SelectedProfile; |
||||
|
||||
profiles.ForEach(p => p.Save()); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
public object Owner |
||||
{ |
||||
get; set; |
||||
} |
||||
|
||||
public object Control |
||||
{ |
||||
get { |
||||
return this; |
||||
} |
||||
} |
||||
|
||||
private void profilesTextBox_SelectionChanged(object sender, SelectionChangedEventArgs e) |
||||
{ |
||||
if (e.AddedItems == null || e.AddedItems.Count == 0) { |
||||
return; |
||||
} |
||||
|
||||
var userGestureProfileAction = e.AddedItems[0] as UserGestureProfileAction; |
||||
if (userGestureProfileAction != null) { |
||||
if (userGestureProfileAction.Name == "Delete" && SelectedProfile != null) { |
||||
var result = MessageBox.Show( |
||||
StringParser.Parse("${res:ShortcutsManagement.ShortcutsManagementOptionsPanel.ConfirmDeleteProfileMessage}"), |
||||
StringParser.Parse("${res:ShortcutsManagement.ShortcutsManagementOptionsPanel.ConfirmDeleteProfileMessageWindowName}"), |
||||
MessageBoxButton.YesNo); |
||||
|
||||
if(MessageBoxResult.Yes == result) { |
||||
profiles.Remove(SelectedProfile); |
||||
removedProfiles.Add(SelectedProfile); |
||||
SelectedProfile = null; |
||||
} |
||||
} |
||||
|
||||
if (userGestureProfileAction.Name == "Rename" && SelectedProfile != null) { |
||||
var promptWindow = new CreateNewProfilePrompt(); |
||||
promptWindow.BaseProfilesVisibility = Visibility.Collapsed; |
||||
promptWindow.Text = SelectedProfile.Text; |
||||
promptWindow.ShowDialog(); |
||||
|
||||
SelectedProfile.Text = promptWindow.Text; |
||||
} |
||||
|
||||
if(userGestureProfileAction.Name == "Load") { |
||||
var openDialog = new OpenFileDialog(); |
||||
openDialog.Filter = "Xml files (*.xml)|*.xml"; |
||||
openDialog.FilterIndex = 1; |
||||
openDialog.RestoreDirectory = false; |
||||
if(true == openDialog.ShowDialog()) { |
||||
var loadedProfilePath = Path.Combine(UserGestureProfileManager.UserGestureProfilesDirectory, Guid.NewGuid().ToString()); |
||||
File.Copy(openDialog.FileName, loadedProfilePath); |
||||
var loadedProfile = new UserGestureProfile(loadedProfilePath); |
||||
loadedProfile.Load(); |
||||
|
||||
profiles.Add(loadedProfile); |
||||
SelectedProfile = loadedProfile; |
||||
} |
||||
} |
||||
|
||||
if (userGestureProfileAction.Name == "Reset") { |
||||
SelectedProfile = null; |
||||
} |
||||
|
||||
if(userGestureProfileAction.Name == "Create") { |
||||
var promptWindow = new CreateNewProfilePrompt(); |
||||
promptWindow.AvailableBaseProfiles = profiles; |
||||
promptWindow.ShowDialog(); |
||||
|
||||
if (promptWindow.DialogResult == true) { |
||||
UserGestureProfile newProfile; |
||||
|
||||
var newProfileName = Guid.NewGuid().ToString(); |
||||
newProfile = new UserGestureProfile( |
||||
Path.Combine(UserGestureProfileManager.UserGestureProfilesDirectory, newProfileName + ".xml"), |
||||
newProfileName, |
||||
promptWindow.Text, |
||||
false); |
||||
|
||||
if (promptWindow.BaseProfile != null) { |
||||
foreach(var pair in promptWindow.BaseProfile) { |
||||
newProfile[pair.Key] = pair.Value; |
||||
} |
||||
} |
||||
|
||||
profiles.Add(newProfile); |
||||
|
||||
SelectedProfile = newProfile; |
||||
} |
||||
} |
||||
} |
||||
|
||||
var userGestureProfile = e.AddedItems[0] as UserGestureProfile; |
||||
if (userGestureProfile != null && userGestureProfile != SelectedProfile) { |
||||
SelectedProfile = userGestureProfile; |
||||
} |
||||
|
||||
BindProfiles(); |
||||
BindShortcuts(); |
||||
} |
||||
|
||||
private void shortcutsManagementOptionsPanel_ShortcutModified(object sender, EventArgs e) |
||||
{ |
||||
var selectedShortcut = (Shortcut)shortcutsManagementOptionsPanel.shortcutsTreeView.SelectedItem; |
||||
|
||||
if(SelectedProfile == null) { |
||||
MessageBox.Show(StringParser.Parse("${res:ShortcutsManagement.ShortcutsManagementOptionsPanel.NoProfileSelectedMessage}")); |
||||
return; |
||||
} |
||||
|
||||
if(SelectedProfile.ReadOnly) { |
||||
MessageBox.Show(StringParser.Parse("${res:ShortcutsManagement.ShortcutsManagementOptionsPanel.SelectedProfileIsReadOnlyMessage}")); |
||||
return; |
||||
} |
||||
|
||||
Shortcut shortcutCopy = null; |
||||
|
||||
var cloner = new IShortcutTreeEntryCloner(); |
||||
var rootEntriesCopy = cloner.CloneShortcutTree(rootEntries); |
||||
foreach(var clonedEntry in rootEntriesCopy) { |
||||
if (shortcutCopy == null) { |
||||
shortcutCopy = clonedEntry.FindShortcut(selectedShortcut.Id); |
||||
} |
||||
} |
||||
|
||||
var shortcutManagementWindow = new ShortcutManagementWindow(shortcutCopy, rootEntriesCopy); |
||||
shortcutManagementWindow.ShowDialog(); |
||||
|
||||
if (SelectedProfile != null && shortcutManagementWindow.DialogResult.HasValue && shortcutManagementWindow.DialogResult.Value) { |
||||
// Move modifications from shortcut copies to original shortcut objects
|
||||
foreach (var relatedShortcutCopy in shortcutManagementWindow.ModifiedShortcuts) { |
||||
foreach (var rootEntry in rootEntries) { |
||||
var originalRelatedShortcut = rootEntry.FindShortcut(relatedShortcutCopy.Id); |
||||
if (originalRelatedShortcut != null) { |
||||
originalRelatedShortcut.Gestures.Clear(); |
||||
originalRelatedShortcut.Gestures.AddRange(relatedShortcutCopy.Gestures); |
||||
|
||||
var id = BindingInfoTemplate.CreateFromIBindingInfo(shortcutsMap.MapForward(originalRelatedShortcut)); |
||||
SelectedProfile[id] = relatedShortcutCopy.DoesUseDefault ? null : new InputGestureCollection(relatedShortcutCopy.Gestures); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,93 @@
@@ -0,0 +1,93 @@
|
||||
<UserControl x:Class="ICSharpCode.ShortcutsManagement.Dialogs.ShortcutsTreeView" |
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |
||||
xmlns:Data="clr-namespace:ICSharpCode.ShortcutsManagement.Data" |
||||
xmlns:Dialogs="clr-namespace:ICSharpCode.ShortcutsManagement.Dialogs" |
||||
xmlns:Extensions="clr-namespace:ICSharpCode.ShortcutsManagement.Extensions" |
||||
mc:Ignorable="d" |
||||
x:Name="_this" |
||||
d:DesignHeight="300" d:DesignWidth="300" > |
||||
|
||||
<UserControl.Resources> |
||||
<ResourceDictionary> |
||||
<ResourceDictionary.MergedDictionaries> |
||||
<ResourceDictionary Source="Resources.xaml" /> |
||||
</ResourceDictionary.MergedDictionaries> |
||||
</ResourceDictionary> |
||||
</UserControl.Resources> |
||||
|
||||
|
||||
|
||||
<Grid> |
||||
<Grid.RowDefinitions> |
||||
<RowDefinition /> |
||||
<RowDefinition Height="Auto" /> |
||||
</Grid.RowDefinitions> |
||||
|
||||
<!-- Tree view --> |
||||
<TreeView x:Name="shortcutsTreeView" ItemsSource="{Binding}" ItemContainerStyle="{StaticResource ShortcutsTreeItem}" Grid.Column="0" Grid.Row="0" FocusManager.FocusedElement="{Binding ElementName=searchTextBox}" PreviewKeyDown="shortcutsTreeView_PreviewKeyDown"> |
||||
<TreeView.Resources> |
||||
<!-- Tree view add-in data template --> |
||||
<HierarchicalDataTemplate DataType="{x:Type Data:AddIn}" ItemsSource="{Binding Path=Categories}" > |
||||
<TextBlock Text="{Binding Path=Name}" Extensions:TextBlockBehavior.SearchedText="{Binding ElementName=searchTextBox, Path=Text}" /> |
||||
</HierarchicalDataTemplate> |
||||
|
||||
<!-- Tree view category data template --> |
||||
<HierarchicalDataTemplate DataType="{x:Type Data:ShortcutCategory}" > |
||||
<HierarchicalDataTemplate.ItemsSource> |
||||
<MultiBinding Converter="{StaticResource ShortcutsTreeConverter}"> |
||||
<Binding Path="SubCategories" /> |
||||
<Binding Path="Shortcuts" /> |
||||
</MultiBinding> |
||||
</HierarchicalDataTemplate.ItemsSource> |
||||
|
||||
<TextBlock Text="{Binding Path=Name}" Extensions:TextBlockBehavior.SearchedText="{Binding ElementName=searchTextBox, Path=Text}" /> |
||||
</HierarchicalDataTemplate> |
||||
|
||||
<!-- Tree view shortcut data template --> |
||||
<HierarchicalDataTemplate DataType="{x:Type Data:Shortcut}" > |
||||
<Grid x:Name="shortcutEntry" MouseDown="shortcutEntry_MouseDown" Panel.Background="{Binding Panel.Background, RelativeSource={RelativeSource TemplatedParent}}"> |
||||
<Grid.ColumnDefinitions> |
||||
<ColumnDefinition /> |
||||
<ColumnDefinition /> |
||||
<ColumnDefinition Width="Auto" /> |
||||
</Grid.ColumnDefinitions> |
||||
|
||||
<TextBlock Text="{Binding Name}" Extensions: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" /> |
||||
<Button x:Name="removeShortcutButton" Style="{StaticResource RemoveButton}" Visibility="Hidden" Grid.Column="2" Tag="{Binding}" Click="removeShortcutButton_Click" SnapsToDevicePixels="True" /> |
||||
</Grid> |
||||
<HierarchicalDataTemplate.Triggers> |
||||
<DataTrigger Binding="{Binding ElementName=_this, Path=IsRemovableShortcutsEnabled}" Value="True"> |
||||
<Setter Property="Margin" TargetName="removeShortcutButton" Value="10,0,0,0" /> |
||||
</DataTrigger> |
||||
<MultiDataTrigger> |
||||
<MultiDataTrigger.Conditions> |
||||
<Condition Binding="{Binding ElementName=_this, Path=IsRemovableShortcutsEnabled}" Value="True" /> |
||||
<Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource TemplatedParent}}" Value="True" /> |
||||
</MultiDataTrigger.Conditions> |
||||
<Setter Property="Visibility" TargetName="removeShortcutButton" Value="Visible" /> |
||||
</MultiDataTrigger> |
||||
</HierarchicalDataTemplate.Triggers> |
||||
</HierarchicalDataTemplate> |
||||
</TreeView.Resources> |
||||
</TreeView> |
||||
|
||||
<!-- Search box --> |
||||
<Border x:Name="searchSection" CornerRadius="0,0,8,8" Padding="2" Background="#FFF" BorderBrush="#888" BorderThickness="1,0,1,1" Grid.Column="0" Grid.Row="1" Visibility="{Binding ElementName=_this, Path=IsSearchable, Converter={StaticResource BoolToVisibilityConverter}, ConverterParameter=Collapsed}"> |
||||
<Grid> |
||||
<Grid.ColumnDefinitions> |
||||
<ColumnDefinition /> |
||||
<ColumnDefinition Width="20" /> |
||||
</Grid.ColumnDefinitions> |
||||
|
||||
<TextBox Grid.Column="0" x:Name="searchTextBox" TextChanged="searchTextBox_TextChanged" BorderThickness="0" PreviewKeyDown="searchTextBox_PreviewKeyDown" /> |
||||
<Dialogs:MultiKeyGestureTextBox Grid.Column="0" x:Name="gestureTextBox" NotificationVisibility="Collapsed" TextBoxBorderThickness="0" Visibility="{Binding ElementName=searchTypeToggleButton, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}, ConverterParameter=Hidden}" GestureChanged="gestureTextBox_GestureChanged" PreviewKeyDown="searchTextBox_PreviewKeyDown" /> |
||||
|
||||
<ToggleButton x:Name="searchTypeToggleButton" Grid.Column="1" Style="{StaticResource KeyToggleButton}" ClickMode="Press" Click="searchTypeToggleButton_Click" /> |
||||
</Grid> |
||||
</Border> |
||||
</Grid> |
||||
</UserControl> |
@ -0,0 +1,320 @@
@@ -0,0 +1,320 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using System.Windows; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Input; |
||||
using ICSharpCode.Core.Presentation; |
||||
using ICSharpCode.ShortcutsManagement.Data; |
||||
using ICSharpCode.ShortcutsManagement.Extensions; |
||||
|
||||
namespace ICSharpCode.ShortcutsManagement.Dialogs |
||||
{ |
||||
/// <summary>
|
||||
/// This panel is used in SharpDevelop options window to manage shortcuts
|
||||
/// </summary>
|
||||
public partial class ShortcutsTreeView : UserControl |
||||
{ |
||||
/// <summary>
|
||||
/// Identifies <see cref="IsSearchable"/> dependency property
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty IsSearchableProperty = DependencyProperty.Register( |
||||
"IsSearchable", |
||||
typeof(Boolean), |
||||
typeof(ShortcutsTreeView), |
||||
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender)); |
||||
|
||||
/// <summary>
|
||||
/// Gets or sets property specifying whether shortcuts tree can be searched using part of the shortcut's name or
|
||||
/// gesture
|
||||
/// </summary>
|
||||
public Boolean IsSearchable |
||||
{ |
||||
get { |
||||
return (Boolean)GetValue(IsSearchableProperty); |
||||
} |
||||
set { |
||||
SetValue(IsSearchableProperty, value); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Identifies <see cref="IsRemovableShortcutsEnabled" /> dependency property
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty IsRemovableShortcutsEnabledProperty = DependencyProperty.Register( |
||||
"IsRemovableShortcutsEnabled", |
||||
typeof(Boolean), |
||||
typeof(ShortcutsTreeView), |
||||
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender)); |
||||
|
||||
/// <summary>
|
||||
/// Specify whether shortcuts can be removed from the tree.
|
||||
///
|
||||
/// If this value set to true <see cref="RemoveShortcutClick"/> will be Executed when
|
||||
/// shortcut is deleted
|
||||
/// </summary>
|
||||
public Boolean IsRemovableShortcutsEnabled |
||||
{ |
||||
get { |
||||
return (Boolean)GetValue(IsSearchableProperty); |
||||
} |
||||
set { |
||||
SetValue(IsSearchableProperty, value); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Occurs when user tries to remove shortcut from shortcuts tree
|
||||
/// </summary>
|
||||
public event RemoveShortcutRoutedHandler RemoveShortcutClick; |
||||
|
||||
/// <summary>
|
||||
/// List of add-ins containing shortcut categories and shortcuts
|
||||
/// </summary>
|
||||
private ICollection<IShortcutTreeEntry> RootEntries |
||||
{ |
||||
get { |
||||
return (ICollection<IShortcutTreeEntry>)DataContext; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Creates new instance of <see cref="ShortcutsTreeView" />
|
||||
/// </summary>
|
||||
public ShortcutsTreeView() |
||||
{ |
||||
InitializeComponent(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Selects first enabled shortcut in shortcut tree
|
||||
/// </summary>
|
||||
/// <param name="setFocus">Set focus to this shortcut entry</param>
|
||||
public void SelectFirstVisibleShortcut(bool setFocus) |
||||
{ |
||||
var path = new List<IShortcutTreeEntry>(); |
||||
foreach (var entry in RootEntries) { |
||||
if (entry != null && entry.IsVisible) { |
||||
path.Add(entry); |
||||
FindFirstVisibleItemPath(entry, path); |
||||
shortcutsTreeView.SelectItem(path.Cast<object>().ToList(), setFocus); |
||||
|
||||
return; |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Find path to first <see cref="IShortcutTreeEntry"/> with <see cref="IShortcutTreeEntry.IsVisible"/> true
|
||||
/// </summary>
|
||||
/// <param name="parent">Starting node</param>
|
||||
/// <param name="path">Accumulated path</param>
|
||||
private void FindFirstVisibleItemPath(IShortcutTreeEntry parent, List<IShortcutTreeEntry> path) |
||||
{ |
||||
// Find first visible add-in
|
||||
var addIn = parent as AddIn; |
||||
if(addIn != null) { |
||||
var selectedCategory = addIn.Categories.FirstOrDefault(a => a.IsVisible); |
||||
if (selectedCategory != null) { |
||||
path.Add(selectedCategory); |
||||
FindFirstVisibleItemPath(selectedCategory, path); |
||||
return; |
||||
} |
||||
} |
||||
|
||||
// Find first visible category
|
||||
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; |
||||
} |
||||
|
||||
// Find first visible shortcut
|
||||
var selectedShortcut = category.Shortcuts.FirstOrDefault(a => a.IsVisible); |
||||
if (selectedShortcut != null) { |
||||
path.Add(selectedShortcut); |
||||
FindFirstVisibleItemPath(selectedShortcut, path); |
||||
return; |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Expands all elements of the tree
|
||||
/// </summary>
|
||||
public void ExpandAll() |
||||
{ |
||||
shortcutsTreeView.SetExpandAll(true); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Executed when user starts to type inside shortcuts tree
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender object</param>
|
||||
/// <param name="e">Event arguments</param>
|
||||
private void shortcutsTreeView_PreviewKeyDown(object sender, KeyEventArgs e) |
||||
{ |
||||
// If not navigating tree set focus to search text box
|
||||
var keyboardDevice = (KeyboardDevice)e.Device; |
||||
if (keyboardDevice.Modifiers != ModifierKeys.None || Array.IndexOf(new[] { Key.Up, Key.Right, Key.Down, Key.Left }, e.Key) < 0) { |
||||
searchTextBox.Text = ""; |
||||
Keyboard.Focus(searchTextBox); |
||||
return; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Executed when user tries to remove a shortcut from shortcut tree
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender object</param>
|
||||
/// <param name="e">Event arguments</param>
|
||||
private void removeShortcutButton_Click(object sender, RoutedEventArgs e) |
||||
{ |
||||
if(RemoveShortcutClick != null) { |
||||
var removeButton = (Button) sender; |
||||
var routedRemoveShortcutEventArgs = new RoutedRemoveShortcutEventArgs(e.RoutedEvent, e.OriginalSource, (Shortcut)removeButton.Tag); |
||||
|
||||
// Forward event
|
||||
RemoveShortcutClick.Invoke(sender, routedRemoveShortcutEventArgs); |
||||
} |
||||
} |
||||
|
||||
|
||||
/// <summary>
|
||||
/// Executed when user changes text in search textbox
|
||||
/// </summary>
|
||||
/// <param name="sender">Object sender</param>
|
||||
/// <param name="e">Event arguments</param>
|
||||
private void searchTextBox_TextChanged(object sender, TextChangedEventArgs e) |
||||
{ |
||||
if (!searchTypeToggleButton.IsChecked.HasValue || searchTypeToggleButton.IsChecked.Value) return; |
||||
|
||||
new ShortcutsFinder(RootEntries).Filter(searchTextBox.Text); |
||||
|
||||
if (!string.IsNullOrEmpty(searchTextBox.Text)) { |
||||
SelectFirstVisibleShortcut(false); |
||||
} else { |
||||
shortcutsTreeView.SetExpandAll(false); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Executed when changing search type
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender object</param>
|
||||
/// <param name="e">Event arguments</param>
|
||||
private void searchTypeToggleButton_Click(object sender, RoutedEventArgs e) |
||||
{ |
||||
searchTextBox.Text = ""; |
||||
gestureTextBox.shortcutTextBox.Text = ""; |
||||
|
||||
new ShortcutsFinder(RootEntries).Filter(""); |
||||
shortcutsTreeView.SetExpandAll(false); |
||||
|
||||
if(!searchTypeToggleButton.IsChecked.HasValue || !searchTypeToggleButton.IsChecked.Value) { |
||||
Keyboard.Focus(searchTextBox); |
||||
} else { |
||||
Keyboard.Focus(gestureTextBox.shortcutTextBox); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Occurs when shortcut is modified
|
||||
/// </summary>
|
||||
public event EventHandler ShortcutModified; |
||||
|
||||
/// <summary>
|
||||
/// Executed when user presses a key inside search box
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender object </param>
|
||||
/// <param name="e">Event arguments</param>
|
||||
private void searchTextBox_PreviewKeyDown(object sender, KeyEventArgs e) |
||||
{ |
||||
var keyboardDevice = (KeyboardDevice)e.Device; |
||||
|
||||
// If Up/Down is pressed switch focus to shortcuts tree
|
||||
if (keyboardDevice.Modifiers == ModifierKeys.None && Array.IndexOf(new[] { Key.Up, Key.Down }, e.Key) >= 0) { |
||||
SelectFirstVisibleShortcut(true); |
||||
return; |
||||
} |
||||
|
||||
// If enter is pressed open shortcut configuration
|
||||
if (keyboardDevice.Modifiers == ModifierKeys.None && e.Key == Key.Enter && shortcutsTreeView.SelectedItem is Shortcut) { |
||||
e.Handled = true; |
||||
if(ShortcutModified != null) { |
||||
ShortcutModified.Invoke(sender, null); |
||||
} |
||||
|
||||
return; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Raised if gestures entered in gesture text box change
|
||||
/// </summary>
|
||||
/// <param name="sender">Senrer object</param>
|
||||
/// <param name="e">Event arguments</param>
|
||||
private void gestureTextBox_GestureChanged(object sender, EventArgs e) |
||||
{ |
||||
// Exit if filtering by text (Handled in searchTextBox_TextChanged)
|
||||
if (searchTypeToggleButton.IsChecked.HasValue && !searchTypeToggleButton.IsChecked.Value) { |
||||
return; |
||||
} |
||||
|
||||
if (gestureTextBox.Gesture != null) { |
||||
new ShortcutsFinder(RootEntries).FilterGesture(gestureTextBox.Gesture, GestureCompareMode.PartlyMatches); |
||||
SelectFirstVisibleShortcut(false); |
||||
} else { |
||||
new ShortcutsFinder(RootEntries).Filter(""); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Executed when user double click on shortcut tree item
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender object</param>
|
||||
/// <param name="e">Event arguments</param>
|
||||
private void shortcutEntry_MouseDown(object sender, MouseButtonEventArgs e) |
||||
{ |
||||
if (e.ChangedButton == MouseButton.Left && e.ClickCount == 2) { |
||||
if (shortcutsTreeView.SelectedItem is Shortcut) { |
||||
if(ShortcutModified != null) { |
||||
ShortcutModified.Invoke(sender, null); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
public delegate void RemoveShortcutRoutedHandler(object sender, RoutedRemoveShortcutEventArgs args); |
||||
|
||||
/// <summary>
|
||||
/// Contains state information and event data associated with <see cref="RemoveShortcutRoutedHandler"/>
|
||||
/// </summary>
|
||||
public class RoutedRemoveShortcutEventArgs : RoutedEventArgs |
||||
{ |
||||
/// <summary>
|
||||
/// Reference to shortcut being removed
|
||||
/// </summary>
|
||||
public Shortcut RemovedShortcut |
||||
{ |
||||
get; |
||||
private set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Creates new isntance of <see cref="RoutedRemoveShortcutEventArgs" />
|
||||
/// </summary>
|
||||
/// <param name="routedEvent">Associated routed event</param>
|
||||
/// <param name="source">Source which will be reported when event is handled</param>
|
||||
/// <param name="removedShortcut">Shortcut being removed</param>
|
||||
public RoutedRemoveShortcutEventArgs(RoutedEvent routedEvent, object source, Shortcut removedShortcut) |
||||
: base(routedEvent, source) |
||||
{ |
||||
RemovedShortcut = removedShortcut; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,90 @@
@@ -0,0 +1,90 @@
|
||||
using System.Text.RegularExpressions; |
||||
using System.Windows; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Documents; |
||||
using System.Windows.Media; |
||||
|
||||
namespace ICSharpCode.ShortcutsManagement.Extensions |
||||
{ |
||||
/// <summary>
|
||||
/// Contains <see cref="TextBlock"/> attached properties
|
||||
/// </summary>
|
||||
public static class TextBlockBehavior |
||||
{ |
||||
/// <summary>
|
||||
/// Gets "TextBlockBehavior.SearchedText" attached property value
|
||||
/// </summary>
|
||||
/// <param name="textBlock">Attached property host</param>
|
||||
/// <returns>Attached property value</returns>
|
||||
public static string GetSearchedText(TextBlock textBlock) |
||||
{ |
||||
return (string)textBlock.GetValue(SearchedTextProperty); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Set "TextBlockBehavior.SearchedText" attached property value
|
||||
/// </summary>
|
||||
/// <param name="textBlock">Attached property host</param>
|
||||
/// <param name="value">New attached property value</param>
|
||||
public static void SetSearchedText(TextBlock textBlock, string value) |
||||
{ |
||||
textBlock.SetValue(SearchedTextProperty, value); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Identifies SearchedText dependency property
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty SearchedTextProperty = |
||||
DependencyProperty.RegisterAttached( |
||||
"SearchedText", |
||||
typeof(string), |
||||
typeof(TextBlockBehavior), |
||||
new UIPropertyMetadata(null, OnSearchedTextChanged)); |
||||
|
||||
/// <summary>
|
||||
/// On SearchedText changed highlight text in TextBlock which matches
|
||||
/// attached property value
|
||||
/// </summary>
|
||||
/// <param name="depObj"></param>
|
||||
/// <param name="e"></param>
|
||||
private static void OnSearchedTextChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e) |
||||
{ |
||||
var textBlock = (TextBlock) depObj; |
||||
var textBlockText = textBlock.Text; |
||||
|
||||
// Remove all text from text block
|
||||
textBlock.Inlines.Clear(); |
||||
|
||||
// Split text contained in text block to three parts: before the match, the match and after the match
|
||||
var matches = Regex.Matches(textBlockText, @"(.*)(" + Regex.Escape((string)e.NewValue) + @")(.*)", RegexOptions.IgnoreCase); |
||||
if (matches.Count > 0) { |
||||
foreach (Match match in matches) { |
||||
// Add what is found before match back to the block without modifications
|
||||
var matchedTextPrefix = match.Groups[1].Value; |
||||
if (!string.IsNullOrEmpty(matchedTextPrefix)) { |
||||
textBlock.Inlines.Add(new Run(matchedTextPrefix)); |
||||
} |
||||
|
||||
// Higlight the match and add back to textblock
|
||||
var matchedText = match.Groups[2].Value; |
||||
if (!string.IsNullOrEmpty(matchedText)) { |
||||
var matchedRun = new Run(matchedText); |
||||
|
||||
matchedRun.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#CEDEF7")); |
||||
matchedRun.Foreground = new SolidColorBrush((Color) ColorConverter.ConvertFromString("#000000")); |
||||
textBlock.Inlines.Add(matchedRun); |
||||
} |
||||
|
||||
// Add what is found after match back to the block without modifications
|
||||
var matchedTextSuffix = match.Groups[3].Value; |
||||
if (!string.IsNullOrEmpty(matchedTextSuffix)) { |
||||
textBlock.Inlines.Add(new Run(matchedTextSuffix)); |
||||
} |
||||
} |
||||
} else { |
||||
// If filter string is not found put the original text back without modifications
|
||||
textBlock.Inlines.Add(new Run(textBlockText)); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,81 @@
@@ -0,0 +1,81 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using System.Reflection; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Controls.Primitives; |
||||
using System.Windows.Input; |
||||
|
||||
namespace ICSharpCode.ShortcutsManagement.Extensions |
||||
{ |
||||
/// <summary>
|
||||
/// <see cref="TreeView"/> extention methods
|
||||
/// </summary>
|
||||
public static class TreeViewExtensions |
||||
{ |
||||
/// <summary>
|
||||
/// Expand TreeView items according to provided path and select element
|
||||
/// on the lowest level
|
||||
/// </summary>
|
||||
/// <param name="parentContainer">TreeView instance</param>
|
||||
/// <param name="path">Path to the selected item</param>
|
||||
/// <param name="setFocus"></param>
|
||||
public static void SelectItem(this ItemsControl parentContainer, List<object> path, bool setFocus) |
||||
{ |
||||
if(path == null || path.Count == 0) { |
||||
return; |
||||
} |
||||
|
||||
var head = path.First(); |
||||
var tail = path.GetRange(1, path.Count - 1); |
||||
|
||||
// Get TreeViewItem which wraps first element from path
|
||||
var itemContainer = parentContainer.ItemContainerGenerator.ContainerFromItem(head) as TreeViewItem; |
||||
|
||||
if (itemContainer != null && itemContainer.Items.Count == 0) { |
||||
// If item container doesn't have any sub-elements select it
|
||||
itemContainer.IsSelected = true; |
||||
|
||||
if(setFocus) { |
||||
Keyboard.Focus(itemContainer); |
||||
} |
||||
|
||||
var selectMethod = typeof(TreeViewItem).GetMethod("Select", BindingFlags.NonPublic | BindingFlags.Instance); |
||||
selectMethod.Invoke(itemContainer, new object[] { true }); |
||||
} else if (itemContainer != null) { |
||||
// If item container have sub-elements expand it and select item from this container
|
||||
itemContainer.IsExpanded = true; |
||||
|
||||
if (itemContainer.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated) { |
||||
// If item container is not generated yet register a delegate which would be called when container is generated
|
||||
itemContainer.ItemContainerGenerator.StatusChanged += delegate { |
||||
SelectItem(itemContainer, tail, setFocus); |
||||
}; |
||||
} else { |
||||
// If item container already generated select sub-element from this container
|
||||
SelectItem(itemContainer, tail, setFocus); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Expand/Collapse all tree view items
|
||||
/// </summary>
|
||||
/// <param name="parentContainer">TreeView or TreeViewItem</param>
|
||||
/// <param name="value">True - expand, False - collapse</param>
|
||||
public static void SetExpandAll(this ItemsControl parentContainer, bool value) |
||||
{ |
||||
foreach (Object item in parentContainer.Items) { |
||||
var currentContainer = parentContainer.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem; |
||||
if (currentContainer != null && currentContainer.Items.Count > 0) { |
||||
currentContainer.IsExpanded = value; |
||||
if (currentContainer.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated) { |
||||
currentContainer.ItemContainerGenerator.StatusChanged += delegate { SetExpandAll(currentContainer, value); }; |
||||
} else { |
||||
SetExpandAll(currentContainer, value); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
|
||||
<ResourceDictionary |
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
||||
|
||||
</ResourceDictionary> |
@ -0,0 +1,110 @@
@@ -0,0 +1,110 @@
|
||||
using System; |
||||
|
||||
namespace ICSharpCode.Core |
||||
{ |
||||
/// <summary>
|
||||
/// Describes <see cref="ICSharpCode.Core.Presentation.CommandBindingInfo" />
|
||||
/// </summary>
|
||||
public class CommandBindingInfoDescriptor |
||||
{ |
||||
/// <summary>
|
||||
/// Gets codon used to create this descriptor
|
||||
/// </summary>
|
||||
public Codon Codon { |
||||
get; private set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets full name of the command class (should implement ICSharpCode.Core.ICommand or System.Window.Input.ICommand) containing user instructions associated with
|
||||
/// <see cref="System.Windows.Input.CommandBinding" />
|
||||
/// </summary>
|
||||
public string Class { |
||||
get; private set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets name of <see cref="System.Window.Input.RoutedUICommand" /> associated with descriptor
|
||||
/// A name should be associated to a command in code using <see cref="ICSharpCode.Core.Presentation.CommandManager" />
|
||||
/// </summary>
|
||||
public string Command { |
||||
get; private set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets overriden routed command text (string visible to user)
|
||||
///
|
||||
/// If not provided <see cref="System.Window.Input.RoutedUICommand.Text" /> property value is used
|
||||
/// </summary>
|
||||
public string CommandText { |
||||
get; private set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets name of binding owner type name.
|
||||
///
|
||||
/// A name can be assigned to type in code using <see cref="ICSharpCode.Core.Presentation.CommandManager" />.
|
||||
/// If this property is set then <see cref="OwnerTypeName" /> property can be ignored
|
||||
/// If neither owner type nor owner instance is specified default owner type is applied
|
||||
/// </summary>
|
||||
public string OwnerInstanceName { |
||||
get; private set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Name of binding owner instance name.
|
||||
///
|
||||
/// A name can be assigned to instance in code using <see cref="ICSharpCode.Core.Presentation.CommandManager" />.
|
||||
/// If this property is set then <see cref="OwnerInstanceName" /> property can be ignored
|
||||
/// If neither owner type nor owner instance is specified default owner type is applied
|
||||
/// </summary>
|
||||
public string OwnerTypeName { |
||||
get; private set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets gestures associated with created <see cref="ICSharpCode.Core.Presentation.InputBindingInfo" />
|
||||
///
|
||||
/// Optional, if provided input binding info with the same owner will be created
|
||||
/// </summary>
|
||||
public string Gestures { |
||||
get; private set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets list of paths to input binding categories associated with created <see cref="ICSharpCode.Core.Presentation.InputBindingInfo" /> (separated by comma)
|
||||
///
|
||||
/// Can only be used together with <see cref="Gestures" /> property
|
||||
/// </summary>
|
||||
public string Categories { |
||||
get; private set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Lazy loading
|
||||
///
|
||||
/// If true add-in referenced assemblies are loaded when command is invoked.
|
||||
/// Otherwise command can't be invoked until addin is loaded
|
||||
/// </summary>
|
||||
public bool Lazy { |
||||
get { |
||||
return Codon.Properties["lazy"] == "1" || Codon.Properties["lazy"] == "true"; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Creates new instance of <see cref="CommandBindingInfoDescriptor" />
|
||||
/// </summary>
|
||||
/// <param name="codon">Reference to codon used to create this descriptor</param>
|
||||
public CommandBindingInfoDescriptor(Codon codon) |
||||
{ |
||||
Codon = codon; |
||||
Class = Codon.Properties["class"]; |
||||
Command = Codon.Properties["command"]; |
||||
CommandText = Codon.Properties["commandtext"]; |
||||
OwnerInstanceName = Codon.Properties["ownerinstance"]; |
||||
OwnerTypeName = Codon.Properties["ownertype"]; |
||||
Gestures = Codon.Properties["gestures"]; |
||||
Categories = Codon.Properties["categories"]; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,76 @@
@@ -0,0 +1,76 @@
|
||||
using System; |
||||
|
||||
namespace ICSharpCode.Core |
||||
{ |
||||
/// <attribute name="command" use="required">
|
||||
/// Name of System.Window.Input.RoutedUICommand associated with built CommandBindingInfoDescriptor
|
||||
/// The name should be first registered in code using ICSharpCode.Core.Presentation.CommandManager
|
||||
/// or in addin file using RoutedUICommand node
|
||||
/// </attribute>
|
||||
/// <attribute name="class" use="required">
|
||||
/// Full name of the command class (should implement ICSharpCode.Core.ICommand or System.Window.Input.ICommand) containing user instructions associated with
|
||||
/// System.Windows.Input.CommandBinding
|
||||
/// </attribute>
|
||||
/// <attribute name="ownertype" use="optional">
|
||||
/// Name of binding owner type.
|
||||
///
|
||||
/// A name can be assigned to type in code using ICSharpCode.Core.Presentation.CommandManager.
|
||||
/// If this attribute is used "ownerinstance" attribute cannot be used
|
||||
/// If neither owner type nor owner instance is specified default owner type is applied
|
||||
/// </attribute>
|
||||
/// <attribute name="ownertype" use="optional">
|
||||
/// Name of binding owner instance.
|
||||
///
|
||||
/// A name can be assigned to instance in code using ICSharpCode.Core.Presentation.CommandManager.
|
||||
/// If this attribute is used "ownertype" attribute cannot be used
|
||||
/// If neither owner type nor owner instance is specified default owner type is applied
|
||||
/// </attribute>
|
||||
/// <attribute name="lazy" use="optional" enum="1;0;true;false">
|
||||
/// Use lazy loading.
|
||||
/// </attribute>
|
||||
/// <attribute name="gestures" use="optional">
|
||||
/// Create input bindings assigned to the same owner type or owner instance and associated
|
||||
/// with the same System.Window.Input.RoutedUICommand
|
||||
/// </attribute>
|
||||
/// <attribute name="commandtext" use="optional">
|
||||
/// Text displayed to user when managing input bindings (shortcuts)
|
||||
///
|
||||
/// If this attribute is not used System.Window.Input.RoutedUICommand.Text property is used
|
||||
/// This attribute can only be used together with "gestures" attribute
|
||||
/// </attribute>
|
||||
/// <attribute name="categories" use="optional">
|
||||
/// List of paths to input binding categories associated with created input binding info (separated by comma)
|
||||
///
|
||||
/// Input binding categories can be created in code using ICSharpCode.Core.Presentation.CommandManager or by using InputBindingCategory node in addin file
|
||||
/// Input binding categories are used to group shortcuts into separate sections when displaying to user.
|
||||
/// This attribute can only be used together with "gestures" attribute
|
||||
/// </attribute>
|
||||
/// <usage>Only in /SharpDevelop/Workbench/CommandBindings</usage>
|
||||
/// <returns>
|
||||
/// CommandBindingInfoDescriptor object
|
||||
/// </returns>
|
||||
/// <summary>
|
||||
/// Registers ICSharpCode.Core.Presentation.CommandBindingInfo with specified pa
|
||||
/// </summary>
|
||||
public class CommandBindingInfoDoozer : IDoozer |
||||
{ |
||||
/// <inheritdoc />
|
||||
public bool HandleConditions { |
||||
get { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Builds instance of <see cref="CommandBindingInfoDescriptor" /> from codon
|
||||
/// </summary>
|
||||
/// <param name="caller">Caller object</param>
|
||||
/// <param name="codon">Codon</param>
|
||||
/// <param name="subItems">Codon sub-items</param>
|
||||
/// <returns>Instance of <see cref="CommandBindingInfoDescriptor" /></returns>
|
||||
public object BuildItem(object caller, Codon codon, System.Collections.ArrayList subItems) |
||||
{ |
||||
return new CommandBindingInfoDescriptor(codon); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,45 @@
@@ -0,0 +1,45 @@
|
||||
using System; |
||||
using System.Linq; |
||||
using System.Collections.Generic; |
||||
|
||||
namespace ICSharpCode.Core |
||||
{ |
||||
/// <summary>
|
||||
/// Describes <see cref="ICSharpCode.Core.Presentation.CommandBindingInfo" />
|
||||
/// </summary>
|
||||
public class InputBindingCategoryDescriptor |
||||
{ |
||||
/// <summary>
|
||||
/// Gets category Id used to create category path
|
||||
/// </summary>
|
||||
public string Id { |
||||
get; private set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets category name displayed to user
|
||||
/// </summary>
|
||||
public string Text { |
||||
get; private set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets children category descriptors
|
||||
/// </summary>
|
||||
public List<InputBindingCategoryDescriptor> Children { |
||||
get; private set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Creates instance of <see cref="InputBindingCategoryDescriptor" />
|
||||
/// </summary>
|
||||
/// <param name="codon">Reference to codon used to create this descriptor</param>
|
||||
/// <param name="subItems">List of sub-category descriptors</param>
|
||||
public InputBindingCategoryDescriptor(Codon codon, System.Collections.ArrayList subItems) |
||||
{ |
||||
Id = codon.Properties["id"]; |
||||
Text = codon.Properties["text"]; |
||||
Children = subItems != null ? subItems.Cast<InputBindingCategoryDescriptor>().ToList() : new List<InputBindingCategoryDescriptor>(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
|
||||
namespace ICSharpCode.Core |
||||
{ |
||||
/// <attribute name="id" use="required">
|
||||
/// Category Id used in category path
|
||||
/// </attribute>
|
||||
/// <attribute name="name" use="required">
|
||||
/// Category name displayed to user
|
||||
/// </attribute>
|
||||
/// <usage>Only in /SharpDevelop/CommandManager/InputBindingCategories</usage>
|
||||
/// <returns>
|
||||
/// InputBindingCategory object
|
||||
/// </returns>
|
||||
/// <summary>
|
||||
/// Associates ICSharpCode.Core.Presentation.InputBindingCategory with path which can later be used to reference created ICSharpCode.Core.Presentation.InputBindingCategory
|
||||
/// </summary>
|
||||
public class InputBindingCategoryDoozer : IDoozer |
||||
{ |
||||
/// <inheritdoc />
|
||||
public bool HandleConditions { |
||||
get { |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Builds instance of <see cref="InputBindingCategoryDescriptor" /> from codon
|
||||
/// </summary>
|
||||
/// <param name="caller">Caller object</param>
|
||||
/// <param name="codon">Codon</param>
|
||||
/// <param name="subItems">Codon sub-items</param>
|
||||
/// <returns>Instance of <see cref="InputBindingCategoryDescriptor" /></returns>
|
||||
public object BuildItem(object caller, Codon codon, System.Collections.ArrayList subItems) |
||||
{ |
||||
return new InputBindingCategoryDescriptor(codon, subItems); |
||||
} |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,90 @@
@@ -0,0 +1,90 @@
|
||||
using System; |
||||
|
||||
namespace ICSharpCode.Core |
||||
{ |
||||
/// <summary>
|
||||
/// Describes <see cref="ICSharpCode.Core.Presentation.InputBindingInfo" />
|
||||
/// </summary>
|
||||
public class InputBindingInfoDescriptor |
||||
{ |
||||
/// <summary>
|
||||
/// Codon used to create this descriptor
|
||||
/// </summary>
|
||||
public Codon Codon |
||||
{ |
||||
get; private set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets name of <see cref="System.Window.Input.RoutedUICommand" /> associated with descriptor
|
||||
/// The name should be associated to a command in code using <see cref="ICSharpCode.Core.Presentation.CommandManager" />
|
||||
/// </summary>
|
||||
public string Command |
||||
{ |
||||
get; private set; |
||||
} |
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets overriden routed command text (string visible to user)
|
||||
///
|
||||
/// If not provided <see cref="System.Window.Input.RoutedUICommand.Text" /> property value is used
|
||||
/// </summary>
|
||||
public string CommandText |
||||
{ |
||||
get; private set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets name of binding owner type name.
|
||||
///
|
||||
/// A name can be assigned to type in code using <see cref="ICSharpCode.Core.Presentation.CommandManager" />.
|
||||
/// If this property is set then <see cref="OwnerTypeName" /> property can be ignored
|
||||
/// If neither owner type nor owner instance is specified default owner type is applied
|
||||
/// </summary>
|
||||
public string OwnerInstanceName { |
||||
get; private set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Name of binding owner instance name.
|
||||
///
|
||||
/// A name can be assigned to instance in code using <see cref="ICSharpCode.Core.Presentation.CommandManager" />.
|
||||
/// If this property is set then <see cref="OwnerInstanceName" /> property can be ignored
|
||||
/// If neither owner type nor owner instance is specified default owner type is applied
|
||||
/// </summary>
|
||||
public string OwnerTypeName { |
||||
get; private set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets gestures associated with created <see cref="ICSharpCode.Core.Presentation.InputBindingInfo" />
|
||||
/// </summary>
|
||||
public string Gestures { |
||||
get; private set; |
||||
} |
||||
|
||||
|
||||
/// <summary>
|
||||
/// List of paths to input binding categories associated with created <see cref="ICSharpCode.Core.Presentation.InputBindingInfo" /> (separated by comma)
|
||||
/// </summary>
|
||||
public string Categories { |
||||
get; private set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Creates new instance of <see cref="InputBindingInfoDescriptor" />
|
||||
/// </summary>
|
||||
/// <param name="codon">Reference to codon used to create this descriptor</param>
|
||||
public InputBindingInfoDescriptor(Codon codon) |
||||
{ |
||||
Codon = codon; |
||||
Command = codon.Properties["command"]; |
||||
CommandText = codon.Properties["commandtext"]; |
||||
OwnerInstanceName = codon.Properties["ownerinstance"]; |
||||
OwnerTypeName = codon.Properties["ownertype"]; |
||||
Gestures = codon.Properties["gestures"]; |
||||
Categories = codon.Properties["categories"]; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,69 @@
@@ -0,0 +1,69 @@
|
||||
using System; |
||||
|
||||
namespace ICSharpCode.Core |
||||
{ |
||||
/// <attribute name="command" use="required">
|
||||
/// Name of System.Window.Input.RoutedUICommand associated with built InputBindingInfoDescriptor
|
||||
/// The name should be first registered in code using ICSharpCode.Core.Presentation.CommandManager
|
||||
/// or in addin file using RoutedUICommand node
|
||||
/// </attribute>
|
||||
/// <attribute name="ownertype" use="optional">
|
||||
/// Name of binding owner type.
|
||||
///
|
||||
/// A name can be assigned to type in code using ICSharpCode.Core.Presentation.CommandManager.
|
||||
/// If this attribute is used "ownerinstance" attribute cannot be used
|
||||
/// If neither owner type nor owner instance is specified default owner type is applied
|
||||
/// </attribute>
|
||||
/// <attribute name="ownertype" use="optional">
|
||||
/// Name of binding owner instance.
|
||||
///
|
||||
/// A name can be assigned to instance in code using ICSharpCode.Core.Presentation.CommandManager.
|
||||
/// If this attribute is used "ownertype" attribute cannot be used
|
||||
/// If neither owner type nor owner instance is specified default owner type is applied
|
||||
/// </attribute>
|
||||
/// <attribute name="gestures" use="optional">
|
||||
/// Gestures associated with created System.Windows.Input.InputBinding instances
|
||||
/// </attribute>
|
||||
/// <attribute name="commandtext" use="optional">
|
||||
/// Text displayed to user when managing input bindings (shortcuts)
|
||||
///
|
||||
/// If this attribute is not used System.Window.Input.RoutedUICommand.Text property is used
|
||||
/// This attribute can only be used together with "gestures" attribute
|
||||
/// </attribute>
|
||||
/// <attribute name="categories" use="optional">
|
||||
/// List of input binding category paths (separated using comma) associated with
|
||||
/// created input binding infos
|
||||
///
|
||||
/// Input binding categories can be created in code using ICSharpCode.Core.Presentation.CommandManager or by using InputBindingCategory node in addin file
|
||||
/// Input binding categories are used to group shortcuts into separate sections when displaying to user.
|
||||
/// </attribute>
|
||||
/// <usage>Only in /SharpDevelop/Workbench/InputBindings</usage>
|
||||
/// <returns>
|
||||
/// CommandBindingInfoDescriptor object
|
||||
/// </returns>
|
||||
/// <summary>
|
||||
/// Registers ICSharpCode.Core.Presentation.InputBindingInfo with specified parameters
|
||||
/// </summary>
|
||||
public class InputBindingInfoDoozer : IDoozer |
||||
{ |
||||
/// <inheritdoc />
|
||||
public bool HandleConditions |
||||
{ |
||||
get { |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Builds instance of <see cref="InputBindingInfoDescriptor" /> from codon
|
||||
/// </summary>
|
||||
/// <param name="caller">Caller object</param>
|
||||
/// <param name="codon">Codon</param>
|
||||
/// <param name="subItems">Codon sub-items</param>
|
||||
/// <returns>Instance of <see cref="InputBindingInfoDescriptor" /></returns>
|
||||
public object BuildItem(object caller, Codon codon, System.Collections.ArrayList subItems) |
||||
{ |
||||
return new InputBindingInfoDescriptor(codon); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
using System; |
||||
|
||||
namespace ICSharpCode.Core |
||||
{ |
||||
/// <summary>
|
||||
/// Describes <see cref="System.Windows.Input.RoutedUICommand" />
|
||||
/// </summary>
|
||||
public class RoutedUICommandDescriptor |
||||
{ |
||||
private Codon codon; |
||||
|
||||
/// <summary>
|
||||
/// Gets text with routed command purpose description
|
||||
/// </summary>
|
||||
public string Text |
||||
{ |
||||
get { |
||||
return codon.Properties["text"]; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Get routed command name
|
||||
/// </summary>
|
||||
public string Name |
||||
{ |
||||
get { |
||||
return codon.Properties["name"]; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Creates instance of <see cref="RoutedUICommandDescriptor" />
|
||||
/// </summary>
|
||||
/// <param name="codon">Reference to codon used to create this descriptor</param>
|
||||
public RoutedUICommandDescriptor(Codon codon) |
||||
{ |
||||
this.codon = codon; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,39 @@
@@ -0,0 +1,39 @@
|
||||
using System; |
||||
|
||||
namespace ICSharpCode.Core |
||||
{ |
||||
/// <attribute name="name" use="required">
|
||||
/// System.Window.Input.RoutedUICommand unique name
|
||||
/// </attribute>
|
||||
/// <attribute name="text" use="required">
|
||||
/// Displayed text associated with created System.Window.Input.RoutedUICommand
|
||||
/// </attribute>
|
||||
/// <usage>Only in /SharpDevelop/CommandManager/RoutedUICommands</usage>
|
||||
/// <returns>
|
||||
/// RoutedUICommandDescriptor object
|
||||
/// </returns>
|
||||
/// <summary>
|
||||
/// Creates new System.Window.Input.RoutedUICommand and associates it with a unique name which can be used later to reference routed command
|
||||
/// </summary>
|
||||
public class RoutedUICommandDoozer : IDoozer |
||||
{ |
||||
/// <inheritdoc />
|
||||
public bool HandleConditions { |
||||
get { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Builds instance of <see cref="RoutedUICommandDescriptor" /> from codon
|
||||
/// </summary>
|
||||
/// <param name="caller">Caller object</param>
|
||||
/// <param name="codon">Codon</param>
|
||||
/// <param name="subItems">Codon sub-items</param>
|
||||
/// <returns>Instance of <see cref="RoutedUICommandDescriptor" /></returns>
|
||||
public object BuildItem(object caller, Codon codon, System.Collections.ArrayList subItems) |
||||
{ |
||||
return new RoutedUICommandDescriptor(codon); |
||||
} |
||||
} |
||||
} |