source: trunk/CrypPlugins/TextOutput/TextOutput.cs @ 2061

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

Nihilist:

TextOutput:

  • added decimal output format (output bytes as decimal numbers, separated by whitespace)
File size: 19.2 KB
Line 
1/*
2   Copyright 2008 Thomas Schmid, University of Siegen
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.Collections.Generic;
19using System.Linq;
20using System.Text;
21using Cryptool.PluginBase;
22using System.Windows;
23using System.IO;
24using System.Windows.Controls;
25using System.Windows.Threading;
26using System.Threading;
27using System.ComponentModel;
28using Cryptool.PluginBase.IO;
29using System.Reflection;
30using System.Runtime.CompilerServices;
31using Cryptool.PluginBase.Miscellaneous;
32using System.Runtime.Remoting.Contexts;
33
34namespace TextOutput
35{
36  [Author("Thomas Schmid", "thomas.schmid@cryptool.org", "Uni Siegen", "http://www.uni-siegen.de")]
37  [PluginInfo(false, "TextOutput", "Simple text output", "", "TextOutput/icon.png")]
38  public class TextOutput : DependencyObject, IOutput
39  {
40    private readonly string inputOne = "InputOne";
41
42    #region Private variables
43    private List<CryptoolStream> listCryptoolStreamsOut = new List<CryptoolStream>();
44    /// <summary>
45    /// This dic is used to store error messages while properties are set in PlayMode. The messages
46    /// will be send in the execute method.
47    /// The editor flushes plugin color markers before calling the execute method.
48    /// So this messages would would still appear in LogWindow, but the color marker of the
49    /// plugin(red/yellow) would be lost if sending the messages right on property set.
50    /// </summary>
51    private Dictionary<string, NotificationLevel> dicWarningsAndErros = new Dictionary<string, NotificationLevel>();
52    private bool canSendPropertiesChangedEvent = true;
53    private int inputs = 0;
54    private string fillValue;
55    #endregion
56
57    #region events
58    public event DynamicPropertiesChanged OnDynamicPropertiesChanged;
59    public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
60    public event PropertyChangedEventHandler PropertyChanged;
61    #pragma warning disable 67
62    public event StatusChangedEventHandler OnPluginStatusChanged;
63    #pragma warning restore
64    #endregion events
65
66    # region constructor
67    public TextOutput()
68    {
69      Presentation = new TextOutputPresentation();
70      QuickWatchPresentation = new TextOutputPresentation();
71      settings = new TextOutputSettings(this);
72      settings.OnGuiLogNotificationOccured += settings_OnGuiLogNotificationOccured;
73      settings.PropertyChanged += settings_PropertyChanged;
74      CanChangeDynamicProperty = true;
75      // No dynProp event in constructor - editor will read the property initial without the event.
76      // event can cause problems when using save files and is processed after
77      // connections have been restored.
78      CreateInputOutput(false);
79    }
80
81    # endregion
82
83    # region Properties
84
85    TextOutputSettings settings;
86    public ISettings Settings
87    {
88      get { return settings; }
89      set { settings = (TextOutputSettings)value; }
90    }
91
92    public void CreateInputOutput(bool announcePropertyChange)
93    {
94      DicDynamicProperties.Clear();
95      AddInput(inputOne, "Input value");
96      if (announcePropertyChange) DynamicPropertiesChanged();
97    }
98
99    private void DynamicPropertiesChanged()
100    {
101      if (OnDynamicPropertiesChanged != null) OnDynamicPropertiesChanged(this);
102    }
103
104    private void settings_OnGuiLogNotificationOccured(IPlugin sender, GuiLogEventArgs args)
105    {
106      EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this, new GuiLogEventArgs(args.Message, this, args.NotificationLevel));
107    }
108
109    void settings_PropertyChanged(object sender, PropertyChangedEventArgs e)
110    {
111      if (e.PropertyName == "PresentationFormatSetting" && fillValue != null)
112      {
113        setText(fillValue);
114      }
115    }
116
117    public Dictionary<string, DynamicProperty> dicDynamicProperties = new Dictionary<string, DynamicProperty>();
118
119    [DynamicPropertyInfo("methodGetValue", "methodSetValue", "CanChangeDynamicProperty", "OnDynamicPropertiesChanged", "CanSendPropertiesChangedEvent")]
120    public Dictionary<string, DynamicProperty> DicDynamicProperties
121    {
122      get { return dicDynamicProperties; }
123      set { dicDynamicProperties = value; }
124    }
125
126    public bool CanChangeDynamicProperty
127    {
128      get { return settings.CanChangeProperty; }
129      set { settings.CanChangeProperty = value; }
130    }
131
132    public bool CanSendPropertiesChangedEvent
133    {
134      get { return canSendPropertiesChangedEvent; }
135      set { canSendPropertiesChangedEvent = value; }
136    }
137
138
139    private Type getCurrentType()
140    {
141      switch (settings.CurrentDataType)
142      {
143        case TextOutputSettings.DynamicDataTypes.CryptoolStream:
144          return typeof(CryptoolStream);
145        case TextOutputSettings.DynamicDataTypes.String:
146          return typeof(string);
147        case TextOutputSettings.DynamicDataTypes.ByteArray:
148          return typeof(byte[]);
149        case TextOutputSettings.DynamicDataTypes.Boolean:
150          return typeof(bool);
151        case TextOutputSettings.DynamicDataTypes.Integer:
152          return typeof(int);
153        case TextOutputSettings.DynamicDataTypes.Double:
154          return typeof(double);
155        case TextOutputSettings.DynamicDataTypes.Object:
156          return typeof(object);
157        default:
158          return null;
159      }
160    }
161
162    private object getCurrentValue(string name)
163    {
164      if (DicDynamicProperties.ContainsKey(name))
165      {
166        switch (settings.CurrentDataType)
167        {
168          case TextOutputSettings.DynamicDataTypes.CryptoolStream:
169            if ((CryptoolStream)DicDynamicProperties[name].Value != null)
170            {
171              CryptoolStream cryptoolStream = new CryptoolStream();
172              listCryptoolStreamsOut.Add(cryptoolStream);
173              cryptoolStream.OpenRead(((CryptoolStream)DicDynamicProperties[name].Value).FileName);
174              return cryptoolStream;
175            }
176            else
177              return null;
178          case TextOutputSettings.DynamicDataTypes.String:
179            return DicDynamicProperties[name].Value;
180          case TextOutputSettings.DynamicDataTypes.ByteArray:
181            return DicDynamicProperties[name].Value;
182          case TextOutputSettings.DynamicDataTypes.Boolean:
183            return DicDynamicProperties[name].Value;
184          case TextOutputSettings.DynamicDataTypes.Integer:
185            return DicDynamicProperties[name].Value;
186          case TextOutputSettings.DynamicDataTypes.Double:
187            return DicDynamicProperties[name].Value;
188          case TextOutputSettings.DynamicDataTypes.Object:
189            return DicDynamicProperties[name].Value;
190          default:
191            return null;
192        }
193      }
194      return null;
195    }
196
197    private void AddInput(string name, string toolTip)
198    {
199      inputs++;
200      if (name == null || name == string.Empty) name = "Input " + inputs;
201      DicDynamicProperties.Add(name,
202        new DynamicProperty(name, getCurrentType(),
203          new PropertyInfoAttribute(Direction.InputData, name, toolTip, "", false, true, DisplayLevel.Beginner, QuickWatchFormat.None, null))
204      );
205    }
206
207    [MethodImpl(MethodImplOptions.Synchronized)]
208    public void methodSetValue(string propertyKey, object value)
209    {
210      try
211      {
212        if (DicDynamicProperties.ContainsKey(propertyKey))
213        {
214          DicDynamicProperties[propertyKey].Value = value;
215        }
216
217        if (value == null)
218        {
219            fillValue = string.Empty;
220            OnPropertyChanged(propertyKey);
221        }
222        else
223        {
224            // check type explicitly, if connector type is set to anything else than object
225            if (getCurrentType() != typeof(object) && !getCurrentType().Equals(value.GetType()))
226            {
227                GuiLogMessage(String.Format("Input data type does not match setting. Expected: {0}, Found: {1}", getCurrentType(), value.GetType()),
228                    NotificationLevel.Error);
229                return;
230            }
231
232            if (value is bool)
233            {
234                if (settings.BooleanAsNumeric)
235                {
236                    fillValue = Convert.ToInt32(value).ToString();
237                }
238                else
239                {
240                    fillValue = ((bool)value).ToString();
241                }
242            }
243            else if (value is CryptoolStream)
244            {
245                listCryptoolStreamsOut.Add((CryptoolStream)value);
246                CryptoolStream stream = value as CryptoolStream;
247                // GuiLogMessage("Stream: Filling TextBoxes now...", NotificationLevel.Debug);
248                if (stream.Length > settings.MaxLength)
249                    AddMessage("WARNING - Stream is too large (" + (stream.Length / 1024).ToString("0.00") + " kB), output will be truncated to " + (settings.MaxLength / 1024).ToString("0.00") + "kB", NotificationLevel.Warning);
250                byte[] byteValues = new byte[Math.Min(settings.MaxLength, stream.Length)];
251                int bytesRead;
252                stream.Seek(0, SeekOrigin.Begin);
253                bytesRead = stream.Read(byteValues, 0, byteValues.Length);
254                fillValue = GetStringForSelectedEncoding(byteValues);
255            }
256            else if (value is byte[])
257            {
258                byte[] byteArray = value as byte[];
259                // GuiLogMessage("Byte array: Filling textbox now...", NotificationLevel.Debug);
260                if (byteArray.Length > settings.MaxLength)
261                {
262                    AddMessage("WARNING - byte array is too large (" + (byteArray.Length / 1024).ToString("0.00") + " kB), output will be truncated to " + (settings.MaxLength / 1024).ToString("0.00") + "kB", NotificationLevel.Warning);
263                }
264
265                long size = byteArray.Length;
266                if (size > settings.MaxLength)
267                {
268                    size = settings.MaxLength;
269                }
270                byte[] sizedArray = new byte[size];
271                for (int i = 0; i < size; i++)
272                {
273                    sizedArray[i] = byteArray[i];
274                }
275                fillValue = GetStringForSelectedEncoding(sizedArray);
276            }
277            else
278            {
279                fillValue = value.ToString();
280            }
281        }
282
283        if (fillValue != null)
284        {
285            if (fillValue.Length > settings.MaxLength)
286            {
287                fillValue = fillValue.Substring(0, settings.MaxLength);
288            }
289
290            setText(fillValue);
291            OnPropertyChanged(propertyKey);
292        }
293      }
294      catch (Exception ex)
295      {
296        GuiLogMessage(ex.Message, NotificationLevel.Error);
297      }
298    }
299
300    private void setText(string fillValue)
301    {
302      if (fillValue != null)
303      {
304        // Presentation format conversion
305        switch (settings.Presentation)
306        {
307          case TextOutputSettings.PresentationFormat.Text:
308            // nothin to do here
309            break;
310          case TextOutputSettings.PresentationFormat.Hex:
311            byte[] byteValues = Encoding.Default.GetBytes(fillValue.ToCharArray());
312            fillValue = BitConverter.ToString(byteValues, 0, byteValues.Length).Replace("-", "");
313            break;
314          case TextOutputSettings.PresentationFormat.Base64:
315            fillValue = Convert.ToBase64String(Encoding.Default.GetBytes(fillValue.ToCharArray()));
316            break;
317          case TextOutputSettings.PresentationFormat.Decimal:
318            byte[] decValues = Encoding.Default.GetBytes(fillValue.ToCharArray());
319            StringBuilder sb = new StringBuilder();
320            if (decValues.Length > 0)
321            {
322              sb.Append(decValues[0]);
323              for (int i = 1; i < decValues.Length; i++)
324              {
325                sb.Append(" ");
326                sb.Append(decValues[i]);
327              }
328            }
329            fillValue = sb.ToString();
330            break;
331          default:
332            break;
333        }
334
335
336        Presentation.Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
337        {
338          if (settings.Append)
339          {
340            if (textOutputPresentation.textBox.Text.Length > settings.MaxLength)
341            {
342              GuiLogMessage("Text exceeds size limit. Deleting text...", NotificationLevel.Debug);
343              textOutputPresentation.textBox.Text = string.Empty;
344              textOutputQuickWatchPresentation.textBox.Text = string.Empty;
345            }
346
347            // append line breaks only if not first line
348            if (textOutputPresentation.textBox.Text != null && textOutputPresentation.textBox.Text.Length > 0)
349            {
350              for (int i = 0; i < settings.AppendBreaks; i++)
351              {
352                textOutputPresentation.textBox.AppendText("\n");
353                textOutputQuickWatchPresentation.textBox.AppendText("\n");
354              }
355            }
356            textOutputPresentation.textBox.AppendText(fillValue);
357            textOutputQuickWatchPresentation.textBox.AppendText(fillValue);
358
359            textOutputPresentation.textBox.ScrollToEnd();
360            textOutputQuickWatchPresentation.textBox.ScrollToEnd();
361          }
362          else
363          {
364            textOutputPresentation.textBox.Text = fillValue;
365            textOutputQuickWatchPresentation.textBox.Text = fillValue;
366          }
367          if (settings.BooleanAsNumeric)
368          {
369              textOutputPresentation.labelBytes.Content = string.Format("{0:0,0}", Encoding.Default.GetBytes(textOutputPresentation.textBox.Text.ToCharArray()).Length) + " Bits";
370              textOutputQuickWatchPresentation.labelBytes.Content = string.Format("{0:0,0}", Encoding.Default.GetBytes(textOutputPresentation.textBox.Text.ToCharArray()).Length) + " Bits";
371          }
372          else
373          {
374              textOutputPresentation.labelBytes.Content = string.Format("{0:0,0}", Encoding.Default.GetBytes(textOutputPresentation.textBox.Text.ToCharArray()).Length) + " Bytes";
375              textOutputQuickWatchPresentation.labelBytes.Content = string.Format("{0:0,0}", Encoding.Default.GetBytes(textOutputPresentation.textBox.Text.ToCharArray()).Length) + " Bytes";
376          }
377        }, fillValue);
378      }
379    }
380
381    private List<string> listBuffer = new List<string>();
382
383    [MethodImpl(MethodImplOptions.Synchronized)]
384    public object methodGetValue(string propertyKey)
385    {
386      return getCurrentValue(propertyKey); // QuickWatchDataCall to Input values
387    }
388
389    #endregion
390
391    # region methods
392    private string GetStringForSelectedEncoding(byte[] arrByte)
393    {
394      if (arrByte != null)
395      {
396        GuiLogMessage("Converting from \"" + settings.Encoding.ToString() + "\"...", NotificationLevel.Debug);
397        string returnValue;
398
399        // here conversion happens
400        switch (settings.Encoding)
401        {
402          case TextOutputSettings.EncodingTypes.Default:
403            returnValue = Encoding.Default.GetString(arrByte, 0, arrByte.Length);
404            break;
405          case TextOutputSettings.EncodingTypes.Unicode:
406            returnValue = Encoding.Unicode.GetString(arrByte, 0, arrByte.Length);
407            break;
408          case TextOutputSettings.EncodingTypes.UTF7:
409            returnValue = Encoding.UTF7.GetString(arrByte, 0, arrByte.Length);
410            break;
411          case TextOutputSettings.EncodingTypes.UTF8:
412            returnValue = Encoding.UTF8.GetString(arrByte, 0, arrByte.Length);
413            break;
414          case TextOutputSettings.EncodingTypes.UTF32:
415            returnValue = Encoding.UTF32.GetString(arrByte, 0, arrByte.Length);
416            break;
417          case TextOutputSettings.EncodingTypes.ASCII:
418            returnValue = Encoding.ASCII.GetString(arrByte, 0, arrByte.Length);
419            break;
420          case TextOutputSettings.EncodingTypes.BigEndianUnicode:
421            returnValue = Encoding.BigEndianUnicode.GetString(arrByte, 0, arrByte.Length);
422            break;
423          default:
424            returnValue = Encoding.Default.GetString(arrByte, 0, arrByte.Length);
425            break;
426        }
427        return returnValue;
428      }
429      return null;
430    }
431
432    private void Progress(double value, double max)
433    {
434      EventsHelper.ProgressChanged(OnPluginProgressChanged, this, new PluginProgressEventArgs(value, max));
435    }
436    # endregion
437
438    #region INotifyPropertyChanged Members
439   
440    public void OnPropertyChanged(string name)
441    {
442      EventsHelper.PropertyChanged(PropertyChanged, this, new PropertyChangedEventArgs(name));
443    }
444
445    #endregion
446
447    #region IPlugin Members
448
449    private TextOutputPresentation textOutputPresentation
450    {
451      get { return Presentation as TextOutputPresentation; }
452    }
453
454    private TextOutputPresentation textOutputQuickWatchPresentation
455    {
456      get { return QuickWatchPresentation as TextOutputPresentation; }
457    }
458
459    public UserControl Presentation { get; private set; }
460
461    public UserControl QuickWatchPresentation { get; private set; }
462
463    public void Initialize()
464    {
465
466    }
467
468    public void Dispose()
469    {
470      foreach (CryptoolStream cryptoolStream in listCryptoolStreamsOut)
471      {
472        cryptoolStream.Close();
473      }
474      listCryptoolStreamsOut.Clear();
475    }
476
477    public void Stop()
478    {
479
480    }
481
482    public void PreExecution()
483    {
484      if (settings.FlushOnPreExecution)
485      {
486        textOutputPresentation.Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
487        {
488          textOutputPresentation.textBox.Text = null;
489          textOutputQuickWatchPresentation.textBox.Text = null;
490        }, null);
491      }
492      foreach (DynamicProperty item in dicDynamicProperties.Values)
493      {
494        if (item.Value is CryptoolStream)
495        {
496          item.Value = null;
497        }
498      }
499      Dispose();
500    }
501
502    public void PostExecution()
503    {
504      Dispose();
505    }
506
507    private void GuiLogMessage(string message, NotificationLevel logLevel)
508    {
509      EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this, new GuiLogEventArgs(message, this, logLevel));
510    }
511
512    public event PluginProgressChangedEventHandler OnPluginProgressChanged;
513
514    public void Execute()
515    {
516      Progress(100, 100);
517      foreach (KeyValuePair<string, NotificationLevel> kvp in dicWarningsAndErros)
518      {
519        GuiLogMessage(kvp.Key, kvp.Value);
520      }
521      dicWarningsAndErros.Clear();
522    }
523
524    public void Pause()
525    {
526
527    }
528
529    private void AddMessage(string message, NotificationLevel level)
530    {
531      if (!dicWarningsAndErros.ContainsKey(message))
532        dicWarningsAndErros.Add(message, level);
533    }
534
535    #endregion
536  }
537}
Note: See TracBrowser for help on using the repository browser.