source: trunk/CrypPlugins/Caesar/CaesarSettings.cs @ 1778

Last change on this file since 1778 was 626, checked in by Matthäus Wander, 12 years ago

Caesar:

  • changeable settings during execution, closes #88
File size: 14.8 KB
Line 
1/*                             
2   Copyright 2009 Arno Wacker, Uni Duisburg-Essen
3
4   Licensed under the Apache License, Version 2.0 (the "License");
5   you may not use this file except in compliance with the License.
6   You may obtain a copy of the License at
7
8       http://www.apache.org/licenses/LICENSE-2.0
9
10   Unless required by applicable law or agreed to in writing, software
11   distributed under the License is distributed on an "AS IS" BASIS,
12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   See the License for the specific language governing permissions and
14   limitations under the License.
15*/
16
17using System;
18using System.ComponentModel;
19using System.Windows;
20using Cryptool.PluginBase;
21using System.Windows.Controls;
22
23namespace Cryptool.Caesar
24{
25    public class CaesarSettings : ISettings
26    {
27        #region Public Caesar specific interface
28       
29        /// <summary>
30        /// We use this delegate to send log messages from the settings class to the Caesar plugin
31        /// </summary>
32        public delegate void CaesarLogMessage(string msg, NotificationLevel loglevel);
33
34        /// <summary>
35        /// An enumaration for the different modes of dealing with unknown characters
36        /// </summary>
37        public enum UnknownSymbolHandlingMode { Ignore = 0, Remove = 1, Replace = 2 };
38
39
40        /// <summary>
41        /// Feuern, wenn ein neuer Text im Statusbar angezeigt werden soll.
42        /// </summary>
43        public event CaesarLogMessage LogMessage;
44
45        public delegate void CaesarReExecute();
46
47        public event CaesarReExecute ReExecute;
48
49        /// <summary>
50        /// Retrieves the current sihft value of Caesar (i.e. the key), or sets it
51        /// </summary>
52        [PropertySaveOrder(0)]
53        public int ShiftKey
54        {
55            get { return shiftValue; }
56            set
57            {
58                setKeyByValue(value);
59            }
60        }
61
62        /// <summary>
63        /// Retrieves the current setting whether the alphabet should be treated as case sensitive or not
64        /// </summary>
65        [PropertySaveOrder(1)]
66        public bool CaseSensitiveAlphabet
67        {
68            get
69            {
70                if (caseSensitiveAlphabet == 0)
71                {   return false;   }
72                else
73                {   return true;    }
74            }
75            set {} // readonly, because there are some problems if we omit the set part.
76        }
77
78
79        /// <summary>
80        /// Returns true if some settings have been changed. This value should be set externally to false e.g.
81        /// when a project was saved.
82        /// </summary>
83        [PropertySaveOrder(3)]
84        public bool HasChanges
85        {
86            get { return hasChanges; }
87            set { hasChanges = value; }
88        }
89
90        #endregion
91
92        #region Private variables
93        private bool hasChanges;
94        private int selectedAction = 0;
95        private string upperAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
96        private string lowerAlphabet = "abcdefghijklmnopqrstuvwxyz";
97        private string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
98        private char shiftChar = 'C';
99        private int shiftValue = 2; 
100        // private int shiftValue = 2;
101        private UnknownSymbolHandlingMode unknownSymbolHandling = UnknownSymbolHandlingMode.Ignore;
102        private int caseSensitiveAlphabet = 0; // 0 = case insensitve, 1 = case sensitive
103        private bool sensitivityEnabled = true;
104        #endregion
105
106        #region Private methods
107
108        private string removeEqualChars(string value)
109        {
110            int length = value.Length;
111
112            for (int i = 0; i < length; i++)
113            {
114                for (int j = i + 1; j < length; j++)
115                {
116                    if ((value[i] == value[j]) || (!CaseSensitiveAlphabet & (char.ToUpper(value[i]) == char.ToUpper(value[j]))))
117                    {
118                        LogMessage("Removing duplicate letter: \'" + value[j] + "\' from alphabet!", NotificationLevel.Warning);
119                        value = value.Remove(j,1);
120                        j--;
121                        length--;
122                    }
123                }
124            }
125
126            return value;
127        }
128
129        /// <summary>
130        /// Set the new shiftValue and the new shiftCharacter to offset % alphabet.Length
131        /// </summary>
132        private void setKeyByValue(int offset)
133        {
134            HasChanges = true;
135
136            // making sure the shift value lies within the alphabet range     
137            offset = offset % alphabet.Length;
138
139            // set the new shiftChar
140            shiftChar = alphabet[offset];
141
142            // set the new shiftValue
143            shiftValue = offset;
144
145            // Anounnce this to the settings pane
146            OnPropertyChanged("ShiftValue");
147            OnPropertyChanged("ShiftChar");
148
149            // print some info in the log.
150            LogMessage("Accepted new shift value " + offset + "! (Adjusted shift character to \'" + shiftChar + "\')", NotificationLevel.Info);
151        }
152
153        private void setKeyByCharacter(string value)
154        {
155            try
156            {
157                int offset;
158                if (this.CaseSensitiveAlphabet)
159                {
160                    offset = alphabet.IndexOf(value[0]);
161                }
162                else
163                {
164                    offset = alphabet.ToUpper().IndexOf(char.ToUpper(value[0]));
165                }
166               
167                if (offset >= 0)
168                {
169                    HasChanges = true;
170                    shiftValue = offset;
171                    shiftChar = alphabet[shiftValue];
172                    LogMessage("Accepted new shift character \'" + shiftChar + "\'! (Adjusted shift value to " + shiftValue + ")", NotificationLevel.Info);
173                    OnPropertyChanged("ShiftValue");
174                    OnPropertyChanged("ShiftChar");
175                }
176                else
177                {
178                    LogMessage("Bad input \"" + value + "\"! (Character not in alphabet!) Reverting to " + shiftChar.ToString() + "!", NotificationLevel.Error);
179                }
180            }
181            catch (Exception e)
182            {
183                LogMessage("Bad input \"" + value + "\"! (" + e.Message + ") Reverting to " + shiftChar.ToString() + "!", NotificationLevel.Error);
184            }
185        } 
186
187        #endregion
188
189        #region Algorithm settings properties (visible in the Settings pane)
190
191        [PropertySaveOrder(4)]
192        [ContextMenu("Action", "Select the Algorithm action", 1, DisplayLevel.Beginner, ContextMenuControlType.ComboBox, new int[] { 1, 2 }, "Encrypt", "Decrypt")]
193        [TaskPane("Action", "setAlgorithmActionDescription", null, 1, true, DisplayLevel.Beginner, ControlType.ComboBox, new string[] { "Encrypt", "Decrypt" })]
194        public int Action
195        {
196            get
197            {
198                return this.selectedAction;
199            }
200            set
201            {
202                if (value != selectedAction) HasChanges = true;
203                this.selectedAction = value;
204                OnPropertyChanged("Action");
205
206                if (ReExecute != null) ReExecute();
207            }
208        }
209       
210        [PropertySaveOrder(5)]
211        [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)]       
212        public int ShiftValue
213        {
214            get { return shiftValue; }
215            set
216            {
217                setKeyByValue(value);
218                if (ReExecute != null) ReExecute();
219            }
220        }
221
222
223        [PropertySaveOrder(6)]
224        [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}$")]
225        public string ShiftChar
226        {
227            get { return this.shiftChar.ToString(); }
228            set
229            {
230                setKeyByCharacter(value);
231                if (ReExecute != null) ReExecute();
232            }
233        }
234
235        [PropertySaveOrder(7)]
236        [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 \'?\'" })]
237        [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 \'?\'" })]
238        public int UnknownSymbolHandling
239        {
240            get { return (int)this.unknownSymbolHandling; }
241            set
242            {
243                if ((UnknownSymbolHandlingMode)value != unknownSymbolHandling) HasChanges = true;
244                this.unknownSymbolHandling = (UnknownSymbolHandlingMode)value;
245                OnPropertyChanged("UnknownSymbolHandling");
246
247                if (ReExecute != null) ReExecute();
248            }
249        }
250
251        [SettingsFormat(0, "Normal", "Normal", "Black", "White", Orientation.Vertical)]
252        [PropertySaveOrder(9)]
253        [TaskPane("Alphabet", "This is the used alphabet.", null, 6, true, DisplayLevel.Expert, ControlType.TextBox, "")]
254        public string AlphabetSymbols
255        {
256          get { return this.alphabet; }
257          set
258          {
259            string a = removeEqualChars(value);
260            if (a.Length == 0) // cannot accept empty alphabets
261            {
262              LogMessage("Ignoring empty alphabet from user! Using previous alphabet: \"" + alphabet + "\" (" + alphabet.Length.ToString() + " Symbols)", NotificationLevel.Info);
263            }
264            else if (!alphabet.Equals(a))
265            {
266              HasChanges = true;
267              this.alphabet = a;
268              setKeyByValue(shiftValue); //re-evaluate if the shiftvalue is still within the range
269              LogMessage("Accepted new alphabet from user: \"" + alphabet + "\" (" + alphabet.Length.ToString() + " Symbols)", NotificationLevel.Info);
270              OnPropertyChanged("AlphabetSymbols");
271
272              if (ReExecute != null) ReExecute();
273            }
274          }
275        }
276
277        /// <summary>
278        /// Visible setting how to deal with alphabet case. 0 = case insentive, 1 = case sensitive
279        /// </summary>   
280        //[SettingsFormat(1, "Normal")]
281        [PropertySaveOrder(8)]
282        [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" })]
283        [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" })]
284        public int AlphabetCase
285        {
286            get { return this.caseSensitiveAlphabet; }
287            set
288            {
289                if (value != caseSensitiveAlphabet) HasChanges = true;
290                this.caseSensitiveAlphabet = value;
291                if (value == 0)
292                {
293                    if (alphabet == (upperAlphabet + lowerAlphabet))
294                    {
295                        alphabet = upperAlphabet;
296                        LogMessage("Changing alphabet to: \"" + alphabet + "\" (" + alphabet.Length.ToString() + " Symbols)", NotificationLevel.Info);
297                        OnPropertyChanged("AlphabetSymbols");                       
298                        // re-set also the key (shiftvalue/shiftChar to be in the range of the new alphabet
299                        setKeyByValue(shiftValue);
300                    }
301                }
302                else
303                {
304                    if (alphabet == upperAlphabet)
305                    {
306                        alphabet = upperAlphabet + lowerAlphabet;
307                        LogMessage("Changing alphabet to: \"" + alphabet + "\" (" + alphabet.Length.ToString() + " Symbols)", NotificationLevel.Info);
308                        OnPropertyChanged("AlphabetSymbols");                       
309                    }
310                }
311
312                // remove equal characters from the current alphabet
313                string a = alphabet;
314                alphabet = removeEqualChars(alphabet);
315
316                if (a != alphabet)
317                {
318                    OnPropertyChanged("AlphabetSymbols");
319                    LogMessage("Changing alphabet to: \"" + alphabet + "\" (" + alphabet.Length.ToString() + " Symbols)", NotificationLevel.Info);
320                }
321
322                OnPropertyChanged("AlphabetCase");
323                if (ReExecute != null) ReExecute();
324            }
325        }
326
327        #endregion
328
329        #region INotifyPropertyChanged Members
330
331        public event PropertyChangedEventHandler PropertyChanged;
332
333        protected void OnPropertyChanged(string name)
334        {         
335          if (PropertyChanged != null)
336          {
337            PropertyChanged(this, new PropertyChangedEventArgs(name));
338          }
339        }
340
341        #endregion
342
343        #region TaskPaneAttributeChanged-Sample
344        /// <summary>
345        /// This event is just used here for sample reasons
346        /// </summary>
347        public event TaskPaneAttributeChangedHandler TaskPaneAttributeChanged;
348
349        [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)]
350        public void EnableDisableSesitivity()
351        {
352          if (TaskPaneAttributeChanged!= null)
353          {
354            sensitivityEnabled = !sensitivityEnabled;
355            if (sensitivityEnabled)
356            {             
357              TaskPaneAttributeChanged(this, new TaskPaneAttributeChangedEventArgs(new TaskPaneAttribteContainer("AlphabetCase", Visibility.Visible)));
358            }
359            else
360            {
361              TaskPaneAttributeChanged(this, new TaskPaneAttributeChangedEventArgs(new TaskPaneAttribteContainer("AlphabetCase", Visibility.Collapsed)));
362            }
363          }
364        }
365        #endregion TaskPaneAttributeChanged-Sample
366    }
367}
Note: See TracBrowser for help on using the repository browser.