# Changeset 1229 for trunk/Documentation

Ignore:
Timestamp:
Mar 2, 2010, 6:18:43 PM (12 years ago)
Message:

HowTo: further edits, mostly to middle section. Still more to come!

Location:
trunk/Documentation/Developer/PluginHowTo
Files:
4 edited

### Legend:

Unmodified
 r1181 Now you will need a way of accessing and downloading the source code. In the CrypTool 2.0 project we use Subversion (SVN) for version control, and hence you need an \textbf{SVN client}, e.g.\ \textbf{TortoiseSVN} or the \textbf{svn commandline from cygwin}. It does not matter which client you use, but if you have never worked with SVN before, we suggest using \href{http://www.tortoisesvn.net/}{TortoiseSVN}, since it offers a nice Windows Explorer integration of SVN. \clearpage \subsection*{The CrypTool2 SVN URL} As mentioned above, in order to access the SVN repository one of the best options is \href{http://www.tortoisesvn.net/}{TortoiseSVN}. We will describe here how to use the basics of the program, although you should be able to use any SVN client in a similar fashion. First install TortoiseSVN (which unfortunately requires you to reboot your computer) and then create a directory (for instance CrypTool2") for storing the local working files somewhere on your computer. Right-click on this directory and select SVN Checkout" from the context menu. A window will appear in which you will be asked for the URL of the repository as given above. The Checkout directory" should already be filled in correctly with your new folder. Then just hit OK", accept the certificate (if necessary), and enter your login information as described above. Mark the checkbox for saving your credentials if you don't want to enter them every time you work with the repository. Then hit OK", and now the whole CrypTool2 repository should be checked out into your chosen directory. \begin{figure}[h!] \centering \includegraphics[width=0.40\textwidth]{figures/tortoise_svn_checkout.jpg} \caption{Selecting SVN Checkout" from the context menu after installing TortoiseSVN.} \label{fig:tortoise_svn_checkout} \end{figure} First install TortoiseSVN (which unfortunately requires you to reboot your computer) and then create a directory (for instance CrypTool2") for storing the local working files somewhere on your computer. Right-click on this directory and select SVN Checkout" from the context menu. A window will appear in which you will be asked for the URL of the repository; use the address given above, as seen in Figure \ref{fig:tortoise_svn_checkout2}. The Checkout directory" should already be filled in correctly with your new folder. Then just hit OK", accept the certificate (if necessary), and enter your login information as described above. Mark the checkbox for saving your credentials if you don't want to enter them every time you work with the repository. Then hit OK", and now the whole CrypTool2 repository should be checked out into your chosen directory. \clearpage \begin{figure}[h!] \centering \includegraphics[width=0.60\textwidth]{figures/tortoise_svn_checkout2.jpg} \caption{Checking out the CrypTool2 repository.} \label{fig:tortoise_svn_checkout2} \end{figure} Later on, if changes have been made in the repository and you want to update your working copy, you can do this by right-clicking on any directory within the working files and choosing SVN Update" from the context menu. You should do this often to maintain a current version of the files. If you are a registered developer, you can commit your file changes to the public CrypTool2 repository. Right-click on the directory within the working files that contains your changes and select SVN Commit" from the context menu to upload your changes. Please always provide \textit{meaningful descriptions} of your updates. You should commit your sources to our SVN repository as often as you can to ensure your interoperability with the rest of the project, but only commit code that successfully compiles and runs! \begin{figure}[h!] \centering \includegraphics[width=0.40\textwidth]{figures/tortoise_svn_commit.jpg} \caption{Selecting SVN Commit" from the context menu.} \label{fig:tortoise_svn_commit} \end{figure} You can use command words in the SVN comment to link your changes to a particular ticket. The command syntax is as follows: Please note that any text after the colon and the whitespace will be treated as the file name. Therefore, do not use quotation marks and do not write any text after the file name. \clearpage \section{Compiling the sources}
 r1181 \centering \includegraphics[width=0.80\textwidth]{figures/save_solution_csharp_express.JPG} \caption{The Microsoft C\# Express Edition Save Project" dialog window.} \caption{The Visual Studio C\# Express Edition Save Project" dialog window.} \label{fig:save_solution_csharp_express} \end{figure} \clearpage \noindent Select the project CrypPluginBase". If you do not have the CrypPluginBase" source code, it is also possible to add a reference the binary DLL. In this case browse to the path where the library file \textit{CrypPluginBase.dll} is located, e.g.\ \textit{C:\textbackslash Documents and Settings\textbackslash $<$Username$>$\textbackslash My Documents\textbackslash Visual Studio 2008\textbackslash Projects\textbackslash CrypPluginBase\textbackslash bin\textbackslash Debug} and select the library by double clicking the file or pressing the OK" button. (You can also select the binary DLL located in the folder where \textit{CrypWin.exe} was placed when you downloaded CrypTool2.) \noindent Unless you have created your new project in the same CrypTool 2.0 solution, you probably will not be able to select the library directly as seen above in Figure \ref{fig:add_pluginbase_source}; instead you can browse for the binary DLL as seen below in Figure \ref{fig:browse_reference}. Click on the Browse" tab and navigate to the folder in which you downloaded the CrypTool 2 project. Within that folder, go to \textit{\textbackslash CrypPluginBase\textbackslash bin\textbackslash Debug} and select the file CryptPluginBase.dll". The library reference can then be added by double clicking the file or pressing the OK" button. \begin{figure}[h!] \end{figure} \noindent Besides CrypPluginBase you will need to add three assembly references to provide the necessary Windows" namespaces for the \textbf{user control} functions Presentation" and QuickWatchPresentation". This can be done in the same manner as before with the CrypPluginBase" but by selecting the .NET" tab. Select the following .NET components: \noindent Besides CrypPluginBase you will need to add three Windows assembly references to provide the necessary namespaces for the \textbf{user control} functions Presentation" and QuickWatchPresentation". This can be done in a similar manner as before with the CrypPluginBase" reference, but by selecting the .NET" tab and searching for the references there. Select the following .NET components: \begin{itemize} \label{sec:CreatingClassesForTheAlgorithmAndItsSettings} In the next step we will create two classes. The first class will be the main driver; we will call ours Caesar" since that is the name of the cipher that it will implement. In our case, this class has to inherit from IEncryption because it will be an ecryption plugin. If it was instead a hash plugin, this class should inherit from IHash. The second class will be used to store setting information for the plugin, and thus we will name ours CaesarSettings". It has to inherit from ISettings. In the next step we will create two classes. The first class will be the main driver; we will call ours Caesar" since that is the name of the cipher that it will implement. In our case, this class has to inherit from IEncryption because it will be an ecryption plugin. If it was instead a hash plugin, this class should inherit from IHash. The second class will be used to store setting information for the plugin, and thus we will name ours CaesarSettings". It will need to inherit from ISettings. \clearpage \item Cryptool.PluginBase.Miscellaneous --- contains assorted helper classes, including \textit{GuiLogMessage} and \textit{PropertyChanged}. \item Cryptool.PluginBase.Resources --- used only by CrypWin and the editor; not necessary for plugin development. \item Cryptool.PluginBase.Tool --- contains an interface for all external tools implemented by CrypTool 2.0 that do not entirely support the CrypTool 2.0 API . \item Cryptool.PluginBase.Tool --- contains an interface for all external tools implemented by CrypTool 2.0 that do not entirely support the CrypTool 2.0 API. \item Cryptool.PluginBase.Validation --- contains interfaces for validation methods, including regular expressions. \end{itemize} \end{lstlisting} \subsection{Adding interface functions for the Caesar class} \label{sec:AddingInterfaceFunctionsForTheCaesarClass} There is an underscore at the ''I'' in IEncryption statement. Move your mouse over it or place the cursor at it and press ''Shift+Alt+F10'' and you will see the following submenu: \subsection{Adding interface functions to the Caesar class} \label{sec:AddingInterfaceFunctionsToTheCaesarClass} You may notice an underscore underneath the I" in IEncryption". Move your mouse over it, or place the cursor on it and press Shift+Alt+F10" and the following submenu should appear: \begin{figure}[h!] \centering \caption{Inherit submenu} \label{fig:inherit_submenu} \end{figure}\\ Choose the item ''Implement interface 'IEncryption'''. Visual Studio/C\# Express will now place all available and needed interface members to interact with the CrypTool core (this saves you also a lot of typing code).\\ Your code will now look like this: \end{figure} Select the item Implement interface IEncryption'". Visual Studio will automatically generate all the interface members necessary for interaction with the CrypTool 2 core. (This step will save you a lot of typing!) \clearpage \noindent Your code should now look like this: \begin{lstlisting} using System.Collections.Generic; } \end{lstlisting} \subsection{Add namespace and interfaces for the class CaesarSettings}\label{sec:AddNamespaceAndInterfacesForTheClassCaesarSettings} Let's now take a look at the second class "CaesarSettings" by double clicking at the "CaesarSettings.cs" file at the Solution Explorer. First we also have to include the namespace of "Cryptool.PluginBase" to the class header and let the settings class inherit from "ISettings" analogous as seen before at the Caesar class. Visual Studio/C\# Express will here also automatically place code from the CrypTool interface if available. \subsection{Adding the namespace and interfaces to the CaesarSettings class} \label{sec:AddingTheNamespaceAndInterfacesToTheCaesarSettingsClass} Let's now take a look at the second class in our example, CaesarSettings", by double-clicking on the CaesarSettings.cs" file in the Solution Explorer. First, we need to again include the Cryptool.PluginBase" namespace to the class header. Then we must let the settings class inherit from ISettings" in the same manner as was done with the Caesar class. Visual Studio will again automatically generate code from the CrypTool interface as seen below. (We can again remove the lines \texttt{using System;} and \texttt{using System.Linq;}, as we do not need those references.)\\ \begin{lstlisting} using System.Collections.Generic; } \end{lstlisting} \subsection{Add controls for the class CaesarSettings (if needed)}\label{sec:AddControlsForTheClassCaesarSettingsIfNeeded} Now we have to implement some kind of controls (like button, text box) if we need them in the CrypTool \textbf{TaskPane} to modify settings of the algorithm. If you decided to provide an algorithm (e.g. Hash) which do not have any kind of settings you can leave this class now empty. The only part you have to modify is the ''HasChanges'' property to avoid any ''NotImplementedException''. How to modify this property you can see in the following code which demonstrate the modifications fot the TaskPane for our Caesar algorithm. You can also take a look at the other algorithm source codes which are stored in our subversion how you can provide a TaskPane. The following source code demonstrates how we provide our TaskPane as seen above. \subsection{Adding controls to the CaesarSettings class} \label{sec:AddingControlsToTheCaesarSettingsClass} The settings class is used to populate the TaskPane in the CrypTool 2 application so that the user can modify settings at will. To meet these ends we will need to implement some controls such as buttons and text boxes. If you will be implementing an algorithm that does not have any user-defined settings (e.g. a hash function), then this class can be left empty; you will, however, still have to modify the HasChanges" property to avoid a NotImplementedException". The following code demonstrates the modifications necessary to create the backend for the TaskPane for our Caesar algorithm. You can also look at the source code of other algorithms in the subversion repository for examples of how to create the TaskPane backend.\\ \begin{lstlisting} using System; /// /// We use this delegate to send log messages from the settings class to the Caesar plugin /// We use this delegate to send log messages from /// the settings class to the Caesar plugin. /// public delegate void CaesarLogMessage(string msg, NotificationLevel loglevel); /// /// An enumaration for the different modes of dealing with unknown characters /// An enumeration for the different modes of handling /// unknown characters. /// public enum UnknownSymbolHandlingMode { Ignore = 0, Remove = 1, Replace = 2 }; /// /// Fire if a new status message was send /// Fires when a new status message was sent. /// public event CaesarLogMessage LogMessage; /// /// Retrieves the current sihft value of Caesar (i.e. the key), or sets it /// Retrieves or sets the current shift value (i.e. the key). /// [PropertySaveOrder(0)] /// /// Retrieves the current setting whether the alphabet should be treated as case sensitive or not /// Retrieves the current setting of whether or not the /// alphabet should be treated as case-sensitive. /// [PropertySaveOrder(1)] {   return true;    } } set {} // readonly, because there are some problems if we omit the set part. set {} // this setting is readonly, but we must include // some form of set method to prevent problems. } /// /// Returns true if some settings have been changed. This value should be set externally to false e.g. /// when a project was saved. /// Returns true if any settings have been changed. /// This value should be set externally to false e.g. /// when a project is saved. /// [PropertySaveOrder(3)] private bool hasChanges; private int selectedAction = 0; private string upperAlphabet = ''ABCDEFGHIJKLMNOPQRSTUVWXYZ''; private string lowerAlphabet = ''abcdefghijklmnopqrstuvwxyz''; private string alphabet = ''ABCDEFGHIJKLMNOPQRSTUVWXYZ''; private string upperAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; private string lowerAlphabet = "abcdefghijklmnopqrstuvwxyz"; private string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; private char shiftChar = 'C'; private int shiftValue = 2; // private int shiftValue = 2; private UnknownSymbolHandlingMode unknownSymbolHandling = UnknownSymbolHandlingMode.Ignore; private int caseSensitiveAlphabet = 0; // 0 = case insensitve, 1 = case sensitive private int caseSensitiveAlphabet = 0; // 0 = case-insensitve, 1 = case-sensitive private bool sensitivityEnabled = true; #endregion if ((value[i] == value[j]) || (!CaseSensitiveAlphabet & (char.ToUpper(value[i]) == char.ToUpper(value[j])))) { LogMessage(''Removing duplicate letter: \''' + value[j] + ''\' from alphabet!'', NotificationLevel.Warning); LogMessage("Removing duplicate letter: \'" + value[j] + "\' from alphabet!", NotificationLevel.Warning); value = value.Remove(j,1); j--; /// /// Set the new shiftValue and the new shiftCharacter to offset % alphabet.Length /// Set the new shiftValue and the new shiftCharacter /// to offset % alphabet.Length. /// private void setKeyByValue(int offset) HasChanges = true; // making sure the shift value lies within the alphabet range // Make sure the shift value lies within the alphabet range. offset = offset % alphabet.Length; // set the new shiftChar // Set the new shiftChar. shiftChar = alphabet[offset]; // set the new shiftValue // Set the new shiftValue. shiftValue = offset; // Anounnce this to the settings pane OnPropertyChanged(''ShiftValue''); OnPropertyChanged(''ShiftChar''); // print some info in the log. LogMessage(''Accepted new shift value '' + offset + ''! (Adjusted shift character to \''' + shiftChar + ''\')'', NotificationLevel.Info); // Announce this to the settings pane. OnPropertyChanged("ShiftValue"); OnPropertyChanged("ShiftChar"); // Print some info in the log. LogMessage("Accepted new shift value " + offset + "! (Adjusted shift character to \'" + shiftChar + "\')", NotificationLevel.Info); } shiftValue = offset; shiftChar = alphabet[shiftValue]; LogMessage(''Accepted new shift character \''' + shiftChar + ''\'! (Adjusted shift value to '' + shiftValue + '')'', NotificationLevel.Info); OnPropertyChanged(''ShiftValue''); OnPropertyChanged(''ShiftChar''); LogMessage("Accepted new shift character \'" + shiftChar + "\'! (Adjusted shift value to " + shiftValue + ")", NotificationLevel.Info); OnPropertyChanged("ShiftValue"); OnPropertyChanged("ShiftChar"); } else { LogMessage(''Bad input \'''' + value + ''\''! (Character not in alphabet!) Reverting to '' + shiftChar.ToString() + ''!'', NotificationLevel.Error); LogMessage("Bad input \"" + value + "\"! (Character not in alphabet!) Reverting to " + shiftChar.ToString() + "!", NotificationLevel.Error); } } catch (Exception e) { LogMessage(''Bad input \'''' + value + ''\''! ('' + e.Message + '') Reverting to '' + shiftChar.ToString() + ''!'', NotificationLevel.Error); LogMessage("Bad input \"" + value + "\"! (" + e.Message + ") Reverting to " + shiftChar.ToString() + "!", NotificationLevel.Error); } } [PropertySaveOrder(4)] [ContextMenu(''Action'', ''Select the Algorithm action'', 1, DisplayLevel.Beginner, ContextMenuControlType.ComboBox, new int[] { 1, 2 }, ''Encrypt'', ''Decrypt'')] [TaskPane(''Action'', ''setAlgorithmActionDescription'', null, 1, true, DisplayLevel.Beginner, ControlType.ComboBox, new string[] { ''Encrypt'', ''Decrypt'' })] [ContextMenu("Action", "Select the algorithm action", 1, DisplayLevel.Beginner, ContextMenuControlType.ComboBox, new int[] { 1, 2 }, "Encrypt", "Decrypt")] [TaskPane("Action", "setAlgorithmActionDescription", null, 1, true, DisplayLevel.Beginner, ControlType.ComboBox, new string[] { "Encrypt", "Decrypt" })] public int Action { if (value != selectedAction) HasChanges = true; this.selectedAction = value; OnPropertyChanged(''Action''); OnPropertyChanged("Action"); if (ReExecute != null) ReExecute(); [PropertySaveOrder(5)] [TaskPane(''Key as integer'', ''Enter the number of letters to shift. For instance a value of 1 means that the plaintext character a gets mapped to the ciphertext character B, b to C and so on.'', null, 2, true, DisplayLevel.Beginner, ControlType.NumericUpDown, ValidationType.RangeInteger, 0, 100)] [TaskPane("Key as integer", "Enter the number of letters to shift. For example, a value of 1 means that the plaintext character 'a' gets mapped to the ciphertext character 'B', 'b' to 'C', and so on.", null, 2, true, DisplayLevel.Beginner, ControlType.NumericUpDown, ValidationType.RangeInteger, 0, 100)] public int ShiftValue { } [PropertySaveOrder(6)] [TaskPaneAttribute(''Key as single letter'', ''Enter a single letter as the key. This letter is mapped to an integer stating the position in the alphabet. The values for 'Key as integer' and 'Key as single letter' are always synchronized.'', null, 3, true, DisplayLevel.Beginner, ControlType.TextBox, ValidationType.RegEx, ''^([A-Z]|[a-z]){1,1}'')] [TaskPaneAttribute("Key as single letter", "Enter a single letter as the key. This letter is mapped to an integer stating the position in the alphabet. The values for 'Key as integer' and 'Key as single letter' are always synchronized.", null, 3, true, DisplayLevel.Beginner, ControlType.TextBox, ValidationType.RegEx, "^([A-Z]|[a-z]){1,1}")] public string ShiftChar { [PropertySaveOrder(7)] [ContextMenu(''Unknown symbol handling'', ''What should be done with encountered characters at the input which are not in the alphabet?'', 4, DisplayLevel.Expert, ContextMenuControlType.ComboBox, null, new string[] { ''Ignore (leave unmodified)'', ''Remove'', ''Replace with \'?\''' })] [TaskPane(''Unknown symbol handling'', ''What should be done with encountered characters at the input which are not in the alphabet?'', null, 4, true, DisplayLevel.Expert, ControlType.ComboBox, new string[] { ''Ignore (leave unmodified)'', ''Remove'', ''Replace with \'?\''' })] [ContextMenu("Unknown symbol handling", "What should be done with characters encountered in the input which are not in the alphabet?", 4, DisplayLevel.Expert, ContextMenuControlType.ComboBox, null, new string[] { "Ignore (leave unmodified)", "Remove", "Replace with \'?\'" })] [TaskPane("Unknown symbol handling", "What should be done with characters encountered in the input which are not in the alphabet?", null, 4, true, DisplayLevel.Expert, ControlType.ComboBox, new string[] { "Ignore (leave unmodified)", "Remove", "Replace with \'?\'" })] public int UnknownSymbolHandling { if ((UnknownSymbolHandlingMode)value != unknownSymbolHandling) HasChanges = true; this.unknownSymbolHandling = (UnknownSymbolHandlingMode)value; OnPropertyChanged(''UnknownSymbolHandling''); OnPropertyChanged("UnknownSymbolHandling"); if (ReExecute != null) ReExecute(); } [SettingsFormat(0, ''Normal'', ''Normal'', ''Black'', ''White'', Orientation.Vertical)] [SettingsFormat(0, "Normal", "Normal", "Black", "White", Orientation.Vertical)] [PropertySaveOrder(9)] [TaskPane(''Alphabet'', ''This is the used alphabet.'', null, 6, true, DisplayLevel.Expert, ControlType.TextBox, '''')] [TaskPane("Alphabet", "This is the alphabet currently in use.", null, 6, true, DisplayLevel.Expert, ControlType.TextBox, "")] public string AlphabetSymbols { if (a.Length == 0) // cannot accept empty alphabets { LogMessage(''Ignoring empty alphabet from user! Using previous alphabet: \'''' + alphabet + ''\'' ('' + alphabet.Length.ToString() + '' Symbols)'', NotificationLevel.Info); LogMessage("Ignoring empty alphabet from user! Using previous alphabet instead: \" + alphabet + "\" (" + alphabet.Length.ToString() + " Symbols)", NotificationLevel.Info); } else if (!alphabet.Equals(a)) HasChanges = true; this.alphabet = a; setKeyByValue(shiftValue); //re-evaluate if the shiftvalue is still within the range LogMessage(''Accepted new alphabet from user: \'''' + alphabet + ''\'' ('' + alphabet.Length.ToString() + '' Symbols)'', NotificationLevel.Info); OnPropertyChanged(''AlphabetSymbols''); setKeyByValue(shiftValue); // reevaluate if the shiftvalue is still within the range LogMessage("Accepted new alphabet from user: \" + alphabet + "\" (" + alphabet.Length.ToString() + " Symbols)", NotificationLevel.Info); OnPropertyChanged("AlphabetSymbols"); if (ReExecute != null) ReExecute(); /// /// Visible setting how to deal with alphabet case. 0 = case insentive, 1 = case sensitive /// Visible setting how to deal with alphabet case. /// 0 = case-insentive, 1 = case-sensitive /// //[SettingsFormat(1, ''Normal'')] //[SettingsFormat(1, "Normal")] [PropertySaveOrder(8)] [ContextMenu(''Alphabet case sensitivity'', ''Should upper and lower case be treated differently? (Should a == A)'', 7, DisplayLevel.Expert, ContextMenuControlType.ComboBox, null, new string[] { ''Case insensitive'', ''Case sensitive'' })] [TaskPane(''Alphabet case sensitivity'', ''Should upper and lower case be treated differently? (Should a == A)'', null, 7, true, DisplayLevel.Expert, ControlType.ComboBox, new string[] { ''Case insensitive'', ''Case sensitive'' })] [ContextMenu("Alphabet case sensitivity", "Should upper and lower case be treated as the same (so that 'a' = 'A')?", 7, DisplayLevel.Expert, ContextMenuControlType.ComboBox, null, new string[] { "Case insensitive", "Case sensitive" })] [TaskPane("Alphabet case sensitivity", "Should upper and lower case be treated as the same (so that 'a' = 'A')?", null, 7, true, DisplayLevel.Expert, ControlType.ComboBox, new string[] { "Case insensitive", "Case sensitive" })] public int AlphabetCase { { alphabet = upperAlphabet; LogMessage(''Changing alphabet to: \'''' + alphabet + ''\'' ('' + alphabet.Length.ToString() + '' Symbols)'', NotificationLevel.Info); OnPropertyChanged(''AlphabetSymbols''); // re-set also the key (shiftvalue/shiftChar to be in the range of the new alphabet LogMessage("Changing alphabet to: \"" + alphabet + "\" (" + alphabet.Length.ToString() + " Symbols)", NotificationLevel.Info); OnPropertyChanged("AlphabetSymbols"); // reset the key (shiftvalue/shiftChar) // to be in the range of the new alphabet. setKeyByValue(shiftValue); } { alphabet = upperAlphabet + lowerAlphabet; LogMessage(''Changing alphabet to: \'''' + alphabet + ''\'' ('' + alphabet.Length.ToString() + '' Symbols)'', NotificationLevel.Info); OnPropertyChanged(''AlphabetSymbols''); LogMessage("Changing alphabet to: \"" + alphabet + "\" (" + alphabet.Length.ToString() + " Symbols)", NotificationLevel.Info); OnPropertyChanged("AlphabetSymbols"); } } // remove equal characters from the current alphabet // Remove equal characters from the current alphabet. string a = alphabet; alphabet = removeEqualChars(alphabet); if (a != alphabet) { OnPropertyChanged(''AlphabetSymbols''); LogMessage(''Changing alphabet to: \'''' + alphabet + ''\'' ('' + alphabet.Length.ToString() + '' Symbols)'', NotificationLevel.Info); OnPropertyChanged("AlphabetSymbols"); LogMessage("Changing alphabet to: \"" + alphabet + "\" (" + alphabet.Length.ToString() + " Symbols)", NotificationLevel.Info); } OnPropertyChanged(''AlphabetCase''); OnPropertyChanged("AlphabetCase"); if (ReExecute != null) ReExecute(); } #endregion #region TaskPaneAttributeChanged-Sample #region TaskPaneAttributeChanged (Sample) /// /// This event is just used here for sample reasons /// This event is here merely as a sample. /// public event TaskPaneAttributeChangedHandler TaskPaneAttributeChanged; [TaskPane(''Enable/Disable sensitivity'', ''This setting is just a sample and shows how to enable / disable a setting.'', ''AttributeChangedSample'', 8, false, DisplayLevel.Beginner, ControlType.Button)] [TaskPane("Enable/Disable sensitivity", "This setting is just a sample and shows how to enable / disable a setting.", "AttributeChangedSample", 8, false, DisplayLevel.Beginner, ControlType.Button)] public void EnableDisableSesitivity() { if (sensitivityEnabled) { TaskPaneAttributeChanged(this, new TaskPaneAttributeChangedEventArgs(new TaskPaneAttribteContainer(''AlphabetCase'', Visibility.Visible))); TaskPaneAttributeChanged(this, new TaskPaneAttributeChangedEventArgs(new TaskPaneAttribteContainer("AlphabetCase", Visibility.Visible))); } else { TaskPaneAttributeChanged(this, new TaskPaneAttributeChangedEventArgs(new TaskPaneAttribteContainer(''AlphabetCase'', Visibility.Collapsed))); TaskPaneAttributeChanged(this, new TaskPaneAttributeChangedEventArgs(new TaskPaneAttribteContainer("AlphabetCase", Visibility.Collapsed))); } } } #endregion TaskPaneAttributeChanged-Sample #endregion TaskPaneAttributeChanged (Sample) } } \end{lstlisting} \section{Select and add an image as icon for the class Caesar}\label{sec:SelectAndAddAnImageAsIconForTheClassCaesar} Before we go back to the code of the Caesar class, we have to add an icon image to our project, which will be shown in the CrypTool \textbf{ribbon bar} or/and \textbf{navigation pane}. As there is no default, using an icon image is mandatory.\\\\ \textit{\small Note: This will be changed in future. A default icon will be used if no icon image has been provided.}\\\\ For testing purposes you may create a simple black and white PNG image with MS Paint or Paint.NET. As image size you can use 40x40 pixels for example, but as the image will be scaled when required, any size should do it. Place the image file in your project directory or in a subdirectory.\clearpage Then make a right click on the project item "Caesar" or any subdirectory within the Solution Explorer, and select ''Add-$>$Existing Item...'': \clearpage \section{Adding an icon to the Caesar class} \label{sec:AddingAnIconToTheCaesarClass} Before we go back to the code of the Caesar class, we have to add an icon to our project, which will be shown in the CrypTool \textbf{ribbon bar} and \textbf{navigation pane}. As there is currently no default, it is mandatory to add an icon. (It is planned to include a default icon in future versions.) For testing purposes you can just create a simple black and white PNG image with MS Paint or Paint.NET. The proper image size is 40x40 pixels, but since the image will be rescaled if necessary, any size is technically acceptable. Once you have saved your icon, you should add it directly to the project or to a subdirectory. In the project solution, we created a new folder named Images". This can be done by right-clicking on the project item (Caesar" in our example) and selecting Add $\rightarrow$ New Folder". The icon can be added to this folder (or to the project directly, or to any other subdirectory) by right-clicking on the folder and selecting Add $\rightarrow$ Existing Item". \begin{figure}[h!] \centering \includegraphics{figures/add_existing_item.jpg} \caption{Add existing item} \caption{Adding an existing item.} \label{fig:add_existing_item} \end{figure} As you can see, in our solution we create an new folder named ''Images'' (make a right click on the project item ''Caesar'' and select ''Add-$>$New Folder'') and placed there the new icon by clicking right on the folder as mentioned aboved.\clearpage Then select ''Image Files'' as file type, and choose the icon for your plugin: \clearpage A new window will then appear. Select Image Files" as the file type and select your newly-created icon for your plugin. \begin{figure}[h!] \centering \includegraphics{figures/choose_icon.jpg} \caption{Choose the right icon} \caption{Selecting the image file.} \label{fig:choose_icon} \end{figure} Finally we have to set the icon as a ''Resource'' to avoid providing the icon as a separate file. Make a right click on the icon and select the item ''Properties'':\clearpage \clearpage Finally, we must set the icon as a Resource" to avoid including the icon as a separate file. Right-click on the icon and select Properties" as seen below. \begin{figure}[h!] \centering \includegraphics{figures/icon_properties.jpg} \caption{Icon properties} \caption{Selecting the image properties.} \label{fig:icon_properties} \end{figure} In the ''Properties'' panel you have to set the ''Build Action'' to ''Resource'' (not embedded resource): In the Properties" panel, set the Build Action" to Resource". \begin{figure}[h!] \centering \includegraphics{figures/icon_build_action.jpg} \caption{Icon  build action} \caption{Selecting the icon's build action.} \label{fig:icon_build_action} \end{figure} \section{Set the attributes for the class Caesar}\label{sec:SetTheAttributesForTheClassCaesar} Now let's go back to the code of the Caesar class (''Caesar.cs'' file). First we have to set the necessary attributes for our class. This attributes are used to provide additional information for the CrypTool 2.0 environment. If not set, your plugin won't show up in the GUI, even if everything else is implemented correctly. Attributes are used for \textbf{declarative} programming and provide meta data, that can be attached to the existing .NET meta data , like classes and properties. CrypTool provides a set of custom attributes, that are used to mark the different parts of your plugin. \textit{[Author]}\\ The first attribute called ''Author'' is optional, which means we are not forced to define this attribute. It provides the additional information about the plugin developer. This informations you can see for example in the TaskPane as shown on a screenshot above. We set this attribute to demonstrate how it has to look in case you want to provide this attribute. \begin{figure}[h!] \centering \includegraphics[width=1.00\textwidth]{figures/attribute_author.jpg} \caption{Attribute author} \clearpage \section{Defining the attributes of the Caesar class} \label{sec:DefiningTheAttributesOfTheCaesarClass} Now let's go back to the code of the Caesar class (the Caesar.cs" file in our example). The first thing we will do is define the attributes of our class. These attributes are used to provide additional information for the CrypTool 2.0 environment. If they are not properly defined, your plugin won't show up in the application display, even if everything else is implemented correctly. Attributes are used for \textbf{declarative} programming and provide metadata that can be added to the existing .NET metadata. CrypTool provides a set of custom attributes that are used to mark the different parts of your plugin. These attributes can be defined anywhere within the `Cryptool.Caesar" namespace, but customarily they are defined right before the class declaration. \subsubsection*{The \textit{[Author]} attribute} \label{sec:TheAuthorAttribute} The \textit{[Author]} attribute is optional, and thus we are not required to define it. The attribute can be used to provide additional information about the plugin developer. This information will appear in the TaskPane, as for example in Figure \ref{fig:task_pane}. We will define the attribute to demonstrate how it should look in case you want to use it in your plugin. \begin{figure}[h!] \centering \includegraphics[width=.90\textwidth]{figures/attribute_author_new.jpg} \caption{The defintion for the \textit{[Author]} attribute.} \label{fig:attribute_author} \end{figure} As we can see above the author attribute takes four elements of type string. These elements are: As can be see above, the author attribute takes four elements of type string. These elements are: \begin{itemize} \item Author = name of the plugin developer \item Email = email of the plugin developer if he wants to be contact \item Institute = current employment of the developer like University or Company \item Url = the website or homepage of the developer \item Author --- the name of the plugin developer(s). \item Email --- the email address of the plugin developer(s), should they wish to be available for contact. \item Institute --- the organization, company or university with which the developer(s) are affiliated. \item URL --- the website of the developer(s) or their institution. \end{itemize} All this elements are also optional. The developer decides what he wants to publish. Unused elements shall be set to null or a zero-length string (''''). Our author attribute should look now as you can see below: \begin{figure}[h!] \centering \includegraphics[width=1.00\textwidth]{figures/attribute_author_filled.jpg} \caption{Filled author auttribute} \label{fig:attribute_author_filled} \end{figure} \textit{[PluginInfo]}\\ The second attribute called ''PluginInfo'' provides the necessary information about the plugin like caption and tool tip. This attribute is mandatory. The attribute has the definition as you can see below: All of these elements are optional; the developer(s) can choose what information will be published. Unused elements should be set to null or an empty string. \clearpage %Our author attribute should look now as you can see below: %\begin{figure}[h!] %       \centering %               \includegraphics[width=1.00\textwidth]{figures/attribute_author_filled.jpg} %       \caption{Filled author auttribute} %       \label{fig:attribute_author_filled} %\end{figure} \subsubsection*{The \textit{[PluginInfo]} attribute} \label{sec:ThePluginInfoAttribute} The second attribute, \textit{[PluginInfo]}, provides necessary information about the plugin, and is therefore mandatory. This information appears in the caption and tool tip window. The attribute is defined as follows: \begin{figure}[h] \centering \includegraphics[width=1.00\textwidth]{figures/attribute_plugininfo.jpg} \caption{Attribute PluginInfo} \includegraphics[width=1.00\textwidth]{figures/attribute_plugininfo_new.jpg} \caption{The defintion for the \textit{[PluginInfo]} attribute.} \label{fig:attribute_plugininfo} \end{figure} This attribute expects the following elements: This attribute has the following parameters: \begin{itemize} \item resourceFile = Defines if resource files will be provided and where to find them. E.g. to provide the plugin multilingual you can store the labels in such a resource file. This element is optional. \item startable = Set this flag to true only if your plugin is some kind of input or generator plugin (probably if your plugin just has outputs and no inputs). In all other cases use false here. This flag is important. Setting this flag to true for a non input/generator plugin will result in unpredictable chain runs. This element is mandatory. \item caption = from type string, the name of the plugin or the resource field name if you provide the caption in a resource file (e.g. to provide the button content). This element is mandatory. \item toolTip = from type string, description of the plugin or the resource field name if you provide the toolTip in a resource file (e.g. to provide the button tool tip). This element is optional. \item descriptionUrl = from type string, define where to find the whole description files (e.g. XAML files). This element is optional. \item icons = from type string array, which provides all necessary icon paths you want to use in the plugin (e.g. the plugin icon as seen above). This element is mandatory. \item Resource File --- defines where to find the associated resource file, if one is to be implemented. These are used, for example, to provide multilingual support for the plugin. This element is optional. \item Startable --- a flag that should be set to true only if the plugin is an input generator plugin (i.e. if your plugin only has outputs and no inputs). In all other cases this should be set to false. This flag is important --- setting it incorrectly will result in unpredictable results. This element is mandatory. \item Caption --- the name of the plugin or, if the caption is specified in a resource file, the name of the appropriate field in the resource file. This element is mandatory. \item ToolTip --- a description of the plugin or, if the tool tip is specified in a resource file, the name of the appropriate field in the resource file. This element is optional. \item DescriptionURL --- defines where to find the description file (e.g. XAML file). This element is optional. \item Icons --- an array of strings to define all the paths for the icons to be used in the plugin (i.e. the plugin icon described in section \ref{sec:AddingAnIconToTheCaesarClass}). This element is mandatory. \end{itemize} Unused optional elements shall be set to null or a zero-length string (''''). \textit{\small Note 1: It is possible to use the plugin without setting a caption though it is not recommended. This will be changed in future and the plugin will fail to load without a caption.\\\\ \small Note 2: Currently a zero-length toolTip string appears as empty box. This will be changed in future.\\\\ \small Note 3: Tooltip and description currently do not support internationalization and localization. This will be changed in future.\\\\} Unused elements should be set to null or an empty string. (There are a few limitations and bugs that still exist in the \textit{[PluginInfo]} attribute that will be resolved in a future version. Firstly, it is possible to use the plugin without setting a caption, although this is not recommended. In the future the plugin will fail to load without a caption. Secondly, a zero-length toolTip string currently causes the toolTip to appear as an empty box in the application. Lastly, the toolTip and description do not currently support internationalization and localization.) In our example the first parameter called ''resourceFile'' has to be set to ''Cryptool.Caesar.Resource.res'' because we want to provide the plugin multilingual and want to store the labels and caption in a resource file. Otherwise ignore this element. \begin{figure}[h]