From e258ef14ddcf9e60cf6a018b4a5dd87e49a8723f Mon Sep 17 00:00:00 2001
From: Dmitrii Cetvericov <dmitrii.cetvericov@fau.de>
Date: Mon, 14 Sep 2020 21:14:09 +0200
Subject: [PATCH] Fix "How many bytes do I have left to send before the gate
 closes?" mechanism + add processing delay to scheduler.

---
 .../CBSVisualizer.Common.csproj               |   1 +
 .../CBSVisualizer.Core.csproj                 |   2 +-
 .../CBSVisualizer.Messaging.csproj            |   1 +
 .../Events/RegisterLinkCallbackEvent.cs       |  12 +-
 .../Models/PriorityPacket.cs                  |  42 ++-
 .../CBSVisualizer.Modules.Link.csproj         |  15 +-
 .../Externals/BoolToImageConverter.cs         |  30 --
 .../Properties/Resources.Designer.cs          |  83 -----
 .../Properties/Resources.resx                 | 127 -------
 .../Resources/greendot.png                    | Bin 896 -> 0 bytes
 .../Resources/reddot.png                      | Bin 1074 -> 0 bytes
 .../ViewModels/LinkViewModel.cs               | 114 +++----
 .../Views/Link.xaml                           | 114 +++++--
 .../CBSVisualizer.Modules.MenuBar.csproj      |   4 +-
 .../MenuBarViewModel.LoadGeneration.cs        |  49 +--
 .../ViewModels/MenuBarViewModel.cs            |  17 +-
 .../CBSVisualizer.Modules.QueueGroup.csproj   |   3 +-
 .../Views/QueueGroup.xaml                     |  11 -
 .../Views/QueueGroup.xaml.cs                  |  11 +-
 .../CBSVisualizer.Modules.Queue.csproj        |   6 +-
 .../QueueViewModel.LinkCallbacks.cs           | 316 ++++++++++--------
 .../ViewModels/QueueViewModel.cs              | 236 ++++++++-----
 .../Views/Queue.xaml                          |  38 ++-
 .../Views/Queue.xaml.cs                       |  18 +-
 ...BSVisualizer.Modules.SettingsDialog.csproj |   3 +-
 .../ViewModels/SettingsDialogViewModel.cs     |   8 +-
 .../Views/SettingsDialog.xaml                 |   8 +-
 ...BSVisualizer.Services.PacketService.csproj |  11 +
 .../Implementation/RandomPacketService.cs     |  37 ++
 .../Interface/IPacketService.cs               |  22 ++
 ...sualizer.Services.SchedulingService.csproj |   2 +-
 .../Implementation/RandomSchedulingService.cs |  31 +-
 .../Interface/ISchedulingService.cs           |  12 +-
 ...SVisualizer.Services.SettingService.csproj |   1 +
 .../SettingService.cs                         |   2 +-
 CBSVisualizer/CBSVisualizer.sln               |   7 +
 CBSVisualizer/CBSVisualizer/App.xaml          |   7 +
 CBSVisualizer/CBSVisualizer/App.xaml.cs       |   7 +-
 .../CBSVisualizer/CBSVisualizer.csproj        |   4 +-
 .../CBSVisualizer/Views/MainWindow.xaml       |  15 +-
 40 files changed, 709 insertions(+), 718 deletions(-)
 delete mode 100644 CBSVisualizer/CBSVisualizer.Modules.Link/Externals/BoolToImageConverter.cs
 delete mode 100644 CBSVisualizer/CBSVisualizer.Modules.Link/Properties/Resources.Designer.cs
 delete mode 100644 CBSVisualizer/CBSVisualizer.Modules.Link/Properties/Resources.resx
 delete mode 100644 CBSVisualizer/CBSVisualizer.Modules.Link/Resources/greendot.png
 delete mode 100644 CBSVisualizer/CBSVisualizer.Modules.Link/Resources/reddot.png
 create mode 100644 CBSVisualizer/CBSVisualizer.Services.PacketService/CBSVisualizer.Services.PacketService.csproj
 create mode 100644 CBSVisualizer/CBSVisualizer.Services.PacketService/Implementation/RandomPacketService.cs
 create mode 100644 CBSVisualizer/CBSVisualizer.Services.PacketService/Interface/IPacketService.cs
 rename CBSVisualizer/CBSVisualizer.Services.SettingsService/{Service => Implementation}/SettingService.cs (96%)

diff --git a/CBSVisualizer/CBSVisualizer.Common/CBSVisualizer.Common.csproj b/CBSVisualizer/CBSVisualizer.Common/CBSVisualizer.Common.csproj
index 0a54f5c..6a7fe1b 100644
--- a/CBSVisualizer/CBSVisualizer.Common/CBSVisualizer.Common.csproj
+++ b/CBSVisualizer/CBSVisualizer.Common/CBSVisualizer.Common.csproj
@@ -5,6 +5,7 @@
   </PropertyGroup>
 
   <ItemGroup>
+    <PackageReference Include="log4net" Version="2.0.9" />
     <PackageReference Include="Prism.Core" Version="7.2.0.1422" />
   </ItemGroup>
 
diff --git a/CBSVisualizer/CBSVisualizer.Core/CBSVisualizer.Core.csproj b/CBSVisualizer/CBSVisualizer.Core/CBSVisualizer.Core.csproj
index 16f7d6c..f6367cc 100644
--- a/CBSVisualizer/CBSVisualizer.Core/CBSVisualizer.Core.csproj
+++ b/CBSVisualizer/CBSVisualizer.Core/CBSVisualizer.Core.csproj
@@ -5,7 +5,7 @@
     <AssemblyName>CBSVisualizer.Core</AssemblyName>
   </PropertyGroup>
   <ItemGroup>
-    <PackageReference Include="log4net" Version="2.0.8" />
+    <PackageReference Include="log4net" Version="2.0.9" />
     <PackageReference Include="Prism.Wpf" Version="7.2.0.1422" />
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/CBSVisualizer/CBSVisualizer.MessagingCore/CBSVisualizer.Messaging.csproj b/CBSVisualizer/CBSVisualizer.MessagingCore/CBSVisualizer.Messaging.csproj
index a1193fe..73d623a 100644
--- a/CBSVisualizer/CBSVisualizer.MessagingCore/CBSVisualizer.Messaging.csproj
+++ b/CBSVisualizer/CBSVisualizer.MessagingCore/CBSVisualizer.Messaging.csproj
@@ -5,6 +5,7 @@
   </PropertyGroup>
 
   <ItemGroup>
+    <PackageReference Include="log4net" Version="2.0.9" />
     <PackageReference Include="Prism.Core" Version="7.2.0.1422" />
   </ItemGroup>
 
diff --git a/CBSVisualizer/CBSVisualizer.MessagingCore/Events/RegisterLinkCallbackEvent.cs b/CBSVisualizer/CBSVisualizer.MessagingCore/Events/RegisterLinkCallbackEvent.cs
index d564aef..21304fe 100644
--- a/CBSVisualizer/CBSVisualizer.MessagingCore/Events/RegisterLinkCallbackEvent.cs
+++ b/CBSVisualizer/CBSVisualizer.MessagingCore/Events/RegisterLinkCallbackEvent.cs
@@ -35,36 +35,36 @@ namespace CBSVisualizer.Messaging.Events
         /// Allows to perform necessary initialization operations.
         /// </summary>
         /// <returns></returns>
-        Task Initialize();
+        void Initialize();
 
         /// <summary>
         /// Called by the link when the gate of this queue has been opened.
         /// </summary>
         /// <param name="trySubmitFirstPacket">Called with the packet that should be sent. Returns the result of the attempt (Accepted or Denied because of whatever reason). </param>
-        Task GateOpened(Func<PriorityPacket, PacketSubmitResult> trySubmitFirstPacket);
+        void GateOpened(Func<PriorityPacket, PacketSubmitResult> trySubmitFirstPacket);
 
         /// <summary>
         /// Called by the link if the gate of the queue has been closed.
         /// </summary>
-        Task GateClosed();
+        void GateClosed();
 
         /// <summary>
         /// Called by the gate if the transmission of the given packet has been preempted.
         /// </summary>
         /// <param name="preemptedPacket"> the preempted packet.</param>
         /// <param name="leftoverBytes"> the bytes that are left to sent.</param>
-        Task PacketPreempted(PriorityPacket preemptedPacket, int leftoverBytes);
+        void PacketPreempted(PriorityPacket preemptedPacket, int leftoverBytes);
 
         /// <summary>
         /// Called by the link when the transmission has started.
         /// </summary>
         /// <param name="bytesPerSecondRate"> the rate in bytes per second. </param>
-        Task TransmissionStarted(double bytesPerSecondRate);
+        void TransmissionStarted(long bytesPerSecondRate);
 
         /// <summary>
         /// Called when the transmission of the last packet has been completed.
         /// </summary>
-        Task TransmissionCompleted();
+        void TransmissionCompleted();
     }
     
     /// <summary>
diff --git a/CBSVisualizer/CBSVisualizer.MessagingCore/Models/PriorityPacket.cs b/CBSVisualizer/CBSVisualizer.MessagingCore/Models/PriorityPacket.cs
index 00be892..475ab8d 100644
--- a/CBSVisualizer/CBSVisualizer.MessagingCore/Models/PriorityPacket.cs
+++ b/CBSVisualizer/CBSVisualizer.MessagingCore/Models/PriorityPacket.cs
@@ -13,25 +13,31 @@ namespace CBSVisualizer.Messaging
 
         private static readonly int PREEMPTION_TRAILER_SIZE_BYTES = 12;
 
-        public static PriorityPacket NoPacket { get; } = new PriorityPacket(0, 0);
-        /**
-         *  The priority of the packet. 
-        */
+        public static PriorityPacket NoPacket { get; } = new PriorityPacket(0, 0) { UniqueId = -1 };
+
+        /// <summary>
+        /// The unique ID of the packet.
+        /// </summary>
+        public long UniqueId { get; private set; }
+
+        /// <summary>
+        /// The priority of the packet. 
+        /// </summary>
         public int Priority { get; private set; }
 
-        /**
-         * The header size of the packet.
-         */
+        /// <summary>
+        /// The header size of the packet.
+        /// </summary>
         public int HeaderBytes { get; private set; }
 
-        /*
-        * The amount of payload bytes.
-        */
+        /// <summary>
+        /// The amount of payload bytes.
+        /// </summary>
         public int PayloadBytes { get; private set; }
 
-        /**
-         * The amount of trailer bytes.
-         */
+        /// <summary>
+        /// The amount of trailer bytes.
+        /// </summary>
         public int TrailerBytes { get; private set; }
 
         public int Size
@@ -42,6 +48,8 @@ namespace CBSVisualizer.Messaging
             }
         }
 
+        private static long currentId = 0;
+
         /// <summary>
         /// Constructs a new PriorityPacket.
         /// </summary>
@@ -51,6 +59,7 @@ namespace CBSVisualizer.Messaging
         /// <param name="trailerBytes"></param>
         public PriorityPacket(int prio, int headerBytes, int payloadBytes, int trailerBytes)
         {
+            UniqueId = currentId++;
             Priority = prio;
             HeaderBytes = headerBytes;
             PayloadBytes = payloadBytes;
@@ -63,16 +72,13 @@ namespace CBSVisualizer.Messaging
         /// <param name="prio"></param>
         /// <param name="payloadBytes"></param>
         public PriorityPacket(int prio, int payloadBytes)
+            : this(prio, payloadBytes, PREEMPTION_HEADER_SIZE_BYTES, PREEMPTION_TRAILER_SIZE_BYTES)
         {
-            Priority = prio;
-            PayloadBytes = payloadBytes;
-            HeaderBytes = PREEMPTION_HEADER_SIZE_BYTES;
-            TrailerBytes = PREEMPTION_TRAILER_SIZE_BYTES;
         }
 
         public override string ToString()
         {
-            return $"Priority: {Priority}, Header Size: {HeaderBytes}, Payload Bytes: {PayloadBytes}, Trailer Bytes: {TrailerBytes}";
+            return $"ID: {UniqueId} Priority: {Priority}, Header Size: {HeaderBytes}, Payload Bytes: {PayloadBytes}, Trailer Bytes: {TrailerBytes}";
         }
     }
 }
diff --git a/CBSVisualizer/CBSVisualizer.Modules.Link/CBSVisualizer.Modules.Link.csproj b/CBSVisualizer/CBSVisualizer.Modules.Link/CBSVisualizer.Modules.Link.csproj
index b2c95d5..88a26a2 100644
--- a/CBSVisualizer/CBSVisualizer.Modules.Link/CBSVisualizer.Modules.Link.csproj
+++ b/CBSVisualizer/CBSVisualizer.Modules.Link/CBSVisualizer.Modules.Link.csproj
@@ -5,6 +5,8 @@
     <AssemblyName>CBSVisualizer.Modules.Link</AssemblyName>
   </PropertyGroup>
   <ItemGroup>
+    <PackageReference Include="log4net" Version="2.0.9" />
+    <PackageReference Include="MaterialDesignThemes" Version="3.1.3" />
     <PackageReference Include="ParallelExtensionsExtras" Version="1.2.0" />
     <PackageReference Include="Prism.Wpf" Version="7.2.0.1422" />
   </ItemGroup>
@@ -14,17 +16,4 @@
     <ProjectReference Include="..\CBSVisualizer.MessagingCore\CBSVisualizer.Messaging.csproj" />
     <ProjectReference Include="..\CBSVisualizer.Services.SchedulingService\CBSVisualizer.Services.SchedulingService.csproj" />
   </ItemGroup>
-  <ItemGroup>
-    <Compile Update="Properties\Resources.Designer.cs">
-      <DesignTime>True</DesignTime>
-      <AutoGen>True</AutoGen>
-      <DependentUpon>Resources.resx</DependentUpon>
-    </Compile>
-  </ItemGroup>
-  <ItemGroup>
-    <EmbeddedResource Update="Properties\Resources.resx">
-      <Generator>ResXFileCodeGenerator</Generator>
-      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
-    </EmbeddedResource>
-  </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/CBSVisualizer/CBSVisualizer.Modules.Link/Externals/BoolToImageConverter.cs b/CBSVisualizer/CBSVisualizer.Modules.Link/Externals/BoolToImageConverter.cs
deleted file mode 100644
index 0e34bdd..0000000
--- a/CBSVisualizer/CBSVisualizer.Modules.Link/Externals/BoolToImageConverter.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Resources;
-using System.Text;
-using System.Windows.Data;
-using System.Windows.Media.Imaging;
-
-namespace CBSVisualizer.Modules.Link.Externals
-{
-    public class BoolToImageConverter : IValueConverter
-    {
-        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
-        {
-            bool val = (bool)value;
-            if (val)
-            {
-                return Properties.Resources.GreenDot;
-            } else
-            {
-                return Properties.Resources.RedDot;
-            }
-        }
-
-        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
-        {
-            throw new NotImplementedException();
-        }
-    }
-}
diff --git a/CBSVisualizer/CBSVisualizer.Modules.Link/Properties/Resources.Designer.cs b/CBSVisualizer/CBSVisualizer.Modules.Link/Properties/Resources.Designer.cs
deleted file mode 100644
index 7ca5c05..0000000
--- a/CBSVisualizer/CBSVisualizer.Modules.Link/Properties/Resources.Designer.cs
+++ /dev/null
@@ -1,83 +0,0 @@
-//------------------------------------------------------------------------------
-// <auto-generated>
-//     This code was generated by a tool.
-//     Runtime Version:4.0.30319.42000
-//
-//     Changes to this file may cause incorrect behavior and will be lost if
-//     the code is regenerated.
-// </auto-generated>
-//------------------------------------------------------------------------------
-
-namespace CBSVisualizer.Modules.Link.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", "16.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("CBSVisualizer.Modules.Link.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;
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized resource of type System.Byte[].
-        /// </summary>
-        internal static byte[] GreenDot {
-            get {
-                object obj = ResourceManager.GetObject("GreenDot", resourceCulture);
-                return ((byte[])(obj));
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized resource of type System.Byte[].
-        /// </summary>
-        internal static byte[] RedDot {
-            get {
-                object obj = ResourceManager.GetObject("RedDot", resourceCulture);
-                return ((byte[])(obj));
-            }
-        }
-    }
-}
diff --git a/CBSVisualizer/CBSVisualizer.Modules.Link/Properties/Resources.resx b/CBSVisualizer/CBSVisualizer.Modules.Link/Properties/Resources.resx
deleted file mode 100644
index 49e1ad3..0000000
--- a/CBSVisualizer/CBSVisualizer.Modules.Link/Properties/Resources.resx
+++ /dev/null
@@ -1,127 +0,0 @@
-<?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=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
-  </resheader>
-  <resheader name="writer">
-    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
-  </resheader>
-  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
-  <data name="GreenDot" type="System.Resources.ResXFileRef, System.Windows.Forms">
-    <value>..\Resources\greendot.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
-  </data>
-  <data name="RedDot" type="System.Resources.ResXFileRef, System.Windows.Forms">
-    <value>..\Resources\reddot.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
-  </data>
-</root>
\ No newline at end of file
diff --git a/CBSVisualizer/CBSVisualizer.Modules.Link/Resources/greendot.png b/CBSVisualizer/CBSVisualizer.Modules.Link/Resources/greendot.png
deleted file mode 100644
index 507dccf03172b0f3c7615fcd5cc7f5a69237bb53..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 896
zcmeAS@N?(olHy`uVBq!ia0y~yVCZLHV3@|i#K6Fial>ai0|NtNage(c!@6@aFBupZ
zSkfJR9T^xl_H+M9WMyDr;4JWnEM{QfI}E~%$MaXDFfcHSdb&7<RK&f#6PS0~frsJZ
zlJJ+6w+?T6{xULzF<YXkmt~tvk>#Z`{(n~9RbR)V{Nec~9eK8w$KS3O4C<Z|wd9J@
zQZdb~9xGkFbc3=c5)j(>-}&wH`SIKR?|*y${r+wB3YE3uxpADYuE%Nzyjbl}RJ)aH
z&Njs}w=zYQZLiN<JMmh{@?6`qQ5jo{Ze2T@vneckd2a2QWtoa|wv`&p{v6BJm$mk=
zss9C~px$Nim0vwiEWKs+I%LgdtM<!#H4|LbAD&!sZP}U?POoc17XK<;nmu=FR>+=R
zF>8y1d$q35SW(KlD)6S)<}K@-O;<(ccU`->!i{xx-}PN;S2e2N9*hcKCbjgP!=vc7
zR`Hcj6M8>=Q}pp(mFv0tp{IwI+v$T<dddEC)*d-@kZFs|noV=o-bu=Tx;Tn2EcIMi
zRipVAMP2sQ7U|tr>U7y(e_izL)J>(OVk_rH$u++h+mw6`9Au%_KOQdVpT@s7(lQzr
zj(gWW)jl?n@7=u3cmnjw?WntT5;LwIyj#2t7V@_iKkYuYX3pAOefOV&;^B&)u6!)q
zuD91e8Px1uvA1ZOhwP=IJzd4yE^+T!epRV7<n-YWzmvWnzo{g;;Aur|=#O(p&P+=<
zpZca#U2&y>?(yvCOL;EmrX?)iQ~N<hMRd*6ily%y{^Z0;>QukgRDWoCkSlEN*E_qU
zBF<I`-#1#v9JcL}%i680eIv@|pWbxGZdvK0`E6SJWQ)_YORjOQjt_6WcI)SXWouS=
zWWV)E*nBPM<DDvwzY?>n&tE-z&Gy{{-~FFBqq1E#@LjigsB)*xLiG2Y=*e5%a?kFX
z%c#4>ZS9$=c~^V4xLrPLWgmPyvv=8y(lRO2tGmJvT$6tpSH3p4u}EQIuFBf>dxx4o
t*|1#Ol~BCz^oCmE5+_{M<>SZe3m!2tt#Z7<&cMLH;OXk;vd$@?2>?0uups~d

diff --git a/CBSVisualizer/CBSVisualizer.Modules.Link/Resources/reddot.png b/CBSVisualizer/CBSVisualizer.Modules.Link/Resources/reddot.png
deleted file mode 100644
index 885ff703a6a15f21a203b56b3969027e813427a5..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1074
zcmeAS@N?(olHy`uVBq!ia0y~yVCZLHV3@|i#K6Fial>ai0|NtNage(c!@6@aFBupZ
zSkfJR9T^xl_H+M9WMyDr;4JWnEM{QfI}E~%$MaXDFfcG5_jGX#sfc?!(J@cPk%#&7
z1ewqO=Rf83V|Hd?6V|_$<*9paLx6kr@}s{#CYBWFs>XP8UJp97bqeXsw^94+|5dsF
z*=pytb;ZHHAFig$t}mLZePp`GjOcE&wPNve&+dpaN!nj=+=K1vqO0e+%z2YtbfdER
zD(*}0U0+n1*0r7QL4<Bp%D#&4f#<F)QVcor`h4L6G2aEMc@{3^x>j)^GMD}0b*&;|
zW3GA!>so!4d$i5XD(m9Jav|}uz_{*nyXWuN+<Ggj<VNh#tzSj1Et>pJH&1WbDlys5
zEQOV-s#{<5Jn#5@`owxyb{pR{0nSCbRlkgnim~np+jnD8!<ncrFVwqTH+imhJ-_va
zs_6AqLc5nt3htK6(%<MOw=Pth%}Z&a*xvJXV$!M)qn;)$<0;F&c>2x$q?J4|tDSqc
zo(<Ejn*7)6&DP%R(vH2`I<GHczj-}rt8L6`&o$fHvrRj%e&e{dX!(uuBW2P%!sg$|
zW4``M_;&7tsI^J^G$uxUVfwu<!k{aAYZvR{9bv0cn5VX9Uwr<y{AizI%<AYj5{I_#
zBA>Z0HrsLj_V?YGwm|H5$<lox_|4ZaUIgmA+N9mQF{}M^wmWXP)-*3EzWeI8g0*TJ
zZ^^B@suFfvIWF6ge^Y$t-fe|z`8HlRi{2{sMdx?C;We{$p?cF!9oTy6XprQaYf%>-
zze(R1D6}qA+ssR8;kBlD8K6+L+$#1ZpgT6GaIMxxZ>`L&VqflnqTuA3tqa`kgL48K
zvY&SAa(S%Vx?s6ID8}m6vdVstDXf=N-6~dcO!&ytsUcURE*O3nGZznz$aYk}8yXYs
zpSzY-w#>UQ%l7G3v69<!kF>^?T#33c@w>ow(@P=Qj>}hdudaHzdh3Gb(xbL-w_Mw`
z;PlobyzLeN*^a_1I<C)u?6a1Y*D!w1Z;j(wu@{t#k4Cc>?6}6d*4TYdK96!%?1iB8
zqqEx#S6pLVdrkkI;iST?dKm}hKE6H3v-YdF)E1{2&&HQq?VPpWcf^M{uM~4+jO+d{
n=)U6`b0N8zOV-ZrAH#yZV$*}>{5NJ`U|{fc^>bP0l+XkKzBuiw

diff --git a/CBSVisualizer/CBSVisualizer.Modules.Link/ViewModels/LinkViewModel.cs b/CBSVisualizer/CBSVisualizer.Modules.Link/ViewModels/LinkViewModel.cs
index d2902db..995c0f5 100644
--- a/CBSVisualizer/CBSVisualizer.Modules.Link/ViewModels/LinkViewModel.cs
+++ b/CBSVisualizer/CBSVisualizer.Modules.Link/ViewModels/LinkViewModel.cs
@@ -2,11 +2,12 @@
 using CBSVisualizer.Core.Mvvm;
 using CBSVisualizer.Messaging;
 using CBSVisualizer.Messaging.Events;
-using CBSVisualizer.Services.SchedulingService;
-using CBSVisualizer.Services.SettingsService.Service;
+using CBSVisualizer.Services.SchedulingService.Interface;
+using CBSVisualizer.Services.SettingsService.Implementation;
 using log4net;
 using Prism.Events;
 using Prism.Regions;
+using System.Collections;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Linq;
@@ -31,8 +32,6 @@ namespace CBSVisualizer.Modules.Link.ViewModels
 
         private CancellationTokenSource tokenSource;
 
-        private Task packetTransmissionTask;
-
         /// <summary>
         /// The queue that is currently sending.
         /// </summary>
@@ -64,7 +63,7 @@ namespace CBSVisualizer.Modules.Link.ViewModels
                 linkCallbacks[callback.GetPriority()] = callback;
             });
 
-            eventAggregator.GetEvent<SimulationStartedEvent>().Subscribe(() =>
+            eventAggregator.GetEvent<SimulationStartedEvent>().Subscribe(async () =>
             {
                 if (linkCallbacks.Count != 8)
                 {
@@ -72,26 +71,31 @@ namespace CBSVisualizer.Modules.Link.ViewModels
                     return;
                 }
 
-                scheduler.StartScheduling();
+                // Call Initialize() on each ILinkCallback.
+                log.Info("Initializing all links");
+                foreach (var callback in linkCallbacks.Values)
+                {
+                   callback.Initialize();
+                }
+
+                // Start scheduling.
+                try
+                {
+                    await scheduler.StartScheduling();
+                } catch (TaskCanceledException) {
+                    log.Info("Scheduling was cancelled by button press.");
+                }
 
                 log.Info("Simulation started.");
             });
 
-            eventAggregator.GetEvent<SimulationStoppedEvent>().Subscribe(async () =>
+            eventAggregator.GetEvent<SimulationStoppedEvent>().Subscribe(() =>
             {
                 // Stop the scheduler
-                await scheduler.StopScheduling();
+                scheduler.StopScheduling();
 
                 // Stop packet sending.
                 tokenSource?.Cancel();
-                if (packetTransmissionTask != null)
-                {
-                    try
-                    {
-                        await packetTransmissionTask;
-                    } catch (TaskCanceledException) { }
-
-                }
 
                 // Reset all gate status lamps.
                 SetStatusLamps(new HashSet<int>());
@@ -118,15 +122,6 @@ namespace CBSVisualizer.Modules.Link.ViewModels
         {
             // Cancel old sending task.
             tokenSource?.Cancel();
-            if (packetTransmissionTask != null)
-            {
-                try
-                {
-                    await packetTransmissionTask;
-                }
-                catch (TaskCanceledException) { }
-
-            }
 
             packetInTransit = PriorityPacket.NoPacket;
 
@@ -138,7 +133,7 @@ namespace CBSVisualizer.Modules.Link.ViewModels
 
             // Handle transmission.
             tokenSource = new CancellationTokenSource();
-            packetTransmissionTask = TransmitPackets(infoTuple);
+            await TransmitPackets(infoTuple);
         }
 
         /// <summary>
@@ -148,19 +143,25 @@ namespace CBSVisualizer.Modules.Link.ViewModels
         {
             await Task.Run(async () =>
             {
+                var bitrate = settingService.GetSettingValue<int>("bitrate");
+                var remainingBytes = infoTuple.OpenedTime * (bitrate / 1000);
+
+                log.Info($"The link can send {remainingBytes} until the next GateCloseEvent.");
+
                 while (!tokenSource.IsCancellationRequested)
                 {
                     // Scan the callbacks for the highest-prio queue that wants to send a packet.
                     foreach (var queue in infoTuple.OpenedGates.OrderByDescending(gate => gate))
                     {
-                        await linkCallbacks[queue].GateOpened(packet =>
+                        linkCallbacks[queue].GateOpened(packet =>
                         {
                             if (packetInTransit == PriorityPacket.NoPacket)
                             {
-                                if (CanSendInTime(infoTuple.OpenedTime, packet))
+                                if (CanSendInTime(ref remainingBytes, packet))
                                 {
                                     activeQueue = queue;
                                     packetInTransit = packet;
+                                    log.Info($"Packet {packetInTransit} of queue {activeQueue} has been scheduled for transit.");
                                     return PacketSubmitResult.Accepted;
                                 }
                                 else
@@ -181,40 +182,46 @@ namespace CBSVisualizer.Modules.Link.ViewModels
                         continue;
                     }
 
-                    log.Info($"Packet {packetInTransit} of queue {activeQueue} has been scheduled for transit.");
-
                     // Once a packet was selected for transmission, we send it.
                     transmittedBytes = 0;
-                    var bitrate = settingService.GetSettingValue<int>("bitrate");
 
-                    await linkCallbacks[activeQueue].TransmissionStarted(bitrate);
-                    while (!tokenSource.IsCancellationRequested && transmittedBytes < packetInTransit.Size)
-                    {
-                        await Task.Delay(REFRESH_TIME_MS, tokenSource.Token);
-                        transmittedBytes += REFRESH_TIME_MS * (bitrate / 1000);
-                        log.Info($"Transmitted {transmittedBytes} of {packetInTransit.Size} bytes of packet {packetInTransit}.");
-                    }
+                    linkCallbacks[activeQueue].TransmissionStarted(bitrate);
 
-                    if (transmittedBytes >= packetInTransit.Size)
+                    try
                     {
-                        await linkCallbacks[activeQueue].TransmissionCompleted();
+                        while (!tokenSource.IsCancellationRequested && transmittedBytes < packetInTransit.Size)
+                        {
+                            await Task.Delay(REFRESH_TIME_MS, tokenSource.Token);
+                            transmittedBytes += REFRESH_TIME_MS * (bitrate / 1000);
+                            log.Info($"Transmitted {transmittedBytes} of {packetInTransit.Size} bytes of packet {packetInTransit}.");
+                        }
+                    } catch (TaskCanceledException) { }
+                    finally
+                    {
+                        linkCallbacks[activeQueue].TransmissionCompleted();
                         log.Info($"{packetInTransit} of queue {activeQueue} has been sent successfully.");
-                    }
 
-                    // Reset the "Packet in transit" pointer.
-                    packetInTransit = PriorityPacket.NoPacket;
+                        // Reset the "Packet in transit" pointer.
+                        packetInTransit = PriorityPacket.NoPacket;
+                    }
                 }
             }, tokenSource.Token);
         }
 
-        private bool CanSendInTime(int openedTime, PriorityPacket packet)
+        private bool CanSendInTime(ref int remainingBytes, PriorityPacket packet)
         {
-            // Bitrate * time = bits we can send in that time.
-            // if the packet is larger than that, we have to deny it due to pre-closing.
-            return packet.Size <= openedTime * (settingService.GetSettingValue<int>("bitrate") / 1000);
+            if (packet.Size > remainingBytes)
+            {
+                return false;
+            }
+
+            log.Info($"Packet Size: {packet.Size}, remaining bytes until next GateCloseEvent: {remainingBytes}. {remainingBytes - packet.Size} bytes left.");
+            remainingBytes -= packet.Size;
+            return true;
+
         }
 
-        private void CloseInactiveGates(ISet<int> openedGates)
+        private void CloseInactiveGates(IEnumerable<int> openedGates)
         {
             ISet<int> gatesToClose = new HashSet<int>(linkCallbacks.Keys);
             gatesToClose.ExceptWith(openedGates);
@@ -230,18 +237,11 @@ namespace CBSVisualizer.Modules.Link.ViewModels
         /// Sets the status lamps according to the set.
         /// </summary>
         /// <param name="openedGates">the set containing the opened gates</param>
-        private void SetStatusLamps(ISet<int> openedGates)
+        private void SetStatusLamps(ICollection<int> openedGates)
         {
             foreach (var key in GateStatusDictionary.Keys)
             {
-                if (openedGates.Contains(key))
-                {
-                    GateStatusDictionary[key].Value = true;
-                }
-                else
-                {
-                    GateStatusDictionary[key].Value = false;
-                }
+                GateStatusDictionary[key].Value = openedGates.Contains(key);
             }
         }
 
diff --git a/CBSVisualizer/CBSVisualizer.Modules.Link/Views/Link.xaml b/CBSVisualizer/CBSVisualizer.Modules.Link/Views/Link.xaml
index 055371c..1c59871 100644
--- a/CBSVisualizer/CBSVisualizer.Modules.Link/Views/Link.xaml
+++ b/CBSVisualizer/CBSVisualizer.Modules.Link/Views/Link.xaml
@@ -2,36 +2,98 @@
              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:local="clr-namespace:CBSVisualizer.Modules.Link.Views"
-             xmlns:externals="clr-namespace:CBSVisualizer.Modules.Link.Externals"
-             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
-             mc:Ignorable="d" 
+             mc:Ignorable="d"
              d:DesignHeight="300" d:DesignWidth="300"
              xmlns:prism="http://prismlibrary.com/"
-             prism:ViewModelLocator.AutoWireViewModel="True" >
+             prism:ViewModelLocator.AutoWireViewModel="True">
     <Grid>
-        <Grid.Resources>
-            <externals:BoolToImageConverter x:Key="BoolToImageConv"/>
-        </Grid.Resources>
         <Grid.RowDefinitions>
-            <RowDefinition Height="Auto"/>
-            <RowDefinition Height="*"/>
-            <RowDefinition Height="*"/>
-            <RowDefinition Height="*"/>
-            <RowDefinition Height="*"/>
-            <RowDefinition Height="*"/>
-            <RowDefinition Height="*"/>
-            <RowDefinition Height="*"/>
-            <RowDefinition Height="*"/>
+            <RowDefinition Height="Auto" />
+            <RowDefinition Height="*" />
+            <RowDefinition Height="*" />
+            <RowDefinition Height="*" />
+            <RowDefinition Height="*" />
+            <RowDefinition Height="*" />
+            <RowDefinition Height="*" />
+            <RowDefinition Height="*" />
+            <RowDefinition Height="*" />
         </Grid.RowDefinitions>
-        <TextBlock Text="Gate Status" Grid.Row="0" TextAlignment="Center"/>
-        <Image Grid.Row="1" HorizontalAlignment="Center" Source="{Binding GateStatusDictionary[7].Value, Converter={StaticResource BoolToImageConv}}"/>
-        <Image Grid.Row="2" HorizontalAlignment="Center" Source="{Binding GateStatusDictionary[6].Value, Converter={StaticResource BoolToImageConv}}"/>
-        <Image Grid.Row="3" HorizontalAlignment="Center" Source="{Binding GateStatusDictionary[5].Value, Converter={StaticResource BoolToImageConv}}"/>
-        <Image Grid.Row="4" HorizontalAlignment="Center" Source="{Binding GateStatusDictionary[4].Value, Converter={StaticResource BoolToImageConv}}"/>
-        <Image Grid.Row="5" HorizontalAlignment="Center" Source="{Binding GateStatusDictionary[3].Value, Converter={StaticResource BoolToImageConv}}"/>
-        <Image Grid.Row="6" HorizontalAlignment="Center" Source="{Binding GateStatusDictionary[2].Value, Converter={StaticResource BoolToImageConv}}"/>
-        <Image Grid.Row="7" HorizontalAlignment="Center" Source="{Binding GateStatusDictionary[1].Value, Converter={StaticResource BoolToImageConv}}"/>
-        <Image Grid.Row="8" HorizontalAlignment="Center" Source="{Binding GateStatusDictionary[0].Value, Converter={StaticResource BoolToImageConv}}"/>
+        <TextBlock Text="Gate Status" Grid.Row="0" TextAlignment="Center" />
+
+        <ToggleButton Style="{StaticResource MaterialDesignActionToggleButton}" ToolTip="Gate Status" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center"
+                      IsChecked="{Binding GateStatusDictionary[7].Value, Mode=OneWay}">
+            <ToggleButton.Content>
+                <materialDesign:PackIcon Kind="Gate" Foreground="Red"/>
+            </ToggleButton.Content>
+            <materialDesign:ToggleButtonAssist.OnContent>
+                <materialDesign:PackIcon Kind="GateOpen" Foreground="Green"/>
+            </materialDesign:ToggleButtonAssist.OnContent>
+        </ToggleButton>
+        <ToggleButton Style="{StaticResource MaterialDesignActionToggleButton}" ToolTip="MaterialDesignActionLightToggleButton" Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Center"
+                      IsChecked="{Binding GateStatusDictionary[6].Value, Mode=OneWay}">
+            <ToggleButton.Content>
+                <materialDesign:PackIcon Kind="Gate" Foreground="Red"/>
+            </ToggleButton.Content>
+            <materialDesign:ToggleButtonAssist.OnContent>
+                <materialDesign:PackIcon Kind="GateOpen" Foreground="Green"/>
+            </materialDesign:ToggleButtonAssist.OnContent>
+        </ToggleButton>
+        <ToggleButton Style="{StaticResource MaterialDesignActionToggleButton}" ToolTip="MaterialDesignActionLightToggleButton" Grid.Row="3" HorizontalAlignment="Center" VerticalAlignment="Center"
+                      IsChecked="{Binding GateStatusDictionary[5].Value, Mode=OneWay}">
+            <ToggleButton.Content>
+                <materialDesign:PackIcon Kind="Gate" Foreground="Red"/>
+            </ToggleButton.Content>
+            <materialDesign:ToggleButtonAssist.OnContent>
+                <materialDesign:PackIcon Kind="GateOpen" Foreground="Green"/>
+            </materialDesign:ToggleButtonAssist.OnContent>
+        </ToggleButton>
+        <ToggleButton Style="{StaticResource MaterialDesignActionToggleButton}" ToolTip="MaterialDesignActionLightToggleButton" Grid.Row="4" HorizontalAlignment="Center" VerticalAlignment="Center"
+                      IsChecked="{Binding GateStatusDictionary[4].Value, Mode=OneWay}">
+            <ToggleButton.Content>
+                <materialDesign:PackIcon Kind="Gate" Foreground="Red"/>
+            </ToggleButton.Content>
+            <materialDesign:ToggleButtonAssist.OnContent>
+                <materialDesign:PackIcon Kind="GateOpen" Foreground="Green"/>
+            </materialDesign:ToggleButtonAssist.OnContent>
+        </ToggleButton>
+        <ToggleButton Style="{StaticResource MaterialDesignActionToggleButton}" ToolTip="MaterialDesignActionLightToggleButton" Grid.Row="5" HorizontalAlignment="Center" VerticalAlignment="Center"
+                      IsChecked="{Binding GateStatusDictionary[3].Value, Mode=OneWay}">
+            <ToggleButton.Content>
+                <materialDesign:PackIcon Kind="Gate" Foreground="Red"/>
+            </ToggleButton.Content>
+            <materialDesign:ToggleButtonAssist.OnContent>
+                <materialDesign:PackIcon Kind="GateOpen" Foreground="Green"/>
+            </materialDesign:ToggleButtonAssist.OnContent>
+        </ToggleButton>
+        <ToggleButton Style="{StaticResource MaterialDesignActionToggleButton}" ToolTip="MaterialDesignActionLightToggleButton" Grid.Row="6" HorizontalAlignment="Center" VerticalAlignment="Center"
+                      IsChecked="{Binding GateStatusDictionary[2].Value, Mode=OneWay}">
+            <ToggleButton.Content>
+                <materialDesign:PackIcon Kind="Gate" Foreground="Red"/>
+            </ToggleButton.Content>
+            <materialDesign:ToggleButtonAssist.OnContent>
+                <materialDesign:PackIcon Kind="GateOpen" Foreground="Green"/>
+            </materialDesign:ToggleButtonAssist.OnContent>
+        </ToggleButton>
+        <ToggleButton Style="{StaticResource MaterialDesignActionToggleButton}" ToolTip="MaterialDesignActionLightToggleButton" Grid.Row="7" HorizontalAlignment="Center" VerticalAlignment="Center"
+                      IsChecked="{Binding GateStatusDictionary[1].Value, Mode=OneWay}">
+            <ToggleButton.Content>
+                <materialDesign:PackIcon Kind="Gate" Foreground="Red"/>
+            </ToggleButton.Content>
+            <materialDesign:ToggleButtonAssist.OnContent>
+                <materialDesign:PackIcon Kind="GateOpen" Foreground="Green"/>
+            </materialDesign:ToggleButtonAssist.OnContent>
+        </ToggleButton>
+        <ToggleButton Style="{StaticResource MaterialDesignActionToggleButton}" ToolTip="MaterialDesignActionLightToggleButton" Grid.Row="8" HorizontalAlignment="Center" VerticalAlignment="Center"
+                      IsChecked="{Binding GateStatusDictionary[0].Value, Mode=OneWay}">
+            <ToggleButton.Content>
+                <materialDesign:PackIcon Kind="Gate" Foreground="Red"/>
+            </ToggleButton.Content>
+            <materialDesign:ToggleButtonAssist.OnContent>
+                <materialDesign:PackIcon Kind="GateOpen" Foreground="Green"/>
+            </materialDesign:ToggleButtonAssist.OnContent>
+        </ToggleButton>
     </Grid>
-</UserControl>
+</UserControl>
\ No newline at end of file
diff --git a/CBSVisualizer/CBSVisualizer.Modules.MenuBar/CBSVisualizer.Modules.MenuBar.csproj b/CBSVisualizer/CBSVisualizer.Modules.MenuBar/CBSVisualizer.Modules.MenuBar.csproj
index 39e0363..390006b 100644
--- a/CBSVisualizer/CBSVisualizer.Modules.MenuBar/CBSVisualizer.Modules.MenuBar.csproj
+++ b/CBSVisualizer/CBSVisualizer.Modules.MenuBar/CBSVisualizer.Modules.MenuBar.csproj
@@ -5,12 +5,14 @@
     <AssemblyName>CBSVisualizer.Modules.MenuBar</AssemblyName>
   </PropertyGroup>
   <ItemGroup>
+    <PackageReference Include="log4net" Version="2.0.9" />
+    <PackageReference Include="MaterialDesignThemes" Version="3.1.3" />
     <PackageReference Include="Prism.Wpf" Version="7.2.0.1422" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\CBSVisualizer.Core\CBSVisualizer.Core.csproj" />
     <ProjectReference Include="..\CBSVisualizer.MessagingCore\CBSVisualizer.Messaging.csproj" />
+    <ProjectReference Include="..\CBSVisualizer.Services.PacketService\CBSVisualizer.Services.PacketService.csproj" />
     <ProjectReference Include="..\CBSVisualizer.Services.SettingsService\CBSVisualizer.Services.SettingService.csproj" />
-    <ProjectReference Include="..\CBSVisualizer\CBSVisualizer.Core\CBSVisualizer.Core.csproj" />
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/CBSVisualizer/CBSVisualizer.Modules.MenuBar/ViewModels/MenuBarViewModel.LoadGeneration.cs b/CBSVisualizer/CBSVisualizer.Modules.MenuBar/ViewModels/MenuBarViewModel.LoadGeneration.cs
index 8e09473..c94c3c8 100644
--- a/CBSVisualizer/CBSVisualizer.Modules.MenuBar/ViewModels/MenuBarViewModel.LoadGeneration.cs
+++ b/CBSVisualizer/CBSVisualizer.Modules.MenuBar/ViewModels/MenuBarViewModel.LoadGeneration.cs
@@ -2,10 +2,6 @@
 using CBSVisualizer.Messaging.Events;
 using log4net;
 using Prism.Commands;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
 
@@ -33,22 +29,18 @@ namespace CBSVisualizer.Modules.MenuBar.ViewModels
             }
         }
 
-        private const int HEADER_BYTES = 100;
-
-        private const int TRAILER_BYTES = 100;
-
         private CancellationTokenSource tokenSource = new CancellationTokenSource();
 
-        private readonly Random random = new Random();
-
         private bool CanStartLoadGeneration()
         {
             return !LoadGenerationInProgress;
         }
 
-        private bool CanStopLoadGeneration()
+        private async Task StartLoadThread()
         {
-            return LoadGenerationInProgress;
+            tokenSource = new CancellationTokenSource();
+            LoadGenerationInProgress = true;
+            await GenerateLoad();
         }
 
         private void StopLoadThread()
@@ -59,38 +51,21 @@ namespace CBSVisualizer.Modules.MenuBar.ViewModels
 
         private async Task GenerateLoad()
         {
-            await Task.Run(async () =>
-            {
-                int packetCount = 0;
+            int packetCount = 0;
 
-                while (!tokenSource.IsCancellationRequested)
-                {
-                    eventAggregator.GetEvent<PacketArrivedEvent>().Publish(GenerateRandomPacket());
-                    await Task.Delay(settings.GetSettingValue<int>("interarrival_time"));
-                    log.Info($"I've generated {++packetCount} packets");
-                }
-
-            }, tokenSource.Token);
+            while (!tokenSource.IsCancellationRequested)
+            {
+                eventAggregator.GetEvent<PacketArrivedEvent>().Publish(GenerateRandomPacket());
+                await Task.Delay(settings.GetSettingValue<int>("interarrival_time"));
+                log.Info($"I've generated {++packetCount} packets");
+            }
         }
 
         private PriorityPacket GenerateRandomPacket()
         {
-            PriorityPacket ret = new PriorityPacket(
-                random.Next(0, 8), // Priority between 0 and 7
-                HEADER_BYTES,
-                random.Next(2000), // Random value between 0 and 1999.
-                TRAILER_BYTES);
+            PriorityPacket ret = packetService.GeneratePacket();
             log.Info(ret);
             return ret;
         }
-
-
-        private async Task StartLoadThread()
-        {
-            tokenSource = new CancellationTokenSource();
-            LoadGenerationInProgress = true;
-
-            await GenerateLoad();
-        }
     }
 }
diff --git a/CBSVisualizer/CBSVisualizer.Modules.MenuBar/ViewModels/MenuBarViewModel.cs b/CBSVisualizer/CBSVisualizer.Modules.MenuBar/ViewModels/MenuBarViewModel.cs
index eb68171..ee49c0f 100644
--- a/CBSVisualizer/CBSVisualizer.Modules.MenuBar/ViewModels/MenuBarViewModel.cs
+++ b/CBSVisualizer/CBSVisualizer.Modules.MenuBar/ViewModels/MenuBarViewModel.cs
@@ -1,16 +1,12 @@
 using CBSVisualizer.Core.Mvvm;
 using CBSVisualizer.Messaging.Events;
-using CBSVisualizer.Services.SettingsService.Service;
+using CBSVisualizer.Services.PacketService.Interface;
+using CBSVisualizer.Services.SettingsService.Implementation;
 using Prism.Commands;
 using Prism.Events;
-using Prism.Mvvm;
 using Prism.Regions;
 using Prism.Services.Dialogs;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+
 
 namespace CBSVisualizer.Modules.MenuBar.ViewModels
 {
@@ -40,19 +36,22 @@ namespace CBSVisualizer.Modules.MenuBar.ViewModels
 
         private readonly SettingService settings;
 
+        private readonly IPacketService packetService;
+
 
-        public MenuBarViewModel(IRegionManager regionManager, IEventAggregator eventAggregator, IDialogService dialogService, SettingService settingService)
+        public MenuBarViewModel(IRegionManager regionManager, IEventAggregator eventAggregator, IDialogService dialogService, SettingService settingService, IPacketService packetServ)
             : base(regionManager)
         {
             this.eventAggregator = eventAggregator;
             settings = settingService;
+            packetService = packetServ;
 
             StartSimulationCommand = new DelegateCommand(SignalSimulationStart, () => !SimulationRunning).ObservesProperty(() => SimulationRunning);
             StopSimulationCommand = new DelegateCommand(SignalSimulationStop).ObservesCanExecute(() => SimulationRunning);
             OpenSettingsCommand = new DelegateCommand(() => dialogService.Show("SettingsDialog", new DialogParameters(), result => { }));
 
             StartLoadGeneration = new DelegateCommand(async () => await StartLoadThread(), CanStartLoadGeneration).ObservesProperty(() => LoadGenerationInProgress);
-            StopLoadGeneration = new DelegateCommand(StopLoadThread, CanStopLoadGeneration).ObservesProperty(() => LoadGenerationInProgress);
+            StopLoadGeneration = new DelegateCommand(StopLoadThread, () => !CanStartLoadGeneration()).ObservesProperty(() => LoadGenerationInProgress);
         }
         private void SignalSimulationStart()
         {
diff --git a/CBSVisualizer/CBSVisualizer.Modules.Queue.QueueGroup/CBSVisualizer.Modules.QueueGroup.csproj b/CBSVisualizer/CBSVisualizer.Modules.Queue.QueueGroup/CBSVisualizer.Modules.QueueGroup.csproj
index 9a03652..4028604 100644
--- a/CBSVisualizer/CBSVisualizer.Modules.Queue.QueueGroup/CBSVisualizer.Modules.QueueGroup.csproj
+++ b/CBSVisualizer/CBSVisualizer.Modules.Queue.QueueGroup/CBSVisualizer.Modules.QueueGroup.csproj
@@ -5,11 +5,12 @@
     <AssemblyName>CBSVisualizer.Modules.Queue.QueueGroup</AssemblyName>
   </PropertyGroup>
   <ItemGroup>
+    <PackageReference Include="log4net" Version="2.0.9" />
+    <PackageReference Include="MaterialDesignThemes" Version="3.1.3" />
     <PackageReference Include="Prism.Wpf" Version="7.2.0.1422" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\CBSVisualizer.Core\CBSVisualizer.Core.csproj" />
     <ProjectReference Include="..\CBSVisualizer.Modules.Queue\CBSVisualizer.Modules.Queue.csproj" />
-    <ProjectReference Include="..\CBSVisualizer\CBSVisualizer.Core\CBSVisualizer.Core.csproj" />
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/CBSVisualizer/CBSVisualizer.Modules.Queue.QueueGroup/Views/QueueGroup.xaml b/CBSVisualizer/CBSVisualizer.Modules.Queue.QueueGroup/Views/QueueGroup.xaml
index 4f47ea4..091e5a5 100644
--- a/CBSVisualizer/CBSVisualizer.Modules.Queue.QueueGroup/Views/QueueGroup.xaml
+++ b/CBSVisualizer/CBSVisualizer.Modules.Queue.QueueGroup/Views/QueueGroup.xaml
@@ -10,7 +10,6 @@
              prism:ViewModelLocator.AutoWireViewModel="True" >
     <Grid x:Name="Grid">
         <Grid.RowDefinitions>
-            <RowDefinition Height="Auto"/>
             <RowDefinition Height="*"/>
             <RowDefinition Height="*"/>
             <RowDefinition Height="*"/>
@@ -20,15 +19,5 @@
             <RowDefinition Height="*"/>
             <RowDefinition Height="*"/>
         </Grid.RowDefinitions>
-        <Grid.ColumnDefinitions>
-            <ColumnDefinition Width="*"/>
-            <ColumnDefinition Width="*"/>
-            <ColumnDefinition Width="*"/>
-            <ColumnDefinition Width="*"/>
-        </Grid.ColumnDefinitions>
-        <TextBlock Text="Priority" Grid.Row="0" Grid.Column="0" TextAlignment="Center"/>
-        <TextBlock Text="Packet Count" Grid.Row="0" Grid.Column="1" TextAlignment="Center"/>
-        <TextBlock Text="Idle Slope [b/s]" Grid.Row="0" Grid.Column="2" TextAlignment="Center"/>
-        <TextBlock Text="Credit Behaviour" Grid.Row="0" Grid.Column="3" TextAlignment="Center"/>
     </Grid>
 </UserControl>
diff --git a/CBSVisualizer/CBSVisualizer.Modules.Queue.QueueGroup/Views/QueueGroup.xaml.cs b/CBSVisualizer/CBSVisualizer.Modules.Queue.QueueGroup/Views/QueueGroup.xaml.cs
index 3100399..f917451 100644
--- a/CBSVisualizer/CBSVisualizer.Modules.Queue.QueueGroup/Views/QueueGroup.xaml.cs
+++ b/CBSVisualizer/CBSVisualizer.Modules.Queue.QueueGroup/Views/QueueGroup.xaml.cs
@@ -1,5 +1,7 @@
 using CBSVisualizer.Modules.Queue.ViewModels;
+using CBSVisualizer.Services.PacketService.Interface;
 using Prism.Events;
+using Prism.Ioc;
 using Prism.Regions;
 using System;
 using System.Collections.Generic;
@@ -23,15 +25,14 @@ namespace CBSVisualizer.Modules.Queue.QueueGroup.Views
     /// </summary>
     public partial class QueueGroup : UserControl
     {
-        public QueueGroup(IRegionManager regionManager, IEventAggregator eventAggregator)
+        public QueueGroup(IRegionManager regionManager, IEventAggregator eventAggregator, IPacketService packetService)
         {
             InitializeComponent();
 
-            for (int prio = 1; prio < 9; prio++)
+            for (int prio = 7; prio >= 0; prio--)
             {
-                Queue.Views.Queue newQueue = new Queue.Views.Queue(new QueueViewModel(regionManager, eventAggregator, prio - 1));
-                Grid.SetRow(newQueue, 9 - prio);
-                Grid.SetColumnSpan(newQueue, 4);
+                Queue.Views.Queue newQueue = new Queue.Views.Queue(new QueueViewModel(regionManager, eventAggregator, prio, packetService));
+                Grid.SetRow(newQueue, 7 - prio);
                 Grid.Children.Add(newQueue);
             }
         }
diff --git a/CBSVisualizer/CBSVisualizer.Modules.Queue/CBSVisualizer.Modules.Queue.csproj b/CBSVisualizer/CBSVisualizer.Modules.Queue/CBSVisualizer.Modules.Queue.csproj
index 5fbb50f..7a155ee 100644
--- a/CBSVisualizer/CBSVisualizer.Modules.Queue/CBSVisualizer.Modules.Queue.csproj
+++ b/CBSVisualizer/CBSVisualizer.Modules.Queue/CBSVisualizer.Modules.Queue.csproj
@@ -5,11 +5,15 @@
     <AssemblyName>CBSVisualizer.Modules.Queue</AssemblyName>
   </PropertyGroup>
   <ItemGroup>
+    <PackageReference Include="LiveCharts" Version="0.9.7" />
+    <PackageReference Include="LiveCharts.Wpf" Version="0.9.7" />
+    <PackageReference Include="log4net" Version="2.0.9" />
+    <PackageReference Include="MaterialDesignThemes" Version="3.1.3" />
     <PackageReference Include="Prism.Wpf" Version="7.2.0.1422" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\CBSVisualizer.Core\CBSVisualizer.Core.csproj" />
     <ProjectReference Include="..\CBSVisualizer.MessagingCore\CBSVisualizer.Messaging.csproj" />
-    <ProjectReference Include="..\CBSVisualizer\CBSVisualizer.Core\CBSVisualizer.Core.csproj" />
+    <ProjectReference Include="..\CBSVisualizer.Services.PacketService\CBSVisualizer.Services.PacketService.csproj" />
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.LinkCallbacks.cs b/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.LinkCallbacks.cs
index 5658c4b..5053171 100644
--- a/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.LinkCallbacks.cs
+++ b/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.LinkCallbacks.cs
@@ -3,320 +3,348 @@ using CBSVisualizer.Messaging.Events;
 using System;
 using System.Diagnostics;
 using System.Linq;
-using System.Threading.Tasks;
 
 namespace CBSVisualizer.Modules.Queue.ViewModels
 {
     public partial class QueueViewModel
     {
+        public enum CreditBehaviour
+        {
+            // This is selected when there should be no credit-based shaper for this queue.
+            NoCbs,
+
+            // Frozen credit behaviour
+            Frozen,
+
+            // The standard credit behaviour
+            Standard,
+
+            // Return to zero.
+            ReturnToZero
+        }
 
         private abstract class LinkCallbackBase : ILinkCallback
         {
-            protected readonly QueueViewModel parent;
-            public LinkCallbackBase(QueueViewModel parentViewModel)
+            protected readonly QueueViewModel Parent;
+
+            protected LinkCallbackBase(QueueViewModel parentViewModel)
             {
-                parent = parentViewModel;
+                Parent = parentViewModel;
             }
 
-            protected double GetSendSlope(double rate)
+            protected long GetSendSlope(long rate)
             {
-                return parent.IdleSlope - rate;
+                return Parent.IdleSlope - rate;
             }
 
             public int GetPriority()
             {
-                return parent.Priority;
+                return Parent.Priority;
             }
 
-            public virtual Task Initialize()
+            public virtual void Initialize()
             {
                 // Do nothing by default.
-                return Task.CompletedTask;
             }
 
             protected bool CanSend()
             {
-                lock (parent.queueLock)
+                lock (Parent.queueLock)
                 {
-                    return parent.Queue.Count > 0 && parent.CurrentCredit >= 0;
+                    return Parent.Queue.Count > 0 && Parent.CurrentCredit >= 0;
                 }
             }
 
-            public abstract Task GateClosed();
 
-            public abstract Task GateOpened(Func<PriorityPacket, PacketSubmitResult> trySubmitFirstPacket);
+            protected void TrySendPacket(Func<PriorityPacket, PacketSubmitResult> trySubmitFirstPacket, Action<PriorityPacket> additionalAcceptedAction,
+                Action<PriorityPacket> deniedPreClosingAction, Action<PriorityPacket> deniedHigherPrioAction)
+            {
+                lock (Parent.queueLock)
+                {
+                    lock (Parent.creditLock)
+                    {
+                        if (Parent.Queue.Count <= 0 || Parent.CurrentCredit < 0)
+                        {
+                            return;
+                        }
+
+                        var firstPacket = Parent.Queue.First();
+
+                        switch (trySubmitFirstPacket.Invoke(firstPacket))
+                        {
+                            case PacketSubmitResult.Accepted:
+                                Parent.Queue.Remove(firstPacket);
+                                additionalAcceptedAction?.Invoke(firstPacket);
+                                break;
+
+                            case PacketSubmitResult.DeniedHigherPrio:
+                                deniedHigherPrioAction?.Invoke(firstPacket);
+                                break;
+
+                            case PacketSubmitResult.DeniedPreClosing:
+                                deniedPreClosingAction?.Invoke(firstPacket);
+                                break;
+                        }
+                    }
+                }
+            }
+
+            public abstract void GateClosed();
 
-            public abstract Task PacketPreempted(PriorityPacket preemptedPacket, int leftoverBytes);
+            public abstract void GateOpened(Func<PriorityPacket, PacketSubmitResult> trySubmitFirstPacket);
 
-            public abstract Task TransmissionCompleted();
+            public abstract void PacketPreempted(PriorityPacket preemptedPacket, int leftoverBytes);
 
-            public abstract Task TransmissionStarted(double bytesPerSecondRate);
+            public abstract void TransmissionCompleted();
+
+            public abstract void TransmissionStarted(long bytesPerSecondRate);
         }
 
-        private class NoCBSLinkCallback : LinkCallbackBase
+        #region NoCbsLinkCallback
+        private class NoCbsLinkCallback : LinkCallbackBase
         {
-            public NoCBSLinkCallback(QueueViewModel parent)
+            public NoCbsLinkCallback(QueueViewModel parent)
                 : base(parent)
             {
             }
 
-            public override Task GateClosed()
+            public override void GateClosed()
             {
                 // Nothing to be done.
-                return Task.CompletedTask;
             }
 
-            public override Task GateOpened(Func<PriorityPacket, PacketSubmitResult> trySubmitFirstPacket)
+            public override void GateOpened(Func<PriorityPacket, PacketSubmitResult> trySubmitFirstPacket)
             {
                 // Try to submit the "oldest" packet.
-                lock (parent.queueLock)
+                lock (Parent.queueLock)
                 {
                     // If the queue is empty, return.
-                    if (!CanSend())
+                    if (Parent.Queue.Count <= 0)
                     {
-                        return Task.CompletedTask;
+                        return;
                     }
 
                     // If the packet was accepted, remove it from the queue.
-                    var firstPacket = parent.Queue.First();
+                    var firstPacket = Parent.Queue.First();
 
                     if (trySubmitFirstPacket.Invoke(firstPacket) == PacketSubmitResult.Accepted)
                     {
-                        parent.Queue.Remove(firstPacket);
+                        Parent.Queue.Remove(firstPacket);
                     }
 
                     // Otherwise, just don't do anything :-)
                 }
-                return Task.CompletedTask;
             }
 
-            public override Task PacketPreempted(PriorityPacket preemptedPacket, int leftoverBytes)
+            public override void PacketPreempted(PriorityPacket preemptedPacket, int leftoverBytes)
             {
                 // Build a new packet that just contains the leftover bytes and put it into the queue.
-                lock (parent.queueLock)
+                lock (Parent.queueLock)
                 {
-                    parent.Queue.Insert(0, new PriorityPacket(parent.Priority, leftoverBytes));
-                    return Task.CompletedTask;
+                    Parent.Queue.Insert(0, new PriorityPacket(Parent.Priority, leftoverBytes));
                 }
             }
 
-            public override Task TransmissionCompleted()
+            public override void TransmissionStarted(long bytesPerSecondRate)
             {
-                return Task.CompletedTask;
+                // Just write some log.
+                Debug.WriteLine($"Packet of Queue {Parent.Priority} has started transmission with {bytesPerSecondRate} bytes/s.");
             }
-
-            public override Task TransmissionStarted(double bytesPerSecondRate)
+            
+            public override void TransmissionCompleted()
             {
-                // Just write some log.
-                Debug.WriteLine($"Packet of Queue {parent.Priority} has started transmission with {bytesPerSecondRate} bytes/s.");
-                return Task.CompletedTask;
+                // Nothing to be done.
             }
         }
+        #endregion
 
-        private class FrozenLinkCallback : LinkCallbackBase
+        #region StandardLinkCallback
+        private class StandardLinkCallback : LinkCallbackBase
         {
-
-            public FrozenLinkCallback(QueueViewModel parent)
-                : base(parent)
+            public StandardLinkCallback(QueueViewModel parentViewModel)
+                : base(parentViewModel)
             {
             }
 
-            public override async Task Initialize()
+            public override void Initialize()
             {
-                await parent.StartCreditThread(parent.IdleSlope);
+                Parent.StartCreditThread(Parent.IdleSlope);
             }
 
-            public override Task GateClosed()
+            public override void GateClosed()
             {
-                // Nothing special happens here. The credit handling is done in the GateOpened method.
-                return Task.CompletedTask;
+                // Stop the credit thread.
+                Parent.StopCreditThread();
             }
 
-            public override Task GateOpened(Func<PriorityPacket, PacketSubmitResult> trySubmitFirstPacket)
+            public override void GateOpened(Func<PriorityPacket, PacketSubmitResult> trySubmitFirstPacket)
             {
-                // Try to submit first packet.
-                lock (parent.queueLock)
-                {
-
-                    if (!CanSend())
-                    {
-                        return Task.CompletedTask;
-                    }
-
-                    var firstPacket = parent.Queue.First();
-                    var submitResult = trySubmitFirstPacket.Invoke(firstPacket);
-
-                    // If the packet was accepted, remove it from the queue.
-                    if (submitResult == PacketSubmitResult.Accepted)
-                    {
-                        parent.Queue.Remove(firstPacket);
-
-                        // If my packet was denied due to pre-closing, freeze my credit.
-                    } else if (submitResult == PacketSubmitResult.DeniedPreClosing)
-                    {
-                        _ = parent.StopCreditThread();
-                    }
-                }
+                // Start the credit thread
+                Parent.StartCreditThread(Parent.IdleSlope);
 
-                // Otherwise, just let the credit grow for now.
-                return Task.CompletedTask;
+                // Try to send the packet if we can.
+                TrySendPacket(trySubmitFirstPacket, null, null, null);
             }
 
-            public override Task PacketPreempted(PriorityPacket preemptedPacket, int leftoverBytes)
+            public override void PacketPreempted(PriorityPacket preemptedPacket, int leftoverBytes)
             {
-                // Put the leftovers of the packet back into the queue.
-                lock (parent.queueLock)
+                lock (Parent.queueLock)
                 {
-                    parent.Queue.Insert(0, new PriorityPacket(parent.Priority, leftoverBytes));
+                    Parent.Queue.Insert(0, new PriorityPacket(Parent.Priority, leftoverBytes));
                 }
-
-                return Task.CompletedTask;
             }
 
-            public override async Task TransmissionCompleted()
+            public override void TransmissionCompleted()
             {
-                // Stop and restart the credit thread.
-                await parent.StopCreditThread();
-                await parent.StartCreditThread(parent.IdleSlope);
+                Log.Info("Transmission Completed");
+                Parent.StopCreditThread();
+                Parent.StartCreditThread(Parent.IdleSlope);
             }
 
-            public override async Task TransmissionStarted(double bytesPerSecondRate)
+            public override void TransmissionStarted(long bytesPerSecondRate)
             {
-                // Decrease the credit by the idle slope.
-                await parent.StopCreditThread();
-                await parent.StartCreditThread(GetSendSlope(bytesPerSecondRate));
+                Log.Info("TransmissionStarted");
+                Parent.StopCreditThread();
+                Parent.StartCreditThread(GetSendSlope(bytesPerSecondRate));
             }
         }
+        #endregion
 
-        private class StandardLinkCallback : LinkCallbackBase
+        #region FrozenLinkCallback
+        private class FrozenLinkCallback : LinkCallbackBase
         {
-
-            public StandardLinkCallback(QueueViewModel parentViewModel)
-                : base(parentViewModel)
+            public FrozenLinkCallback(QueueViewModel parent)
+                : base(parent)
             {
             }
 
-            public override async Task Initialize()
+            public override void Initialize()
             {
-                await parent.StartCreditThread(parent.IdleSlope);
+                Parent.StartCreditThread(Parent.IdleSlope);
             }
 
-            public override async Task GateClosed()
+            public override void GateClosed()
             {
-                // Stop the credit growth thread.
-                await parent.StopCreditThread();
+                // Nothing special happens here. The credit handling is done in the GateOpened method.
             }
 
-            public override Task GateOpened(Func<PriorityPacket, PacketSubmitResult> trySubmitFirstPacket)
+            public override void GateOpened(Func<PriorityPacket, PacketSubmitResult> trySubmitFirstPacket)
             {
-                // Start the credit 
-                lock (parent.queueLock)
+                // Try to submit first packet.
+                lock (Parent.queueLock)
                 {
-                    // Don't do anything when there are no packets.
                     if (!CanSend())
                     {
-                        return Task.CompletedTask;
+                        return;
                     }
 
-                    // Otherwise, once again try to send the first packet.
-                    var firstPacket = parent.Queue.First();
-                    if (trySubmitFirstPacket.Invoke(firstPacket) == PacketSubmitResult.Accepted)
+                    var firstPacket = Parent.Queue.First();
+                    var submitResult = trySubmitFirstPacket.Invoke(firstPacket);
+
+                    // If the packet was accepted, remove it from the queue.
+                    if (submitResult == PacketSubmitResult.Accepted)
+                    {
+                        Parent.Queue.Remove(firstPacket);
+
+                        // If my packet was denied due to pre-closing, freeze my credit.
+                    }
+                    else if (submitResult == PacketSubmitResult.DeniedPreClosing)
                     {
-                        parent.Queue.Remove(firstPacket);
+                        Parent.StopCreditThread();
                     }
                 }
 
-                return Task.CompletedTask;
+                // Otherwise, just let the credit grow for now.
             }
 
-            public override Task PacketPreempted(PriorityPacket preemptedPacket, int leftoverBytes)
+            public override void PacketPreempted(PriorityPacket preemptedPacket, int leftoverBytes)
             {
-                lock (parent.queueLock)
+                // Put the leftovers of the packet back into the queue.
+                lock (Parent.queueLock)
                 {
-                    parent.Queue.Insert(0, new PriorityPacket(parent.Priority, leftoverBytes));
+                    Parent.Queue.Insert(0, new PriorityPacket(Parent.Priority, leftoverBytes));
                 }
-
-                return Task.CompletedTask;
             }
 
-            public override async Task TransmissionCompleted()
+            public override void TransmissionCompleted()
             {
-                await parent.StopCreditThread();
-                await parent.StartCreditThread(parent.IdleSlope);
+                // Stop and restart the credit thread.
+                Parent.StopCreditThread();
+                Parent.StartCreditThread(Parent.IdleSlope);
             }
 
-            public override async Task TransmissionStarted(double bytesPerSecondRate)
+            public override void TransmissionStarted(long bytesPerSecondRate)
             {
-                await parent.StopCreditThread();
-                await parent.StartCreditThread(GetSendSlope(bytesPerSecondRate));
+                // Decrease the credit by the idle slope.
+                Parent.StopCreditThread();
+                Parent.StartCreditThread(GetSendSlope(bytesPerSecondRate));
             }
         }
+        #endregion
 
+        #region ReturnToZeroLinkCallback
         private class ReturnToZeroLinkCallback : LinkCallbackBase
         {
             public ReturnToZeroLinkCallback(QueueViewModel parentViewModel)
-                :base(parentViewModel)
+                : base(parentViewModel)
             {
             }
 
-            public override async Task Initialize()
+            public override void Initialize()
             {
-                await parent.StartCreditThread(parent.IdleSlope);
+                Parent.StartCreditThread(Parent.IdleSlope);
             }
 
-            public override Task GateClosed()
+            public override void GateClosed()
             {
                 // Nothing special to be done here.
-                return Task.CompletedTask;
             }
 
-            public override Task GateOpened(Func<PriorityPacket, PacketSubmitResult> trySubmitFirstPacket)
+            public override void GateOpened(Func<PriorityPacket, PacketSubmitResult> trySubmitFirstPacket)
             {
-                lock (parent.queueLock)
+                lock (Parent.queueLock)
                 {
                     // Again, check if we can submit anything.
                     if (!CanSend())
                     {
-                        return Task.CompletedTask;
+                        return;
                     }
 
-                    var firstPacket = parent.Queue.First();
+                    var firstPacket = Parent.Queue.First();
                     var submitResult = trySubmitFirstPacket.Invoke(firstPacket);
 
                     if (submitResult == PacketSubmitResult.Accepted)
                     {
-                        parent.Queue.Remove(firstPacket);
-                    } else if (submitResult == PacketSubmitResult.DeniedPreClosing) // In the pre-closing case, we signal the thread to increase our credit to zero.
+                        Parent.Queue.Remove(firstPacket);
+                    }
+                    else if (submitResult == PacketSubmitResult.DeniedPreClosing) // In the pre-closing case, we signal the thread to increase our credit to zero.
                     {
-                        _ = parent.StopCreditThread();
-                        _ = parent.StartCreditThread(parent.IdleSlope, 0);
+                        Parent.StopCreditThread();
+                        Parent.StartCreditThread(Parent.IdleSlope, 0);
                     }
                 }
-
-                return Task.CompletedTask;
             }
 
-            public override Task PacketPreempted(PriorityPacket preemptedPacket, int leftoverBytes)
+            public override void PacketPreempted(PriorityPacket preemptedPacket, int leftoverBytes)
             {
-                lock (parent.queueLock)
+                lock (Parent.queueLock)
                 {
-                    parent.Queue.Insert(0, new PriorityPacket(GetPriority(), leftoverBytes));
+                    Parent.Queue.Insert(0, new PriorityPacket(GetPriority(), leftoverBytes));
                 }
-
-                return Task.CompletedTask;
             }
 
-            public override async Task TransmissionCompleted()
+            public override void TransmissionCompleted()
             {
-                await parent.StopCreditThread();
-                await parent.StartCreditThread(parent.IdleSlope);
+                Parent.StopCreditThread();
+                Parent.StartCreditThread(Parent.IdleSlope, 0);
             }
 
-            public override async Task TransmissionStarted(double bytesPerSecondRate)
+            public override void TransmissionStarted(long bytesPerSecondRate)
             {
-                await parent.StopCreditThread();
-                await parent.StartCreditThread(GetSendSlope(bytesPerSecondRate));
+                Parent.StopCreditThread();
+                Parent.StartCreditThread(GetSendSlope(bytesPerSecondRate), 0);
             }
         }
+        #endregion
     }
-}
+}
\ No newline at end of file
diff --git a/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.cs b/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.cs
index 1b2a34e..e3b9186 100644
--- a/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.cs
+++ b/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.cs
@@ -1,11 +1,17 @@
 using CBSVisualizer.Core.Mvvm;
 using CBSVisualizer.Messaging;
 using CBSVisualizer.Messaging.Events;
+using CBSVisualizer.Services.PacketService.Interface;
+using LiveCharts;
+using LiveCharts.Defaults;
+using LiveCharts.Wpf;
+using log4net;
+using Prism.Commands;
 using Prism.Events;
 using Prism.Regions;
 using System;
 using System.Collections.ObjectModel;
-using System.Diagnostics;
+using System.Collections.Specialized;
 using System.Threading;
 using System.Threading.Tasks;
 
@@ -13,86 +19,134 @@ namespace CBSVisualizer.Modules.Queue.ViewModels
 {
     public partial class QueueViewModel : RegionViewModelBase
     {
+        private const int ThreadJoinTimeoutS = 1;
+
+        private const long CreditRefreshRateS = 5;
+
+        private static readonly ILog Log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod()?.DeclaringType);
+
         private readonly IEventAggregator eventAggregator;
 
+        private readonly IPacketService packetService;
+
         private readonly object queueLock = new object();
 
+        private readonly object creditLock = new object();
+
         private CancellationTokenSource creditGrowthCancellationSource;
 
-        private const double CREDIT_REFRESH_RATE_S = 0.1;
+        private CreditBehaviour selectedCreditBehaviour;
 
-        private double currentCredit = 0;
+        public CreditBehaviour SelectedCreditBehaviour
+        {
+            get => selectedCreditBehaviour;
 
-        private Task creditUpdateTask;
+            set => SetProperty(ref selectedCreditBehaviour, value);
+        }
 
-        public double CurrentCredit
+        private long currentCredit;
+
+        public long CurrentCredit
         {
             get
             {
-                return currentCredit;
+                lock (creditLock)
+                {
+                    return currentCredit;
+                }
             }
 
             private set
             {
-                SetProperty(ref currentCredit, value);
+                lock (creditLock)
+                {
+                    SetProperty(ref currentCredit, value);
+                }
             }
         }
 
-        public enum CreditBehaviour
-        {
-            // This is selected when there should be no credit-based shaper for this queue.
-            NoCBS,
-
-            // Frozen credit behaviour
-            Frozen,
+        private Thread creditUpdateThread;
 
-            // The standard credit behaviour
-            Standard,
-
-            // Return to zero.
-            ReturnToZero
-        }
-
-        private CreditBehaviour selectedCreditBehaviour;
-        public CreditBehaviour SelectedCreditBehaviour { 
-            get 
-            {
-                return selectedCreditBehaviour;
-            }
+        public int Priority { get; }
 
-            set
-            {
-                SetProperty(ref selectedCreditBehaviour, value);
-            }
-        }
+        public string PrioLabel { get; private set; }
 
-        public int Priority { get; private set; }
+        public string PacketLabel { get; private set; }
 
-        public ObservableCollection<PriorityPacket> Queue { get; private set; } = new ObservableCollection<PriorityPacket>();
+        public ObservableCollection<PriorityPacket> Queue { get; } = new ObservableCollection<PriorityPacket>();
 
         /// <summary>
         /// Idle Slope ( given in byte / s).
         /// </summary>
         public int IdleSlope { get; set; } = 100;
 
-        public QueueViewModel(IRegionManager regionManager, IEventAggregator eventAggregator, int prio) :
+        public SeriesCollection Series { get; set; }
+
+        public DelegateCommand GeneratePacketOnClick { get; private set; }
+
+        public QueueViewModel(IRegionManager regionManager, IEventAggregator eventAggregator, int prio, IPacketService packetProvider) :
             base(regionManager)
         {
             this.eventAggregator = eventAggregator;
+            packetService = packetProvider;
             Priority = prio;
+            HandleLabels();
 
             // Register handlers for the different events.
             RegisterPacketHandler();
             RegisterSimulationStartStopHandler();
 
             PropertyChanged += HandleCreditBehaviourChanged;
+            Queue.CollectionChanged += QueueChangedHandler;
 
             eventAggregator.GetEvent<RegisterLinkCallbackEvent>().Publish(GetLinkCallback());
+
+            InitCharts();
+        }
+
+        private void HandleLabels()
+        {
+            if (Priority == 7)
+            {
+                PrioLabel = "Priority";
+                PacketLabel = "Packet Count";
+            }
+            else
+            {
+                PrioLabel = "";
+                PacketLabel = "";
+            }
+        }
+
+        private void QueueChangedHandler(object sender, NotifyCollectionChangedEventArgs e)
+        {
+            // Add the new value to the series.
+            if (selectedCreditBehaviour != CreditBehaviour.NoCbs)
+            {
+                Series[0].Values.Add(new DateTimePoint(DateTime.Now, CurrentCredit));
+            }
+            Series[1].Values.Add(new DateTimePoint(DateTime.Now, Queue.Count));
+        }
+
+        private void InitCharts()
+        {
+            Series = new SeriesCollection
+            {
+                new LineSeries {
+                    Title = "Credit Values",
+                    Values = new ChartValues<DateTimePoint>() { new DateTimePoint(DateTime.Now, 0) }
+                },
+
+                new LineSeries {
+                    Title = "Packet Count",
+                    Values = new ChartValues<DateTimePoint>() { new DateTimePoint(DateTime.Now, 0) }
+                }
+            };
         }
 
         private void HandleCreditBehaviourChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
         {
-            if (e.PropertyName.Equals("SelectedCreditBehaviour"))
+            if (e.PropertyName != null && e.PropertyName.Equals("SelectedCreditBehaviour"))
             {
                 eventAggregator.GetEvent<RegisterLinkCallbackEvent>().Publish(GetLinkCallback());
             }
@@ -111,89 +165,105 @@ namespace CBSVisualizer.Modules.Queue.ViewModels
 
                 case CreditBehaviour.Standard:
                     return new StandardLinkCallback(this);
-
-                case CreditBehaviour.NoCBS:
+                // Default is no CBS.
+                case CreditBehaviour.NoCbs:
                 default:
-                    return new NoCBSLinkCallback(this);
+                    return new NoCbsLinkCallback(this);
             }
         }
 
         private void RegisterSimulationStartStopHandler()
         {
-            eventAggregator.GetEvent<SimulationStartedEvent>().Subscribe(() =>
+            eventAggregator.GetEvent<SimulationStoppedEvent>().Subscribe(() =>
             {
-                if (SelectedCreditBehaviour != CreditBehaviour.NoCBS && Queue.Count >= 1)
+                if (SelectedCreditBehaviour == CreditBehaviour.NoCbs)
                 {
-                    creditUpdateTask = StartCreditThread(IdleSlope);
+                    return;
                 }
-            }
-            );
 
-            eventAggregator.GetEvent<SimulationStoppedEvent>().Subscribe(async () =>
-            {
-                if (SelectedCreditBehaviour != CreditBehaviour.NoCBS)
-                {
-                    await StopCreditThread();
+                StopCreditThread();
 
-                    // Reset credit.
-                    currentCredit = 0;
-                }
+                // Reset credit.
+                CurrentCredit = 0;
             });
         }
 
-        private async Task StopCreditThread()
+        private void StartCreditThread(long bytesPerSecondSlope, long limit = long.MaxValue)
         {
-            creditGrowthCancellationSource?.Cancel();
-            try
+            // Init new cancellation token.
+            creditGrowthCancellationSource = new CancellationTokenSource();
+
+            creditUpdateThread = new Thread(() =>
             {
-                if (creditUpdateTask != null)
+                Log.Info($"Queue {Priority}: Credit Thread was started with {bytesPerSecondSlope} bytes/s slope.");
+                while (!creditGrowthCancellationSource.Token.IsCancellationRequested)
                 {
-                    await creditUpdateTask;
+                    lock (queueLock)
+                    {
+                        lock (creditLock)
+                        {
+                            if (CurrentCredit > limit || Queue.Count <= 0)
+                            {
+                                return;
+                            }
+                        }
+                    }
+
+                    // Wait for the specified amount of time.
+                    Thread.Sleep(TimeSpan.FromSeconds(CreditRefreshRateS));
+
+                    AtomicUpdateCredit(CreditRefreshRateS * bytesPerSecondSlope, limit);
+
+                    Log.Info($"Queue {Priority}: Credit {CurrentCredit}");
                 }
+            });
 
-            } catch (TaskCanceledException)
-            {
-                // Do nothing.
-            }
-            creditUpdateTask = null;
-            creditGrowthCancellationSource = null;
+            creditUpdateThread.Start();
         }
 
-        private async Task StartCreditThread(double bytesPerSecondSlope, double limit = double.PositiveInfinity)
+        private void StopCreditThread()
         {
-            creditGrowthCancellationSource = new CancellationTokenSource();
-            await Task.Run(async () =>
-                {
-                    // Refresh the credit.
-                    while (!creditGrowthCancellationSource.Token.IsCancellationRequested && CurrentCredit < limit && Queue.Count > 0)
-                    {
-                        // Wait for the specified amount of time.
-                        await Task.Delay(TimeSpan.FromSeconds(CREDIT_REFRESH_RATE_S), creditGrowthCancellationSource.Token);
-
-                        AtomicUpdateCredit(CREDIT_REFRESH_RATE_S * bytesPerSecondSlope, limit);
+            creditGrowthCancellationSource?.Cancel();
 
-                        Debug.WriteLine($"Queue {Priority}: Credit {CurrentCredit}");
-                    }
-                }
-            , creditGrowthCancellationSource.Token);
+            if (creditUpdateThread != null)
+            {
+                Log.Info(creditUpdateThread.Join(TimeSpan.FromSeconds(ThreadJoinTimeoutS))
+                    ? $"Queue {Priority}: Unable to stop credit thread."
+                    : $"Queue {Priority}: Credit Thread was stopped successfully.");
+            }
         }
 
-        private void AtomicUpdateCredit(double increment, double limit)
+        private void AtomicUpdateCredit(long increment, long limit)
         {
-            Interlocked.Exchange(ref currentCredit, Math.Min(currentCredit + increment, limit));
+            // Update the credit.
+            CurrentCredit = Math.Min(CurrentCredit + increment, limit);
         }
 
         private void RegisterPacketHandler()
         {
             eventAggregator.GetEvent<PacketArrivedEvent>().Subscribe(packet =>
             {
-                if (packet.Priority == Priority)
+                if (packet.Priority != Priority)
+                {
+                    return;
+                }
+
+                lock (queueLock)
+                {
+                    // Add packet.
+                    Queue.Add(packet);
+                }
+            });
+
+            GeneratePacketOnClick = new DelegateCommand(async () =>
+            {
+                await Task.Run(() =>
                 {
                     lock (queueLock)
                     {
-                        Queue.Add(packet);
+                        Queue.Add(packetService.GeneratePacket(Priority));
                     }
-                }
+                });
             });
         }
     }
diff --git a/CBSVisualizer/CBSVisualizer.Modules.Queue/Views/Queue.xaml b/CBSVisualizer/CBSVisualizer.Modules.Queue/Views/Queue.xaml
index 4897b5c..13428af 100644
--- a/CBSVisualizer/CBSVisualizer.Modules.Queue/Views/Queue.xaml
+++ b/CBSVisualizer/CBSVisualizer.Modules.Queue/Views/Queue.xaml
@@ -1,7 +1,9 @@
 <UserControl x:Class="CBSVisualizer.Modules.Queue.Views.Queue"
              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
              xmlns:local="clr-namespace:CBSVisualizer.Modules.Queue.Views"
+             xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
              mc:Ignorable="d" 
@@ -9,15 +11,43 @@
              xmlns:prism="http://prismlibrary.com/"
              prism:ViewModelLocator.AutoWireViewModel="False" >
     <Grid>
+        <Grid.RowDefinitions>
+            <RowDefinition Height="Auto"/>
+            <RowDefinition Height="*"/>
+        </Grid.RowDefinitions>
         <Grid.ColumnDefinitions>
             <ColumnDefinition Width="*"/>
             <ColumnDefinition Width="*"/>
             <ColumnDefinition Width="*"/>
             <ColumnDefinition Width="*"/>
+            <ColumnDefinition Width="3*"/>
         </Grid.ColumnDefinitions>
-        <TextBlock Text="{Binding Priority}" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Center"/>
-        <TextBlock Text="{Binding Queue.Count}" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center"/>
-        <TextBox x:Name="CreditRateTextBox" Text="{Binding IdleSlope}" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Center"/>
-        <ComboBox x:Name="CreditBehaviourBox" SelectedItem="{Binding SelectedCreditBehaviour}" Grid.Column="3" VerticalAlignment="Center" HorizontalAlignment="Center"/>
+        <TextBlock Text="{Binding PrioLabel}" Grid.Column="0" Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Center"/>
+        <TextBlock Text="{Binding Priority}" Grid.Column="0" Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Center"/>
+        
+        <TextBlock Text="{Binding PacketLabel}" Grid.Column="1" Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Center"/>
+        <TextBlock Text="{Binding Queue.Count}" Grid.Column="1" Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Center">
+            <TextBlock.InputBindings>
+                <MouseBinding MouseAction="RightClick" Command="{Binding GeneratePacketOnClick}"/>
+            </TextBlock.InputBindings>
+        </TextBlock>
+
+        <TextBox materialDesign:HintAssist.Hint="Idle Slope [byte/s]"
+                 Style="{StaticResource MaterialDesignFloatingHintTextBox}"
+                 x:Name="CreditRateTextBox" Text="{Binding IdleSlope}" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Center" TextAlignment="Center" Grid.RowSpan="2"/>
+
+        <ComboBox Style="{StaticResource MaterialDesignFloatingHintComboBox}"
+            materialDesign:TextFieldAssist.UnderlineBrush="{DynamicResource SecondaryAccentBrush}"
+            materialDesign:HintAssist.Hint="Credit Behaviour"
+            x:Name="CreditBehaviourBox" SelectedItem="{Binding SelectedCreditBehaviour}" Grid.Column="3"  Grid.RowSpan="2" VerticalAlignment="Center" HorizontalAlignment="Center"/>
+        
+        <lvc:CartesianChart Series="{Binding Series}" LegendLocation="Right" Grid.Column="4" Grid.RowSpan="2">
+            <lvc:CartesianChart.AxisX>
+                <lvc:Axis Title="Time" LabelFormatter="{Binding XFormatter}" />
+            </lvc:CartesianChart.AxisX>
+            <lvc:CartesianChart.AxisY>
+                <lvc:Axis Title="Credit"/>
+            </lvc:CartesianChart.AxisY>
+        </lvc:CartesianChart>
     </Grid>
 </UserControl>
diff --git a/CBSVisualizer/CBSVisualizer.Modules.Queue/Views/Queue.xaml.cs b/CBSVisualizer/CBSVisualizer.Modules.Queue/Views/Queue.xaml.cs
index 7b92184..e20fa11 100644
--- a/CBSVisualizer/CBSVisualizer.Modules.Queue/Views/Queue.xaml.cs
+++ b/CBSVisualizer/CBSVisualizer.Modules.Queue/Views/Queue.xaml.cs
@@ -1,19 +1,7 @@
 using CBSVisualizer.Modules.Queue.ViewModels;
-using System;
-using System.Collections.Generic;
 using System.Collections.ObjectModel;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
 using System.Windows.Controls;
-using System.Windows.Data;
-using System.Windows.Documents;
-using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using System.Windows.Navigation;
-using System.Windows.Shapes;
+
 using static CBSVisualizer.Modules.Queue.ViewModels.QueueViewModel;
 
 namespace CBSVisualizer.Modules.Queue.Views
@@ -39,7 +27,7 @@ namespace CBSVisualizer.Modules.Queue.Views
 
         private void CreditBehaviourBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
         {
-            if (CreditBehaviourBox.SelectedItem.Equals(CreditBehaviour.NoCBS))
+            if (CreditBehaviourBox.SelectedItem.Equals(CreditBehaviour.NoCbs))
             {
                 CreditRateTextBox.IsEnabled = false;
             } else
@@ -51,7 +39,7 @@ namespace CBSVisualizer.Modules.Queue.Views
         private static ObservableCollection<CreditBehaviour> InitList()
         {
             ObservableCollection<CreditBehaviour> ret = new ObservableCollection<CreditBehaviour>();
-            ret.Add(CreditBehaviour.NoCBS);
+            ret.Add(CreditBehaviour.NoCbs);
             ret.Add(CreditBehaviour.Frozen);
             ret.Add(CreditBehaviour.Standard);
             ret.Add(CreditBehaviour.ReturnToZero);
diff --git a/CBSVisualizer/CBSVisualizer.Modules.SettingsDialog/CBSVisualizer.Modules.SettingsDialog.csproj b/CBSVisualizer/CBSVisualizer.Modules.SettingsDialog/CBSVisualizer.Modules.SettingsDialog.csproj
index e681e4a..f9da61e 100644
--- a/CBSVisualizer/CBSVisualizer.Modules.SettingsDialog/CBSVisualizer.Modules.SettingsDialog.csproj
+++ b/CBSVisualizer/CBSVisualizer.Modules.SettingsDialog/CBSVisualizer.Modules.SettingsDialog.csproj
@@ -5,11 +5,12 @@
     <AssemblyName>CBSVisualizer.Modules.SettingsDialog</AssemblyName>
   </PropertyGroup>
   <ItemGroup>
+    <PackageReference Include="log4net" Version="2.0.9" />
+    <PackageReference Include="MaterialDesignThemes" Version="3.1.3" />
     <PackageReference Include="Prism.Wpf" Version="7.2.0.1422" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\CBSVisualizer.Core\CBSVisualizer.Core.csproj" />
     <ProjectReference Include="..\CBSVisualizer.Services.SettingsService\CBSVisualizer.Services.SettingService.csproj" />
-    <ProjectReference Include="..\CBSVisualizer\CBSVisualizer.Core\CBSVisualizer.Core.csproj" />
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/CBSVisualizer/CBSVisualizer.Modules.SettingsDialog/ViewModels/SettingsDialogViewModel.cs b/CBSVisualizer/CBSVisualizer.Modules.SettingsDialog/ViewModels/SettingsDialogViewModel.cs
index 48b3dc5..ad966f2 100644
--- a/CBSVisualizer/CBSVisualizer.Modules.SettingsDialog/ViewModels/SettingsDialogViewModel.cs
+++ b/CBSVisualizer/CBSVisualizer.Modules.SettingsDialog/ViewModels/SettingsDialogViewModel.cs
@@ -1,14 +1,8 @@
 using CBSVisualizer.Core.Mvvm;
-using CBSVisualizer.Services.SettingsService.Service;
-using Prism.Commands;
-using Prism.Mvvm;
+using CBSVisualizer.Services.SettingsService.Implementation;
 using Prism.Regions;
 using Prism.Services.Dialogs;
 using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace CBSVisualizer.Modules.SettingsDialog.ViewModels
 {
diff --git a/CBSVisualizer/CBSVisualizer.Modules.SettingsDialog/Views/SettingsDialog.xaml b/CBSVisualizer/CBSVisualizer.Modules.SettingsDialog/Views/SettingsDialog.xaml
index 6a5d5cc..6488678 100644
--- a/CBSVisualizer/CBSVisualizer.Modules.SettingsDialog/Views/SettingsDialog.xaml
+++ b/CBSVisualizer/CBSVisualizer.Modules.SettingsDialog/Views/SettingsDialog.xaml
@@ -8,7 +8,13 @@
              mc:Ignorable="d" 
              d:DesignHeight="300" d:DesignWidth="300"
              xmlns:prism="http://prismlibrary.com/"
-             prism:ViewModelLocator.AutoWireViewModel="True" >
+             prism:ViewModelLocator.AutoWireViewModel="True"
+             xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
+             TextElement.Foreground="{DynamicResource MaterialDesignBody}"
+             Background="{DynamicResource MaterialDesignPaper}"
+             TextElement.FontWeight="Medium"
+             TextElement.FontSize="14"
+             FontFamily="{materialDesign:MaterialDesignFont}">
 
     <prism:Dialog.WindowStyle>
         <Style TargetType="Window">
diff --git a/CBSVisualizer/CBSVisualizer.Services.PacketService/CBSVisualizer.Services.PacketService.csproj b/CBSVisualizer/CBSVisualizer.Services.PacketService/CBSVisualizer.Services.PacketService.csproj
new file mode 100644
index 0000000..2d123f6
--- /dev/null
+++ b/CBSVisualizer/CBSVisualizer.Services.PacketService/CBSVisualizer.Services.PacketService.csproj
@@ -0,0 +1,11 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net5.0</TargetFramework>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\CBSVisualizer.MessagingCore\CBSVisualizer.Messaging.csproj" />
+  </ItemGroup>
+
+</Project>
diff --git a/CBSVisualizer/CBSVisualizer.Services.PacketService/Implementation/RandomPacketService.cs b/CBSVisualizer/CBSVisualizer.Services.PacketService/Implementation/RandomPacketService.cs
new file mode 100644
index 0000000..be5b66a
--- /dev/null
+++ b/CBSVisualizer/CBSVisualizer.Services.PacketService/Implementation/RandomPacketService.cs
@@ -0,0 +1,37 @@
+using CBSVisualizer.Messaging;
+using CBSVisualizer.Services.PacketService.Interface;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CBSVisualizer.Services.PacketService.Implementation
+{
+    public class RandomPacketService : IPacketService
+    {
+        private const int HEADER_BYTES = 100;
+
+        private const int TRAILER_BYTES = 100;
+
+        private readonly Random random = new Random();
+
+        public PriorityPacket GeneratePacket(int priority)
+        {
+            return new PriorityPacket(
+            priority, // Priority between 0 and 7
+            HEADER_BYTES,
+            random.Next(2000), // Random value between 0 and 1999.
+            TRAILER_BYTES);
+        }
+
+        public PriorityPacket GeneratePacket()
+        {
+            return new PriorityPacket(
+            random.Next(0, 8), // Priority between 0 and 7
+            HEADER_BYTES,
+            random.Next(2000), // Random value between 0 and 1999.
+            TRAILER_BYTES);
+        }
+    }
+}
diff --git a/CBSVisualizer/CBSVisualizer.Services.PacketService/Interface/IPacketService.cs b/CBSVisualizer/CBSVisualizer.Services.PacketService/Interface/IPacketService.cs
new file mode 100644
index 0000000..0b7ca4c
--- /dev/null
+++ b/CBSVisualizer/CBSVisualizer.Services.PacketService/Interface/IPacketService.cs
@@ -0,0 +1,22 @@
+using CBSVisualizer.Messaging;
+using System;
+using System.Net.Mail;
+
+namespace CBSVisualizer.Services.PacketService.Interface
+{
+    public interface IPacketService
+    {
+        /// <summary>
+        /// Generates a packet with the specified priority.
+        /// </summary>
+        /// <param name="priority"></param>
+        /// <returns></returns>
+        PriorityPacket GeneratePacket(int priority);
+
+        /// <summary>
+        /// Generates a packet with a random priority.
+        /// </summary>
+        /// <returns></returns>
+        PriorityPacket GeneratePacket();
+    }
+}
diff --git a/CBSVisualizer/CBSVisualizer.Services.SchedulingService/CBSVisualizer.Services.SchedulingService.csproj b/CBSVisualizer/CBSVisualizer.Services.SchedulingService/CBSVisualizer.Services.SchedulingService.csproj
index ae5e714..20f292c 100644
--- a/CBSVisualizer/CBSVisualizer.Services.SchedulingService/CBSVisualizer.Services.SchedulingService.csproj
+++ b/CBSVisualizer/CBSVisualizer.Services.SchedulingService/CBSVisualizer.Services.SchedulingService.csproj
@@ -5,7 +5,7 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="log4net" Version="2.0.8" />
+    <PackageReference Include="log4net" Version="2.0.9" />
     <PackageReference Include="Prism.Core" Version="7.2.0.1422" />
   </ItemGroup>
 
diff --git a/CBSVisualizer/CBSVisualizer.Services.SchedulingService/Implementation/RandomSchedulingService.cs b/CBSVisualizer/CBSVisualizer.Services.SchedulingService/Implementation/RandomSchedulingService.cs
index 8bee7e8..9eb15cd 100644
--- a/CBSVisualizer/CBSVisualizer.Services.SchedulingService/Implementation/RandomSchedulingService.cs
+++ b/CBSVisualizer/CBSVisualizer.Services.SchedulingService/Implementation/RandomSchedulingService.cs
@@ -1,5 +1,6 @@
 using CBSVisualizer.Messaging.Events;
-using CBSVisualizer.Services.SettingsService.Service;
+using CBSVisualizer.Services.SchedulingService.Interface;
+using CBSVisualizer.Services.SettingsService.Implementation;
 using log4net;
 using Prism.Events;
 using System;
@@ -12,6 +13,7 @@ namespace CBSVisualizer.Services.SchedulingService.Implementation
     public class RandomSchedulingService : ISchedulingService
     {
         private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
+        private const int PROCESSING_DELAY_MS = 1500;
         private const string MIN_DELAY_SETTING_KEY = "random_scheduler_min_delay";
         private const string MAX_DELAY_SETTING_KEY = "random_scheduler_max_delay";
         private CancellationTokenSource tokenSource;
@@ -36,21 +38,21 @@ namespace CBSVisualizer.Services.SchedulingService.Implementation
                 int highPrioOpenedTime = GetRandomWaitingTime();
 
                 // Publish GateOpenedEvent for the high prio queue.
+                log.Info("Publishing GateOpenedEvent [High Prio]");
                 eventAggregator.GetEvent<GateOpenedEvent>().Publish((OpenedTime: highPrioOpenedTime, OpenedGates: new HashSet<int> { 7 }));
-                log.Info("Published GateOpenedEvent [High Prio]");
 
                 // Wait for the specified time.
-                await Task.Delay(highPrioOpenedTime, tokenSource.Token);
+                await Task.Delay(highPrioOpenedTime + PROCESSING_DELAY_MS, tokenSource.Token);
 
                 // Get the opening time for the low prio.
                 int lowPrioOpenedTime = GetRandomWaitingTime();
 
                 // Publish another GateOpenedEvent for the other queues.
+                log.Info("Publishing GateOpenedEvent [Lower Prio]");
                 eventAggregator.GetEvent<GateOpenedEvent>().Publish((OpenedTime: lowPrioOpenedTime, OpenedGates: new HashSet<int> { 0, 1, 2, 3, 4, 5, 6 }));
-                log.Info("Published GateOpenedEvent [Lower Prio]");
 
                 // Wait for the specified time again.
-                await Task.Delay(lowPrioOpenedTime, tokenSource.Token);
+                await Task.Delay(lowPrioOpenedTime + PROCESSING_DELAY_MS, tokenSource.Token);
             }
         }
 
@@ -59,26 +61,15 @@ namespace CBSVisualizer.Services.SchedulingService.Implementation
             return random.Next(settings.GetSettingValue<int>(MIN_DELAY_SETTING_KEY), settings.GetSettingValue<int>(MAX_DELAY_SETTING_KEY));
         }
 
-        public void StartScheduling()
+        public async Task StartScheduling()
         {
             tokenSource = new CancellationTokenSource();
-            schedulerTask = StartScheduler();
+            await StartScheduler();
         }
 
-        public async Task StopScheduling()
+        public void StopScheduling()
         {
-            try
-            {
-                tokenSource?.Cancel();
-                if (schedulerTask != null)
-                {
-                    await schedulerTask;
-                }
-            } catch (TaskCanceledException)
-            {
-                // Don't do anything.
-            }
-
+            tokenSource?.Cancel();
         }
     }
 }
\ No newline at end of file
diff --git a/CBSVisualizer/CBSVisualizer.Services.SchedulingService/Interface/ISchedulingService.cs b/CBSVisualizer/CBSVisualizer.Services.SchedulingService/Interface/ISchedulingService.cs
index 2fd639a..e5bb1a1 100644
--- a/CBSVisualizer/CBSVisualizer.Services.SchedulingService/Interface/ISchedulingService.cs
+++ b/CBSVisualizer/CBSVisualizer.Services.SchedulingService/Interface/ISchedulingService.cs
@@ -1,15 +1,11 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System.Threading.Tasks;
 
-namespace CBSVisualizer.Services.SchedulingService
+namespace CBSVisualizer.Services.SchedulingService.Interface
 {
     public interface ISchedulingService
     {
-        public void StartScheduling();
+        public Task StartScheduling();
 
-        public Task StopScheduling();
+        public void StopScheduling();
     }
 }
diff --git a/CBSVisualizer/CBSVisualizer.Services.SettingsService/CBSVisualizer.Services.SettingService.csproj b/CBSVisualizer/CBSVisualizer.Services.SettingsService/CBSVisualizer.Services.SettingService.csproj
index e90b892..6ba72c0 100644
--- a/CBSVisualizer/CBSVisualizer.Services.SettingsService/CBSVisualizer.Services.SettingService.csproj
+++ b/CBSVisualizer/CBSVisualizer.Services.SettingsService/CBSVisualizer.Services.SettingService.csproj
@@ -7,6 +7,7 @@
   </PropertyGroup>
 
   <ItemGroup>
+    <PackageReference Include="log4net" Version="2.0.9" />
     <PackageReference Include="Ookii.Dialogs.Wpf" Version="1.1.0" />
     <PackageReference Include="Prism.Core" Version="7.2.0.1422" />
   </ItemGroup>
diff --git a/CBSVisualizer/CBSVisualizer.Services.SettingsService/Service/SettingService.cs b/CBSVisualizer/CBSVisualizer.Services.SettingsService/Implementation/SettingService.cs
similarity index 96%
rename from CBSVisualizer/CBSVisualizer.Services.SettingsService/Service/SettingService.cs
rename to CBSVisualizer/CBSVisualizer.Services.SettingsService/Implementation/SettingService.cs
index 72e9458..3be0dff 100644
--- a/CBSVisualizer/CBSVisualizer.Services.SettingsService/Service/SettingService.cs
+++ b/CBSVisualizer/CBSVisualizer.Services.SettingsService/Implementation/SettingService.cs
@@ -6,7 +6,7 @@ using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 
-namespace CBSVisualizer.Services.SettingsService.Service
+namespace CBSVisualizer.Services.SettingsService.Implementation
 {
     public class SettingService
     {
diff --git a/CBSVisualizer/CBSVisualizer.sln b/CBSVisualizer/CBSVisualizer.sln
index bc17186..ccf16e1 100644
--- a/CBSVisualizer/CBSVisualizer.sln
+++ b/CBSVisualizer/CBSVisualizer.sln
@@ -36,6 +36,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CBSVisualizer.Core", "CBSVi
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CBSVisualizer.Common", "CBSVisualizer.Common\CBSVisualizer.Common.csproj", "{9B1B603C-601C-4F31-ADD9-D0962C0011AF}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CBSVisualizer.Services.PacketService", "CBSVisualizer.Services.PacketService\CBSVisualizer.Services.PacketService.csproj", "{274C0DC3-C59C-4C91-8130-6DEF2BDBD0A1}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -86,6 +88,10 @@ Global
 		{9B1B603C-601C-4F31-ADD9-D0962C0011AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{9B1B603C-601C-4F31-ADD9-D0962C0011AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{9B1B603C-601C-4F31-ADD9-D0962C0011AF}.Release|Any CPU.Build.0 = Release|Any CPU
+		{274C0DC3-C59C-4C91-8130-6DEF2BDBD0A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{274C0DC3-C59C-4C91-8130-6DEF2BDBD0A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{274C0DC3-C59C-4C91-8130-6DEF2BDBD0A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{274C0DC3-C59C-4C91-8130-6DEF2BDBD0A1}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -99,6 +105,7 @@ Global
 		{B2059A32-91EC-4CFF-AB5C-87FBC3B6686C} = {6D2194E0-E17B-44D6-AD8C-F3699549D259}
 		{AB9EA79C-F11F-4B93-A08E-8C52A9716666} = {BFDCC6CE-CAA6-45AA-832F-0CBAB9A3C8BA}
 		{61B7FF00-1B9D-4ABF-B3BF-667A1505415F} = {BFDCC6CE-CAA6-45AA-832F-0CBAB9A3C8BA}
+		{274C0DC3-C59C-4C91-8130-6DEF2BDBD0A1} = {BFDCC6CE-CAA6-45AA-832F-0CBAB9A3C8BA}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {EE8EFE44-67AF-451F-9DFD-7B458AA3B3B3}
diff --git a/CBSVisualizer/CBSVisualizer/App.xaml b/CBSVisualizer/CBSVisualizer/App.xaml
index 80fe455..220ab7b 100644
--- a/CBSVisualizer/CBSVisualizer/App.xaml
+++ b/CBSVisualizer/CBSVisualizer/App.xaml
@@ -2,7 +2,14 @@
              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:local="clr-namespace:CBSVisualizer"
+             xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
              xmlns:prism="http://prismlibrary.com/" >
     <Application.Resources>
+        <ResourceDictionary>
+            <ResourceDictionary.MergedDictionaries>
+                <materialDesign:BundledTheme BaseTheme="Dark" PrimaryColor="Amber" SecondaryColor="LightBlue" />
+                <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
+            </ResourceDictionary.MergedDictionaries>
+        </ResourceDictionary>
     </Application.Resources>
 </prism:PrismApplication>
diff --git a/CBSVisualizer/CBSVisualizer/App.xaml.cs b/CBSVisualizer/CBSVisualizer/App.xaml.cs
index 8fd0e59..dfe06d6 100644
--- a/CBSVisualizer/CBSVisualizer/App.xaml.cs
+++ b/CBSVisualizer/CBSVisualizer/App.xaml.cs
@@ -2,7 +2,7 @@
 using CBSVisualizer.Views;
 using System.Windows;
 using Prism.Modularity;
-using CBSVisualizer.Services.SettingsService.Service;
+using CBSVisualizer.Services.SettingsService.Implementation;
 using CBSVisualizer.Services.SchedulingService.Implementation;
 using CBSVisualizer.Modules.Queue.QueueGroup;
 using CBSVisualizer.Services.SchedulingService;
@@ -10,7 +10,9 @@ using CBSVisualizer.Modules.Link;
 using CBSVisualizer.Modules.SettingsDialog;
 using CBSVisualizer.Modules.MenuBar;
 using System.IO;
-using System.Configuration;
+using CBSVisualizer.Services.PacketService.Implementation;
+using CBSVisualizer.Services.PacketService.Interface;
+using CBSVisualizer.Services.SchedulingService.Interface;
 
 namespace CBSVisualizer
 {
@@ -29,6 +31,7 @@ namespace CBSVisualizer
             // containerRegistry.RegisterSingleton<IMessageService, MessageService>();
             containerRegistry.RegisterSingleton<SettingService>();
             containerRegistry.RegisterSingleton<ISchedulingService, RandomSchedulingService>();
+            containerRegistry.RegisterSingleton<IPacketService, RandomPacketService>();
         }
 
         protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
diff --git a/CBSVisualizer/CBSVisualizer/CBSVisualizer.csproj b/CBSVisualizer/CBSVisualizer/CBSVisualizer.csproj
index 5e2cc6e..3a731bf 100644
--- a/CBSVisualizer/CBSVisualizer/CBSVisualizer.csproj
+++ b/CBSVisualizer/CBSVisualizer/CBSVisualizer.csproj
@@ -7,7 +7,8 @@
     <AssemblyName>CBSVisualizer</AssemblyName>
   </PropertyGroup>
   <ItemGroup>
-    <PackageReference Include="log4net" Version="2.0.8" />
+    <PackageReference Include="log4net" Version="2.0.9" />
+    <PackageReference Include="MaterialDesignThemes" Version="3.1.3" />
     <PackageReference Include="Prism.DryIoc" Version="7.2.0.1422" />
   </ItemGroup>
   <ItemGroup>
@@ -15,6 +16,7 @@
     <ProjectReference Include="..\CBSVisualizer.Modules.MenuBar\CBSVisualizer.Modules.MenuBar.csproj" />
     <ProjectReference Include="..\CBSVisualizer.Modules.Queue.QueueGroup\CBSVisualizer.Modules.QueueGroup.csproj" />
     <ProjectReference Include="..\CBSVisualizer.Modules.SettingsDialog\CBSVisualizer.Modules.SettingsDialog.csproj" />
+    <ProjectReference Include="..\CBSVisualizer.Services.PacketService\CBSVisualizer.Services.PacketService.csproj" />
     <ProjectReference Include="..\CBSVisualizer.Services.SchedulingService\CBSVisualizer.Services.SchedulingService.csproj" />
     <ProjectReference Include="..\CBSVisualizer.Services.SettingsService\CBSVisualizer.Services.SettingService.csproj" />
   </ItemGroup>
diff --git a/CBSVisualizer/CBSVisualizer/Views/MainWindow.xaml b/CBSVisualizer/CBSVisualizer/Views/MainWindow.xaml
index 4be8a18..1d12452 100644
--- a/CBSVisualizer/CBSVisualizer/Views/MainWindow.xaml
+++ b/CBSVisualizer/CBSVisualizer/Views/MainWindow.xaml
@@ -4,18 +4,25 @@
         xmlns:prism="http://prismlibrary.com/"
         prism:ViewModelLocator.AutoWireViewModel="True"
         xmlns:core="clr-namespace:CBSVisualizer.Core;assembly=CBSVisualizer.Core"
-        Title="{Binding Title}" MinHeight="433" Height="433" MinWidth="867" Width="867" >
+        Title="{Binding Title}" MinHeight="433" Height="433" MinWidth="867" Width="867"
+        xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
+        TextElement.Foreground="{DynamicResource MaterialDesignBody}"
+        Background="{DynamicResource MaterialDesignPaper}"
+        TextElement.FontWeight="Medium"
+        TextElement.FontSize="14"
+        FontFamily="{materialDesign:MaterialDesignFont}"
+        >
     <Grid>
         <Grid.RowDefinitions>
             <RowDefinition Height="Auto"/>
             <RowDefinition Height="*"/>
         </Grid.RowDefinitions>
         <Grid.ColumnDefinitions>
-            <ColumnDefinition Width="*"/>
             <ColumnDefinition Width="Auto"/>
+            <ColumnDefinition Width="*"/>
         </Grid.ColumnDefinitions>
         <ContentControl prism:RegionManager.RegionName="{x:Static core:RegionNames.MenuBarRegion}" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2"/>
-        <ContentControl prism:RegionManager.RegionName="{x:Static core:RegionNames.QueueGroupRegion}" Grid.Column="0" Grid.Row="1"/>
-        <ContentControl prism:RegionManager.RegionName="{x:Static core:RegionNames.LinkRegion}" Grid.Column="1" Grid.Row="1" Margin="0, 0, 5, 0"/>
+        <ContentControl prism:RegionManager.RegionName="{x:Static core:RegionNames.QueueGroupRegion}" Grid.Column="1" Grid.Row="1"/>
+        <ContentControl prism:RegionManager.RegionName="{x:Static core:RegionNames.LinkRegion}" Grid.Column="0" Grid.Row="1" Margin="30, 0, 0, 0"/>
     </Grid>
 </Window>
-- 
GitLab