From 4c9fa6feffaa2932d7aa12706cc7f988bb8e2bd8 Mon Sep 17 00:00:00 2001 From: "Zechert, Frank (EXTERN: Capgemini)" Date: Thu, 17 Dec 2020 17:45:20 +0100 Subject: [PATCH] initial commit --- App.config | 52 +++ BluetoothManager.cs | 171 +++++++ MainWindow.Designer.cs | 752 +++++++++++++++++++++++++++++++ MainWindow.cs | 563 +++++++++++++++++++++++ MainWindow.resx | 372 +++++++++++++++ Meeting-Clock.csproj | 163 +++++++ Meeting-Clock.sln | 37 ++ MeetingClock.cs | 19 + MeetingClockManager.cs | 479 ++++++++++++++++++++ OutlookManager.cs | 181 ++++++++ Properties/AssemblyInfo.cs | 38 ++ Properties/Resources.Designer.cs | 113 +++++ Properties/Resources.resx | 136 ++++++ Properties/Settings.Designer.cs | 143 ++++++ Properties/Settings.settings | 36 ++ Settings.cs | 164 +++++++ icons/icon-error.ico | Bin 0 -> 6782 bytes icons/icon-error.xcf | Bin 0 -> 4000 bytes icons/icon-neutral.ico | Bin 0 -> 6782 bytes icons/icon-neutral.xcf | Bin 0 -> 4000 bytes icons/icon-off.ico | Bin 0 -> 6782 bytes icons/icon-off.xcf | Bin 0 -> 4000 bytes icons/icon-ok.ico | Bin 0 -> 6782 bytes icons/icon-ok.xcf | Bin 0 -> 4000 bytes icons/icon-warning.ico | Bin 0 -> 6782 bytes icons/icon-warning.xcf | Bin 0 -> 4000 bytes 26 files changed, 3419 insertions(+) create mode 100644 App.config create mode 100644 BluetoothManager.cs create mode 100644 MainWindow.Designer.cs create mode 100644 MainWindow.cs create mode 100644 MainWindow.resx create mode 100644 Meeting-Clock.csproj create mode 100644 Meeting-Clock.sln create mode 100644 MeetingClock.cs create mode 100644 MeetingClockManager.cs create mode 100644 OutlookManager.cs create mode 100644 Properties/AssemblyInfo.cs create mode 100644 Properties/Resources.Designer.cs create mode 100644 Properties/Resources.resx create mode 100644 Properties/Settings.Designer.cs create mode 100644 Properties/Settings.settings create mode 100644 Settings.cs create mode 100644 icons/icon-error.ico create mode 100644 icons/icon-error.xcf create mode 100644 icons/icon-neutral.ico create mode 100644 icons/icon-neutral.xcf create mode 100644 icons/icon-off.ico create mode 100644 icons/icon-off.xcf create mode 100644 icons/icon-ok.ico create mode 100644 icons/icon-ok.xcf create mode 100644 icons/icon-warning.ico create mode 100644 icons/icon-warning.xcf diff --git a/App.config b/App.config new file mode 100644 index 0000000..a203aac --- /dev/null +++ b/App.config @@ -0,0 +1,52 @@ + + + + +
+ + +
+ + + + + + + + + v. 1.0.0 + + + + + + + True + + + False + + + False + + + True + + + True + + + False + + + False + + + False + + + 10 + + + + \ No newline at end of file diff --git a/BluetoothManager.cs b/BluetoothManager.cs new file mode 100644 index 0000000..3235285 --- /dev/null +++ b/BluetoothManager.cs @@ -0,0 +1,171 @@ +using System; +using System.Diagnostics; +using System.Threading.Tasks; +using System.Timers; +using Windows.Devices.Bluetooth; +using Windows.Devices.Radios; + +namespace MeetingClock +{ + public class BluetoothManager + { + public enum BluetoothState + { + NotInitialized, + Exception, + NoBluetoothAdapter, + NoBluetoothRadio, + Disabled, + Off, + On, + Unknown + } + + public delegate void BluetoothStateChangeHandler(BluetoothManager manager, BluetoothState oldState, BluetoothState newState); + public event BluetoothStateChangeHandler StateChanged; + + public BluetoothState State { get; private set; } = BluetoothState.NotInitialized; + + private BluetoothAdapter adapter; + private Radio radio; + private Timer updateTimer; + + public BluetoothManager() + { + this.updateTimer = new Timer(100); + this.updateTimer.Elapsed += UpdateTimer_Elapsed; + } + + public async Task Initialize() + { + await this.InitializePrivate(true); + } + + private async Task InitializePrivate(bool withLog) + { + try + { + this.adapter = await BluetoothAdapter.GetDefaultAsync(); + if (this.adapter == null) + { + if (withLog) + { + Debug.WriteLine("No BluetoothAdapter found"); + } + this.State = BluetoothState.NoBluetoothAdapter; + this.StateChanged(this, BluetoothState.NotInitialized, BluetoothState.NoBluetoothAdapter); + this.updateTimer.Start(); + return; + } + if (withLog) + { + Debug.WriteLine(String.Format("Found BluetoothAdapter device id: {0}, address: {1}", this.adapter.DeviceId, this.adapter.BluetoothAddress)); + } + + this.radio = await this.adapter.GetRadioAsync(); + if (this.radio == null) + { + if (withLog) + { + Debug.WriteLine("No Radio found"); + } + this.State = BluetoothState.NoBluetoothRadio; + this.StateChanged(this, BluetoothState.NotInitialized, BluetoothState.NoBluetoothRadio); + this.updateTimer.Start(); + return; + } + if (withLog) + { + Debug.WriteLine(String.Format("Found Bluetooth Radio device: {0}", this.radio.Name)); + } + + this.radio.StateChanged += Radio_StateChanged; + this.UpdateState(); + + if (withLog) + { + Debug.WriteLine(String.Format("Bluetooth State: {0}", this.State)); + } + + this.updateTimer.Start(); + } + catch (Exception exception) + { + + if (withLog) + { + Debug.WriteLine(String.Format("Exception while discovering bluetooth adapter, radio, and state: {0}", exception.Message)); + } + this.State = BluetoothState.Exception; + this.StateChanged(this, BluetoothState.NotInitialized, BluetoothState.Exception); + } + } + + private void UpdateState() { + RadioState state = this.radio.State; + BluetoothState oldState = this.State; + BluetoothState btState; + switch (state) + { + case RadioState.Disabled: + btState = BluetoothState.Disabled; + break; + case RadioState.Off: + btState = BluetoothState.Off; + break; + case RadioState.On: + btState = BluetoothState.On; + break; + default: + btState = BluetoothState.Unknown; + break; + } + + if (btState != this.State) + { + Debug.WriteLine(String.Format("New Bluetooth state detected. Old state {0}, new state {1}", this.State, btState)); + this.State = btState; + if (this.StateChanged != null) + { + this.StateChanged(this, oldState, btState); + } + } + } + + private void Radio_StateChanged(Radio sender, object args) + { + this.UpdateState(); + } + + private async void UpdateTimer_Elapsed(object sender, ElapsedEventArgs e) + { + switch (this.State) + { + case BluetoothState.Exception: + this.updateTimer.Stop(); + break; + case BluetoothState.NotInitialized: + case BluetoothState.NoBluetoothAdapter: + case BluetoothState.NoBluetoothRadio: + await this.InitializePrivate(false); + break; + default: + this.UpdateState(); + break; + } + } + + public async Task Enable() + { + if (this.radio != null) { + return await this.radio.SetStateAsync(RadioState.On); + } + return RadioAccessStatus.Unspecified; + } + + public void Stop() + { + this.updateTimer.Stop(); + } + } +} diff --git a/MainWindow.Designer.cs b/MainWindow.Designer.cs new file mode 100644 index 0000000..f21c1db --- /dev/null +++ b/MainWindow.Designer.cs @@ -0,0 +1,752 @@ + +namespace MeetingClock +{ + partial class MainWindow + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainWindow)); + this.groupBoxState = new System.Windows.Forms.GroupBox(); + this.buttonWebsite = new System.Windows.Forms.Button(); + this.buttonOpenSystemSettingsBluetooth = new System.Windows.Forms.Button(); + this.labelMeetingClockState = new System.Windows.Forms.Label(); + this.labelMeetingClockStateTitle = new System.Windows.Forms.Label(); + this.buttonOpenSystemSettingsPrivacy = new System.Windows.Forms.Button(); + this.buttonEnableBluetooth = new System.Windows.Forms.Button(); + this.labelBluetoothState = new System.Windows.Forms.Label(); + this.labelBluetoothStateTitle = new System.Windows.Forms.Label(); + this.groupBoxApplicationSettings = new System.Windows.Forms.GroupBox(); + this.checkBoxEnableBluetooth = new System.Windows.Forms.CheckBox(); + this.checkBoxCheckForUpdates = new System.Windows.Forms.CheckBox(); + this.checkBoxStartMinimized = new System.Windows.Forms.CheckBox(); + this.checkBoxAutostart = new System.Windows.Forms.CheckBox(); + this.notifyIcon = new System.Windows.Forms.NotifyIcon(this.components); + this.timerEnableBalloon = new System.Windows.Forms.Timer(this.components); + this.groupBoxAppointmentSettings = new System.Windows.Forms.GroupBox(); + this.checkBoxIgnoreTentativeAppointments = new System.Windows.Forms.CheckBox(); + this.checkBoxIgnoreOutOfOfficeAppointments = new System.Windows.Forms.CheckBox(); + this.checkBoxIgnoreFreeAppointments = new System.Windows.Forms.CheckBox(); + this.checkBoxIgnoreCancelledAppointments = new System.Windows.Forms.CheckBox(); + this.checkBoxIgnoreAllDayAppointments = new System.Windows.Forms.CheckBox(); + this.groupBoxClockSettings = new System.Windows.Forms.GroupBox(); + this.label1 = new System.Windows.Forms.Label(); + this.numericUpDownScrollWait = new System.Windows.Forms.NumericUpDown(); + this.labelScrollWaitTitle = new System.Windows.Forms.Label(); + this.labelScrollSpeed = new System.Windows.Forms.Label(); + this.labelScrollSpeedTitle = new System.Windows.Forms.Label(); + this.trackBarScrollSpeed = new System.Windows.Forms.TrackBar(); + this.labelBrightness = new System.Windows.Forms.Label(); + this.labelBrightnessTitle = new System.Windows.Forms.Label(); + this.trackBarBrightness = new System.Windows.Forms.TrackBar(); + this.labelTemperatureIntervalTitleSeconds = new System.Windows.Forms.Label(); + this.numericUpDownTemperatureInterval = new System.Windows.Forms.NumericUpDown(); + this.checkBoxTemperatureEnabled = new System.Windows.Forms.CheckBox(); + this.labelDateIntervalTitleSeconds = new System.Windows.Forms.Label(); + this.numericUpDownDateInterval = new System.Windows.Forms.NumericUpDown(); + this.labelTimeIntervalTitleSeconds = new System.Windows.Forms.Label(); + this.numericUpDownTimeInterval = new System.Windows.Forms.NumericUpDown(); + this.labelTimeIntervalTitle = new System.Windows.Forms.Label(); + this.checkBoxDateEnabled = new System.Windows.Forms.CheckBox(); + this.timerScrollDemo = new System.Windows.Forms.Timer(this.components); + this.buttonResetDefault = new System.Windows.Forms.Button(); + this.timerAdjustClock = new System.Windows.Forms.Timer(this.components); + this.timerGetAppointment = new System.Windows.Forms.Timer(this.components); + this.label2 = new System.Windows.Forms.Label(); + this.numericUpDownReminderTime = new System.Windows.Forms.NumericUpDown(); + this.labelStartReminderTitle = new System.Windows.Forms.Label(); + this.groupBoxState.SuspendLayout(); + this.groupBoxApplicationSettings.SuspendLayout(); + this.groupBoxAppointmentSettings.SuspendLayout(); + this.groupBoxClockSettings.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDownScrollWait)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.trackBarScrollSpeed)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.trackBarBrightness)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDownTemperatureInterval)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDownDateInterval)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDownTimeInterval)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDownReminderTime)).BeginInit(); + this.SuspendLayout(); + // + // groupBoxState + // + this.groupBoxState.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBoxState.Controls.Add(this.buttonWebsite); + this.groupBoxState.Controls.Add(this.buttonOpenSystemSettingsBluetooth); + this.groupBoxState.Controls.Add(this.labelMeetingClockState); + this.groupBoxState.Controls.Add(this.labelMeetingClockStateTitle); + this.groupBoxState.Controls.Add(this.buttonOpenSystemSettingsPrivacy); + this.groupBoxState.Controls.Add(this.buttonEnableBluetooth); + this.groupBoxState.Controls.Add(this.labelBluetoothState); + this.groupBoxState.Controls.Add(this.labelBluetoothStateTitle); + this.groupBoxState.Location = new System.Drawing.Point(12, 12); + this.groupBoxState.Name = "groupBoxState"; + this.groupBoxState.Size = new System.Drawing.Size(560, 100); + this.groupBoxState.TabIndex = 0; + this.groupBoxState.TabStop = false; + this.groupBoxState.Text = "State"; + // + // buttonWebsite + // + this.buttonWebsite.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.buttonWebsite.Location = new System.Drawing.Point(392, 65); + this.buttonWebsite.Name = "buttonWebsite"; + this.buttonWebsite.Size = new System.Drawing.Size(162, 23); + this.buttonWebsite.TabIndex = 8; + this.buttonWebsite.Text = "Open Website"; + this.buttonWebsite.UseVisualStyleBackColor = true; + this.buttonWebsite.Click += new System.EventHandler(this.buttonWebsite_Click); + // + // buttonOpenSystemSettingsBluetooth + // + this.buttonOpenSystemSettingsBluetooth.Location = new System.Drawing.Point(197, 65); + this.buttonOpenSystemSettingsBluetooth.Name = "buttonOpenSystemSettingsBluetooth"; + this.buttonOpenSystemSettingsBluetooth.Size = new System.Drawing.Size(185, 23); + this.buttonOpenSystemSettingsBluetooth.TabIndex = 7; + this.buttonOpenSystemSettingsBluetooth.Text = "Open System Settings: Bluetooth"; + this.buttonOpenSystemSettingsBluetooth.UseVisualStyleBackColor = true; + this.buttonOpenSystemSettingsBluetooth.Click += new System.EventHandler(this.buttonOpenSystemSettingsBluetooth_Click); + // + // labelMeetingClockState + // + this.labelMeetingClockState.AutoSize = true; + this.labelMeetingClockState.Location = new System.Drawing.Point(99, 46); + this.labelMeetingClockState.Name = "labelMeetingClockState"; + this.labelMeetingClockState.Size = new System.Drawing.Size(51, 13); + this.labelMeetingClockState.TabIndex = 6; + this.labelMeetingClockState.Text = "unknown"; + // + // labelMeetingClockStateTitle + // + this.labelMeetingClockStateTitle.AutoSize = true; + this.labelMeetingClockStateTitle.Location = new System.Drawing.Point(7, 46); + this.labelMeetingClockStateTitle.Name = "labelMeetingClockStateTitle"; + this.labelMeetingClockStateTitle.Size = new System.Drawing.Size(78, 13); + this.labelMeetingClockStateTitle.TabIndex = 5; + this.labelMeetingClockStateTitle.Text = "Meeting Clock:"; + // + // buttonOpenSystemSettingsPrivacy + // + this.buttonOpenSystemSettingsPrivacy.Location = new System.Drawing.Point(6, 65); + this.buttonOpenSystemSettingsPrivacy.Name = "buttonOpenSystemSettingsPrivacy"; + this.buttonOpenSystemSettingsPrivacy.Size = new System.Drawing.Size(185, 23); + this.buttonOpenSystemSettingsPrivacy.TabIndex = 3; + this.buttonOpenSystemSettingsPrivacy.Text = "Open System Settings: Privacy"; + this.buttonOpenSystemSettingsPrivacy.UseVisualStyleBackColor = true; + this.buttonOpenSystemSettingsPrivacy.Click += new System.EventHandler(this.ButtonOpenSystemSettingsPrivacy_Click); + // + // buttonEnableBluetooth + // + this.buttonEnableBluetooth.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.buttonEnableBluetooth.Enabled = false; + this.buttonEnableBluetooth.Location = new System.Drawing.Point(392, 19); + this.buttonEnableBluetooth.Name = "buttonEnableBluetooth"; + this.buttonEnableBluetooth.Size = new System.Drawing.Size(162, 40); + this.buttonEnableBluetooth.TabIndex = 2; + this.buttonEnableBluetooth.Text = "Enable Bluetooth"; + this.buttonEnableBluetooth.UseVisualStyleBackColor = true; + this.buttonEnableBluetooth.Click += new System.EventHandler(this.ButtonEnableBluetooth_Click); + // + // labelBluetoothState + // + this.labelBluetoothState.AutoSize = true; + this.labelBluetoothState.Location = new System.Drawing.Point(99, 24); + this.labelBluetoothState.Name = "labelBluetoothState"; + this.labelBluetoothState.Size = new System.Drawing.Size(51, 13); + this.labelBluetoothState.TabIndex = 1; + this.labelBluetoothState.Text = "unknown"; + // + // labelBluetoothStateTitle + // + this.labelBluetoothStateTitle.AutoSize = true; + this.labelBluetoothStateTitle.Location = new System.Drawing.Point(7, 24); + this.labelBluetoothStateTitle.Name = "labelBluetoothStateTitle"; + this.labelBluetoothStateTitle.Size = new System.Drawing.Size(83, 13); + this.labelBluetoothStateTitle.TabIndex = 0; + this.labelBluetoothStateTitle.Text = "Bluetooth State:"; + // + // groupBoxApplicationSettings + // + this.groupBoxApplicationSettings.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBoxApplicationSettings.Controls.Add(this.checkBoxEnableBluetooth); + this.groupBoxApplicationSettings.Controls.Add(this.checkBoxCheckForUpdates); + this.groupBoxApplicationSettings.Controls.Add(this.checkBoxStartMinimized); + this.groupBoxApplicationSettings.Controls.Add(this.checkBoxAutostart); + this.groupBoxApplicationSettings.Location = new System.Drawing.Point(12, 118); + this.groupBoxApplicationSettings.Name = "groupBoxApplicationSettings"; + this.groupBoxApplicationSettings.Size = new System.Drawing.Size(560, 116); + this.groupBoxApplicationSettings.TabIndex = 1; + this.groupBoxApplicationSettings.TabStop = false; + this.groupBoxApplicationSettings.Text = "Application Settings"; + // + // checkBoxEnableBluetooth + // + this.checkBoxEnableBluetooth.AutoSize = true; + this.checkBoxEnableBluetooth.Location = new System.Drawing.Point(6, 91); + this.checkBoxEnableBluetooth.Name = "checkBoxEnableBluetooth"; + this.checkBoxEnableBluetooth.Size = new System.Drawing.Size(172, 17); + this.checkBoxEnableBluetooth.TabIndex = 3; + this.checkBoxEnableBluetooth.Text = "Automatically Enable Bluetooth"; + this.checkBoxEnableBluetooth.UseVisualStyleBackColor = true; + this.checkBoxEnableBluetooth.CheckedChanged += new System.EventHandler(this.checkBoxEnableBluetooth_CheckedChanged); + // + // checkBoxCheckForUpdates + // + this.checkBoxCheckForUpdates.AutoSize = true; + this.checkBoxCheckForUpdates.Location = new System.Drawing.Point(6, 67); + this.checkBoxCheckForUpdates.Name = "checkBoxCheckForUpdates"; + this.checkBoxCheckForUpdates.Size = new System.Drawing.Size(180, 17); + this.checkBoxCheckForUpdates.TabIndex = 2; + this.checkBoxCheckForUpdates.Text = "Automatically Check for Updates"; + this.checkBoxCheckForUpdates.UseVisualStyleBackColor = true; + this.checkBoxCheckForUpdates.CheckedChanged += new System.EventHandler(this.checkBoxCheckForUpdates_CheckedChanged); + // + // checkBoxStartMinimized + // + this.checkBoxStartMinimized.AutoSize = true; + this.checkBoxStartMinimized.Location = new System.Drawing.Point(6, 43); + this.checkBoxStartMinimized.Name = "checkBoxStartMinimized"; + this.checkBoxStartMinimized.Size = new System.Drawing.Size(97, 17); + this.checkBoxStartMinimized.TabIndex = 1; + this.checkBoxStartMinimized.Text = "Start Minimized"; + this.checkBoxStartMinimized.UseVisualStyleBackColor = true; + this.checkBoxStartMinimized.CheckedChanged += new System.EventHandler(this.checkBoxStartMinimized_CheckedChanged); + // + // checkBoxAutostart + // + this.checkBoxAutostart.AutoSize = true; + this.checkBoxAutostart.Location = new System.Drawing.Point(6, 19); + this.checkBoxAutostart.Name = "checkBoxAutostart"; + this.checkBoxAutostart.Size = new System.Drawing.Size(182, 17); + this.checkBoxAutostart.TabIndex = 0; + this.checkBoxAutostart.Text = "Automatically Start with Windows"; + this.checkBoxAutostart.UseVisualStyleBackColor = true; + this.checkBoxAutostart.CheckedChanged += new System.EventHandler(this.checkBoxAutostart_CheckedChanged); + // + // notifyIcon + // + this.notifyIcon.BalloonTipIcon = System.Windows.Forms.ToolTipIcon.Info; + this.notifyIcon.BalloonTipText = "Meeting Clock was minimized to the tray"; + this.notifyIcon.BalloonTipTitle = "Minimized to Tray"; + this.notifyIcon.Icon = ((System.Drawing.Icon)(resources.GetObject("notifyIcon.Icon"))); + this.notifyIcon.Text = "Meeting Clock"; + this.notifyIcon.Visible = true; + this.notifyIcon.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.NotifyIcon_MouseDoubleClick); + // + // timerEnableBalloon + // + this.timerEnableBalloon.Enabled = true; + this.timerEnableBalloon.Interval = 1000; + this.timerEnableBalloon.Tick += new System.EventHandler(this.timerEnableBalloon_Tick); + // + // groupBoxAppointmentSettings + // + this.groupBoxAppointmentSettings.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBoxAppointmentSettings.Controls.Add(this.label2); + this.groupBoxAppointmentSettings.Controls.Add(this.checkBoxIgnoreTentativeAppointments); + this.groupBoxAppointmentSettings.Controls.Add(this.numericUpDownReminderTime); + this.groupBoxAppointmentSettings.Controls.Add(this.labelStartReminderTitle); + this.groupBoxAppointmentSettings.Controls.Add(this.checkBoxIgnoreOutOfOfficeAppointments); + this.groupBoxAppointmentSettings.Controls.Add(this.checkBoxIgnoreFreeAppointments); + this.groupBoxAppointmentSettings.Controls.Add(this.checkBoxIgnoreCancelledAppointments); + this.groupBoxAppointmentSettings.Controls.Add(this.checkBoxIgnoreAllDayAppointments); + this.groupBoxAppointmentSettings.Location = new System.Drawing.Point(12, 241); + this.groupBoxAppointmentSettings.Name = "groupBoxAppointmentSettings"; + this.groupBoxAppointmentSettings.Size = new System.Drawing.Size(560, 166); + this.groupBoxAppointmentSettings.TabIndex = 2; + this.groupBoxAppointmentSettings.TabStop = false; + this.groupBoxAppointmentSettings.Text = "Appointment Settings"; + // + // checkBoxIgnoreTentativeAppointments + // + this.checkBoxIgnoreTentativeAppointments.AutoSize = true; + this.checkBoxIgnoreTentativeAppointments.Location = new System.Drawing.Point(6, 115); + this.checkBoxIgnoreTentativeAppointments.Name = "checkBoxIgnoreTentativeAppointments"; + this.checkBoxIgnoreTentativeAppointments.Size = new System.Drawing.Size(234, 17); + this.checkBoxIgnoreTentativeAppointments.TabIndex = 4; + this.checkBoxIgnoreTentativeAppointments.Text = "Ignore Appointments Marked as \"Tentative\""; + this.checkBoxIgnoreTentativeAppointments.UseVisualStyleBackColor = true; + this.checkBoxIgnoreTentativeAppointments.CheckedChanged += new System.EventHandler(this.checkBoxIgnoreTentativeAppointments_CheckedChanged); + // + // checkBoxIgnoreOutOfOfficeAppointments + // + this.checkBoxIgnoreOutOfOfficeAppointments.AutoSize = true; + this.checkBoxIgnoreOutOfOfficeAppointments.Location = new System.Drawing.Point(6, 91); + this.checkBoxIgnoreOutOfOfficeAppointments.Name = "checkBoxIgnoreOutOfOfficeAppointments"; + this.checkBoxIgnoreOutOfOfficeAppointments.Size = new System.Drawing.Size(249, 17); + this.checkBoxIgnoreOutOfOfficeAppointments.TabIndex = 3; + this.checkBoxIgnoreOutOfOfficeAppointments.Text = "Ignore Appointments Marked as \"Out of Office\""; + this.checkBoxIgnoreOutOfOfficeAppointments.UseVisualStyleBackColor = true; + this.checkBoxIgnoreOutOfOfficeAppointments.CheckedChanged += new System.EventHandler(this.checkBoxIgnoreOutOfOfficeAppointments_CheckedChanged); + // + // checkBoxIgnoreFreeAppointments + // + this.checkBoxIgnoreFreeAppointments.AutoSize = true; + this.checkBoxIgnoreFreeAppointments.Location = new System.Drawing.Point(6, 67); + this.checkBoxIgnoreFreeAppointments.Name = "checkBoxIgnoreFreeAppointments"; + this.checkBoxIgnoreFreeAppointments.Size = new System.Drawing.Size(210, 17); + this.checkBoxIgnoreFreeAppointments.TabIndex = 2; + this.checkBoxIgnoreFreeAppointments.Text = "Ignore Appointments Marked as \"Free\""; + this.checkBoxIgnoreFreeAppointments.UseVisualStyleBackColor = true; + this.checkBoxIgnoreFreeAppointments.CheckedChanged += new System.EventHandler(this.checkBoxIgnoreFreeAppointments_CheckedChanged); + // + // checkBoxIgnoreCancelledAppointments + // + this.checkBoxIgnoreCancelledAppointments.AutoSize = true; + this.checkBoxIgnoreCancelledAppointments.Location = new System.Drawing.Point(6, 43); + this.checkBoxIgnoreCancelledAppointments.Name = "checkBoxIgnoreCancelledAppointments"; + this.checkBoxIgnoreCancelledAppointments.Size = new System.Drawing.Size(173, 17); + this.checkBoxIgnoreCancelledAppointments.TabIndex = 1; + this.checkBoxIgnoreCancelledAppointments.Text = "Ignore Cancelled Appointments"; + this.checkBoxIgnoreCancelledAppointments.UseVisualStyleBackColor = true; + this.checkBoxIgnoreCancelledAppointments.CheckedChanged += new System.EventHandler(this.checkBoxIgnoreCancelledAppointments_CheckedChanged); + // + // checkBoxIgnoreAllDayAppointments + // + this.checkBoxIgnoreAllDayAppointments.AutoSize = true; + this.checkBoxIgnoreAllDayAppointments.Location = new System.Drawing.Point(6, 19); + this.checkBoxIgnoreAllDayAppointments.Name = "checkBoxIgnoreAllDayAppointments"; + this.checkBoxIgnoreAllDayAppointments.Size = new System.Drawing.Size(159, 17); + this.checkBoxIgnoreAllDayAppointments.TabIndex = 0; + this.checkBoxIgnoreAllDayAppointments.Text = "Ignore All-Day Appointments"; + this.checkBoxIgnoreAllDayAppointments.UseVisualStyleBackColor = true; + this.checkBoxIgnoreAllDayAppointments.CheckedChanged += new System.EventHandler(this.checkBoxIgnoreAllDayAppointments_CheckedChanged); + // + // groupBoxClockSettings + // + this.groupBoxClockSettings.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBoxClockSettings.Controls.Add(this.buttonResetDefault); + this.groupBoxClockSettings.Controls.Add(this.label1); + this.groupBoxClockSettings.Controls.Add(this.numericUpDownScrollWait); + this.groupBoxClockSettings.Controls.Add(this.labelScrollWaitTitle); + this.groupBoxClockSettings.Controls.Add(this.labelScrollSpeed); + this.groupBoxClockSettings.Controls.Add(this.labelScrollSpeedTitle); + this.groupBoxClockSettings.Controls.Add(this.trackBarScrollSpeed); + this.groupBoxClockSettings.Controls.Add(this.labelBrightness); + this.groupBoxClockSettings.Controls.Add(this.labelBrightnessTitle); + this.groupBoxClockSettings.Controls.Add(this.trackBarBrightness); + this.groupBoxClockSettings.Controls.Add(this.labelTemperatureIntervalTitleSeconds); + this.groupBoxClockSettings.Controls.Add(this.numericUpDownTemperatureInterval); + this.groupBoxClockSettings.Controls.Add(this.checkBoxTemperatureEnabled); + this.groupBoxClockSettings.Controls.Add(this.labelDateIntervalTitleSeconds); + this.groupBoxClockSettings.Controls.Add(this.numericUpDownDateInterval); + this.groupBoxClockSettings.Controls.Add(this.labelTimeIntervalTitleSeconds); + this.groupBoxClockSettings.Controls.Add(this.numericUpDownTimeInterval); + this.groupBoxClockSettings.Controls.Add(this.labelTimeIntervalTitle); + this.groupBoxClockSettings.Controls.Add(this.checkBoxDateEnabled); + this.groupBoxClockSettings.Enabled = false; + this.groupBoxClockSettings.Location = new System.Drawing.Point(12, 413); + this.groupBoxClockSettings.Name = "groupBoxClockSettings"; + this.groupBoxClockSettings.Size = new System.Drawing.Size(560, 200); + this.groupBoxClockSettings.TabIndex = 3; + this.groupBoxClockSettings.TabStop = false; + this.groupBoxClockSettings.Text = "Clock Settings"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(227, 170); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(49, 13); + this.label1.TabIndex = 18; + this.label1.Text = "Seconds"; + // + // numericUpDownScrollWait + // + this.numericUpDownScrollWait.DecimalPlaces = 1; + this.numericUpDownScrollWait.Location = new System.Drawing.Point(162, 166); + this.numericUpDownScrollWait.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 65536}); + this.numericUpDownScrollWait.Name = "numericUpDownScrollWait"; + this.numericUpDownScrollWait.Size = new System.Drawing.Size(63, 20); + this.numericUpDownScrollWait.TabIndex = 17; + this.numericUpDownScrollWait.Value = new decimal(new int[] { + 4, + 0, + 0, + 0}); + this.numericUpDownScrollWait.ValueChanged += new System.EventHandler(this.numericUpDownScrollWait_ValueChanged); + // + // labelScrollWaitTitle + // + this.labelScrollWaitTitle.AutoSize = true; + this.labelScrollWaitTitle.Location = new System.Drawing.Point(6, 170); + this.labelScrollWaitTitle.Name = "labelScrollWaitTitle"; + this.labelScrollWaitTitle.Size = new System.Drawing.Size(106, 13); + this.labelScrollWaitTitle.TabIndex = 16; + this.labelScrollWaitTitle.Text = "Wait Before Scrolling"; + // + // labelScrollSpeed + // + this.labelScrollSpeed.AutoSize = true; + this.labelScrollSpeed.Location = new System.Drawing.Point(503, 131); + this.labelScrollSpeed.Name = "labelScrollSpeed"; + this.labelScrollSpeed.Size = new System.Drawing.Size(13, 13); + this.labelScrollSpeed.TabIndex = 15; + this.labelScrollSpeed.Text = "5"; + // + // labelScrollSpeedTitle + // + this.labelScrollSpeedTitle.AutoSize = true; + this.labelScrollSpeedTitle.Location = new System.Drawing.Point(6, 131); + this.labelScrollSpeedTitle.Name = "labelScrollSpeedTitle"; + this.labelScrollSpeedTitle.Size = new System.Drawing.Size(67, 13); + this.labelScrollSpeedTitle.TabIndex = 14; + this.labelScrollSpeedTitle.Text = "Scroll Speed"; + // + // trackBarScrollSpeed + // + this.trackBarScrollSpeed.Location = new System.Drawing.Point(162, 126); + this.trackBarScrollSpeed.Maximum = 100; + this.trackBarScrollSpeed.Name = "trackBarScrollSpeed"; + this.trackBarScrollSpeed.Size = new System.Drawing.Size(334, 45); + this.trackBarScrollSpeed.TabIndex = 13; + this.trackBarScrollSpeed.TickFrequency = 5; + this.trackBarScrollSpeed.Value = 5; + this.trackBarScrollSpeed.ValueChanged += new System.EventHandler(this.trackBarScrollSpeed_ValueChanged); + // + // labelBrightness + // + this.labelBrightness.AutoSize = true; + this.labelBrightness.Location = new System.Drawing.Point(503, 93); + this.labelBrightness.Name = "labelBrightness"; + this.labelBrightness.Size = new System.Drawing.Size(19, 13); + this.labelBrightness.TabIndex = 12; + this.labelBrightness.Text = "15"; + // + // labelBrightnessTitle + // + this.labelBrightnessTitle.AutoSize = true; + this.labelBrightnessTitle.Location = new System.Drawing.Point(6, 93); + this.labelBrightnessTitle.Name = "labelBrightnessTitle"; + this.labelBrightnessTitle.Size = new System.Drawing.Size(56, 13); + this.labelBrightnessTitle.TabIndex = 11; + this.labelBrightnessTitle.Text = "Brightness"; + // + // trackBarBrightness + // + this.trackBarBrightness.Location = new System.Drawing.Point(162, 88); + this.trackBarBrightness.Maximum = 15; + this.trackBarBrightness.Minimum = 1; + this.trackBarBrightness.Name = "trackBarBrightness"; + this.trackBarBrightness.Size = new System.Drawing.Size(334, 45); + this.trackBarBrightness.TabIndex = 10; + this.trackBarBrightness.Value = 15; + this.trackBarBrightness.ValueChanged += new System.EventHandler(this.trackBarBrightness_ValueChanged); + // + // labelTemperatureIntervalTitleSeconds + // + this.labelTemperatureIntervalTitleSeconds.AutoSize = true; + this.labelTemperatureIntervalTitleSeconds.Location = new System.Drawing.Point(227, 68); + this.labelTemperatureIntervalTitleSeconds.Name = "labelTemperatureIntervalTitleSeconds"; + this.labelTemperatureIntervalTitleSeconds.Size = new System.Drawing.Size(49, 13); + this.labelTemperatureIntervalTitleSeconds.TabIndex = 9; + this.labelTemperatureIntervalTitleSeconds.Text = "Seconds"; + // + // numericUpDownTemperatureInterval + // + this.numericUpDownTemperatureInterval.Location = new System.Drawing.Point(162, 64); + this.numericUpDownTemperatureInterval.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.numericUpDownTemperatureInterval.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDownTemperatureInterval.Name = "numericUpDownTemperatureInterval"; + this.numericUpDownTemperatureInterval.Size = new System.Drawing.Size(63, 20); + this.numericUpDownTemperatureInterval.TabIndex = 8; + this.numericUpDownTemperatureInterval.Value = new decimal(new int[] { + 3, + 0, + 0, + 0}); + this.numericUpDownTemperatureInterval.ValueChanged += new System.EventHandler(this.numericUpDownTemperatureInterval_ValueChanged); + // + // checkBoxTemperatureEnabled + // + this.checkBoxTemperatureEnabled.AutoSize = true; + this.checkBoxTemperatureEnabled.Location = new System.Drawing.Point(6, 66); + this.checkBoxTemperatureEnabled.Name = "checkBoxTemperatureEnabled"; + this.checkBoxTemperatureEnabled.Size = new System.Drawing.Size(149, 17); + this.checkBoxTemperatureEnabled.TabIndex = 7; + this.checkBoxTemperatureEnabled.Text = "Show the Temperature for"; + this.checkBoxTemperatureEnabled.UseVisualStyleBackColor = true; + this.checkBoxTemperatureEnabled.CheckedChanged += new System.EventHandler(this.checkBoxTemperatureEnabled_CheckedChanged); + // + // labelDateIntervalTitleSeconds + // + this.labelDateIntervalTitleSeconds.AutoSize = true; + this.labelDateIntervalTitleSeconds.Location = new System.Drawing.Point(227, 45); + this.labelDateIntervalTitleSeconds.Name = "labelDateIntervalTitleSeconds"; + this.labelDateIntervalTitleSeconds.Size = new System.Drawing.Size(49, 13); + this.labelDateIntervalTitleSeconds.TabIndex = 6; + this.labelDateIntervalTitleSeconds.Text = "Seconds"; + // + // numericUpDownDateInterval + // + this.numericUpDownDateInterval.Location = new System.Drawing.Point(162, 41); + this.numericUpDownDateInterval.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.numericUpDownDateInterval.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDownDateInterval.Name = "numericUpDownDateInterval"; + this.numericUpDownDateInterval.Size = new System.Drawing.Size(63, 20); + this.numericUpDownDateInterval.TabIndex = 5; + this.numericUpDownDateInterval.Value = new decimal(new int[] { + 3, + 0, + 0, + 0}); + this.numericUpDownDateInterval.ValueChanged += new System.EventHandler(this.numericUpDownDateInterval_ValueChanged); + // + // labelTimeIntervalTitleSeconds + // + this.labelTimeIntervalTitleSeconds.AutoSize = true; + this.labelTimeIntervalTitleSeconds.Location = new System.Drawing.Point(227, 22); + this.labelTimeIntervalTitleSeconds.Name = "labelTimeIntervalTitleSeconds"; + this.labelTimeIntervalTitleSeconds.Size = new System.Drawing.Size(49, 13); + this.labelTimeIntervalTitleSeconds.TabIndex = 4; + this.labelTimeIntervalTitleSeconds.Text = "Seconds"; + // + // numericUpDownTimeInterval + // + this.numericUpDownTimeInterval.Location = new System.Drawing.Point(162, 18); + this.numericUpDownTimeInterval.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.numericUpDownTimeInterval.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDownTimeInterval.Name = "numericUpDownTimeInterval"; + this.numericUpDownTimeInterval.Size = new System.Drawing.Size(63, 20); + this.numericUpDownTimeInterval.TabIndex = 3; + this.numericUpDownTimeInterval.Value = new decimal(new int[] { + 35, + 0, + 0, + 0}); + this.numericUpDownTimeInterval.ValueChanged += new System.EventHandler(this.numericUpDownTimeInterval_ValueChanged); + // + // labelTimeIntervalTitle + // + this.labelTimeIntervalTitle.AutoSize = true; + this.labelTimeIntervalTitle.Location = new System.Drawing.Point(6, 22); + this.labelTimeIntervalTitle.Name = "labelTimeIntervalTitle"; + this.labelTimeIntervalTitle.Size = new System.Drawing.Size(93, 13); + this.labelTimeIntervalTitle.TabIndex = 2; + this.labelTimeIntervalTitle.Text = "Show the Time for"; + // + // checkBoxDateEnabled + // + this.checkBoxDateEnabled.AutoSize = true; + this.checkBoxDateEnabled.Location = new System.Drawing.Point(6, 43); + this.checkBoxDateEnabled.Name = "checkBoxDateEnabled"; + this.checkBoxDateEnabled.Size = new System.Drawing.Size(112, 17); + this.checkBoxDateEnabled.TabIndex = 1; + this.checkBoxDateEnabled.Text = "Show the Date for"; + this.checkBoxDateEnabled.UseVisualStyleBackColor = true; + this.checkBoxDateEnabled.CheckedChanged += new System.EventHandler(this.checkBoxDateEnabled_CheckedChanged); + // + // timerScrollDemo + // + this.timerScrollDemo.Interval = 10000; + this.timerScrollDemo.Tick += new System.EventHandler(this.timerScrollDemo_Tick); + // + // buttonResetDefault + // + this.buttonResetDefault.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.buttonResetDefault.Location = new System.Drawing.Point(392, 18); + this.buttonResetDefault.Name = "buttonResetDefault"; + this.buttonResetDefault.Size = new System.Drawing.Size(162, 43); + this.buttonResetDefault.TabIndex = 19; + this.buttonResetDefault.Text = "Reset All to Default"; + this.buttonResetDefault.UseVisualStyleBackColor = true; + this.buttonResetDefault.Click += new System.EventHandler(this.buttonResetDefault_Click); + // + // timerAdjustClock + // + this.timerAdjustClock.Enabled = true; + this.timerAdjustClock.Interval = 7200000; + this.timerAdjustClock.Tick += new System.EventHandler(this.timerAdjustClock_Tick); + // + // timerGetAppointment + // + this.timerGetAppointment.Enabled = true; + this.timerGetAppointment.Interval = 60000; + this.timerGetAppointment.Tick += new System.EventHandler(this.timerGetAppointment_Tick); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(227, 142); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(188, 13); + this.label2.TabIndex = 22; + this.label2.Text = "Minutes Before the Appointment Starts"; + // + // numericUpDownReminderTime + // + this.numericUpDownReminderTime.Location = new System.Drawing.Point(162, 138); + this.numericUpDownReminderTime.Maximum = new decimal(new int[] { + 60, + 0, + 0, + 0}); + this.numericUpDownReminderTime.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDownReminderTime.Name = "numericUpDownReminderTime"; + this.numericUpDownReminderTime.Size = new System.Drawing.Size(63, 20); + this.numericUpDownReminderTime.TabIndex = 21; + this.numericUpDownReminderTime.Value = new decimal(new int[] { + 10, + 0, + 0, + 0}); + this.numericUpDownReminderTime.ValueChanged += new System.EventHandler(this.numericUpDownReminderTime_ValueChanged); + // + // labelStartReminderTitle + // + this.labelStartReminderTitle.AutoSize = true; + this.labelStartReminderTitle.Location = new System.Drawing.Point(6, 142); + this.labelStartReminderTitle.Name = "labelStartReminderTitle"; + this.labelStartReminderTitle.Size = new System.Drawing.Size(149, 13); + this.labelStartReminderTitle.TabIndex = 20; + this.labelStartReminderTitle.Text = "Show Appointment Reminders"; + // + // MainWindow + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(584, 641); + this.Controls.Add(this.groupBoxClockSettings); + this.Controls.Add(this.groupBoxAppointmentSettings); + this.Controls.Add(this.groupBoxApplicationSettings); + this.Controls.Add(this.groupBoxState); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MaximumSize = new System.Drawing.Size(800, 800); + this.MinimumSize = new System.Drawing.Size(600, 680); + this.Name = "MainWindow"; + this.Text = "Meeting Clock"; + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.MainWindow_FormClosed); + this.Load += new System.EventHandler(this.MainWindow_Load); + this.Resize += new System.EventHandler(this.MainWindow_Resize); + this.groupBoxState.ResumeLayout(false); + this.groupBoxState.PerformLayout(); + this.groupBoxApplicationSettings.ResumeLayout(false); + this.groupBoxApplicationSettings.PerformLayout(); + this.groupBoxAppointmentSettings.ResumeLayout(false); + this.groupBoxAppointmentSettings.PerformLayout(); + this.groupBoxClockSettings.ResumeLayout(false); + this.groupBoxClockSettings.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDownScrollWait)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.trackBarScrollSpeed)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.trackBarBrightness)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDownTemperatureInterval)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDownDateInterval)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDownTimeInterval)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDownReminderTime)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBoxState; + private System.Windows.Forms.Label labelBluetoothState; + private System.Windows.Forms.Label labelBluetoothStateTitle; + private System.Windows.Forms.Button buttonOpenSystemSettingsPrivacy; + private System.Windows.Forms.Button buttonEnableBluetooth; + private System.Windows.Forms.Label labelMeetingClockState; + private System.Windows.Forms.Label labelMeetingClockStateTitle; + private System.Windows.Forms.Button buttonOpenSystemSettingsBluetooth; + private System.Windows.Forms.Button buttonWebsite; + private System.Windows.Forms.GroupBox groupBoxApplicationSettings; + private System.Windows.Forms.CheckBox checkBoxEnableBluetooth; + private System.Windows.Forms.CheckBox checkBoxCheckForUpdates; + private System.Windows.Forms.CheckBox checkBoxStartMinimized; + private System.Windows.Forms.CheckBox checkBoxAutostart; + private System.Windows.Forms.NotifyIcon notifyIcon; + private System.Windows.Forms.Timer timerEnableBalloon; + private System.Windows.Forms.GroupBox groupBoxAppointmentSettings; + private System.Windows.Forms.CheckBox checkBoxIgnoreAllDayAppointments; + private System.Windows.Forms.CheckBox checkBoxIgnoreCancelledAppointments; + private System.Windows.Forms.CheckBox checkBoxIgnoreFreeAppointments; + private System.Windows.Forms.CheckBox checkBoxIgnoreOutOfOfficeAppointments; + private System.Windows.Forms.CheckBox checkBoxIgnoreTentativeAppointments; + private System.Windows.Forms.GroupBox groupBoxClockSettings; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.NumericUpDown numericUpDownScrollWait; + private System.Windows.Forms.Label labelScrollWaitTitle; + private System.Windows.Forms.Label labelScrollSpeed; + private System.Windows.Forms.Label labelScrollSpeedTitle; + private System.Windows.Forms.TrackBar trackBarScrollSpeed; + private System.Windows.Forms.Label labelBrightness; + private System.Windows.Forms.Label labelBrightnessTitle; + private System.Windows.Forms.TrackBar trackBarBrightness; + private System.Windows.Forms.Label labelTemperatureIntervalTitleSeconds; + private System.Windows.Forms.NumericUpDown numericUpDownTemperatureInterval; + private System.Windows.Forms.CheckBox checkBoxTemperatureEnabled; + private System.Windows.Forms.Label labelDateIntervalTitleSeconds; + private System.Windows.Forms.NumericUpDown numericUpDownDateInterval; + private System.Windows.Forms.Label labelTimeIntervalTitleSeconds; + private System.Windows.Forms.NumericUpDown numericUpDownTimeInterval; + private System.Windows.Forms.Label labelTimeIntervalTitle; + private System.Windows.Forms.CheckBox checkBoxDateEnabled; + private System.Windows.Forms.Timer timerScrollDemo; + private System.Windows.Forms.Button buttonResetDefault; + private System.Windows.Forms.Timer timerAdjustClock; + private System.Windows.Forms.Timer timerGetAppointment; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.NumericUpDown numericUpDownReminderTime; + private System.Windows.Forms.Label labelStartReminderTitle; + } +} \ No newline at end of file diff --git a/MainWindow.cs b/MainWindow.cs new file mode 100644 index 0000000..ea0c528 --- /dev/null +++ b/MainWindow.cs @@ -0,0 +1,563 @@ +using System; +using System.Diagnostics; +using System.Drawing; +using System.Net.Http; +using System.Windows.Forms; +using Outlook = Microsoft.Office.Interop.Outlook; + +namespace MeetingClock +{ + public partial class MainWindow : Form + { + private readonly string LINK_URL = "https://zechert.net/meeting-clock"; + private readonly string LINK_URL_UPDATE = "https://zechert.net/meeting-clock/update.txt"; + + private BluetoothManager bluetoothManager; + private MeetingClockManager meetingClockManager; + private readonly HttpClient client = new HttpClient(); + private string clockVersion = null; + private Settings settings = new Settings(); + private bool showBalloon = false; + private OutlookManager outlookManager = new OutlookManager(); + private bool clockSettingsCanBeChanged; + private string currentAppointment = ""; + + public MainWindow() + { + InitializeComponent(); + this.Text += " - " + Properties.Settings.Default.Version; + } + + private async void MainWindow_Load(object sender, System.EventArgs e) + { + this.clockSettingsCanBeChanged = false; + this.checkBoxAutostart.Checked = this.settings.Autostart; + this.checkBoxStartMinimized.Checked = this.settings.StartMinimized; + this.checkBoxCheckForUpdates.Checked = this.settings.CheckForUpdates; + this.checkBoxEnableBluetooth.Checked = this.settings.StartBluetooth; + this.checkBoxIgnoreAllDayAppointments.Checked = this.settings.IgnoreAllDayAppointments; + this.checkBoxIgnoreCancelledAppointments.Checked = this.settings.IgnoreCancelledAppointments; + this.checkBoxIgnoreFreeAppointments.Checked = this.settings.IgnoreFreeAppointments; + this.checkBoxIgnoreOutOfOfficeAppointments.Checked = this.settings.IgnoreOutOfOfficeAppointments; + this.checkBoxIgnoreTentativeAppointments.Checked = this.settings.IgnoreTentativeAppointments; + this.numericUpDownReminderTime.Value = this.settings.ReminderTime; + + if (this.settings.StartMinimized) + { + this.WindowState = FormWindowState.Minimized; + } + + if (this.settings.CheckForUpdates) + { + this.CheckForUpdate(); + } + + this.bluetoothManager = new BluetoothManager(); + this.bluetoothManager.StateChanged += BluetoothManager_StateChanged; + + this.meetingClockManager = new MeetingClockManager(bluetoothManager); + this.meetingClockManager.StateChanged += MeetingClockManager_StateChanged; + + await this.bluetoothManager.Initialize(); + + if (this.settings.StartBluetooth && this.bluetoothManager.State != BluetoothManager.BluetoothState.On) + { + await this.bluetoothManager.Enable(); + } + } + + private void UpdateBluetoothState() + { + switch (this.bluetoothManager.State) + { + case BluetoothManager.BluetoothState.NotInitialized: + this.labelBluetoothState.Text = "not initialized"; + this.labelBluetoothState.ForeColor = SystemColors.ControlText; + this.UpdateIcon(Properties.Resources.icon_neutral); + this.buttonEnableBluetooth.Enabled = false; + break; + case BluetoothManager.BluetoothState.Exception: + this.labelBluetoothState.Text = "system exception"; + this.labelBluetoothState.ForeColor = Color.Red; + this.UpdateIcon(Properties.Resources.icon_error); + this.buttonEnableBluetooth.Enabled = false; + ShowArchitectureWarning(); + break; + case BluetoothManager.BluetoothState.NoBluetoothAdapter: + this.labelBluetoothState.Text = "no bluetooth adapter found"; + this.labelBluetoothState.ForeColor = Color.Red; + this.UpdateIcon(Properties.Resources.icon_error); + this.buttonEnableBluetooth.Enabled = false; + break; + case BluetoothManager.BluetoothState.NoBluetoothRadio: + this.labelBluetoothState.Text = "no bluetooth radio found"; + this.labelBluetoothState.ForeColor = Color.Red; + this.UpdateIcon(Properties.Resources.icon_error); + this.buttonEnableBluetooth.Enabled = false; + break; + case BluetoothManager.BluetoothState.Disabled: + this.labelBluetoothState.Text = "disabled"; + this.labelBluetoothState.ForeColor = SystemColors.ControlText; + this.UpdateIcon(Properties.Resources.icon_warning); + this.buttonEnableBluetooth.Enabled = true; + break; + case BluetoothManager.BluetoothState.Off: + this.labelBluetoothState.Text = "off"; + this.labelBluetoothState.ForeColor = Color.DarkOrange; + this.UpdateIcon(Properties.Resources.icon_warning); + this.buttonEnableBluetooth.Enabled = true; + break; + case BluetoothManager.BluetoothState.On: + this.labelBluetoothState.Text = "on"; + this.UpdateIcon(Properties.Resources.icon_neutral); + this.labelBluetoothState.ForeColor = Color.Green; + this.buttonEnableBluetooth.Enabled = false; + break; + case BluetoothManager.BluetoothState.Unknown: + this.labelBluetoothState.Text = "unknown"; + this.UpdateIcon(Properties.Resources.icon_off); + this.labelBluetoothState.ForeColor = SystemColors.ControlText; + this.buttonEnableBluetooth.Enabled = false; + break; + } + } + + private void BluetoothManager_StateChanged(BluetoothManager manager, BluetoothManager.BluetoothState oldState, BluetoothManager.BluetoothState newState) + { + this.BeginInvoke((Action) (() => { this.UpdateBluetoothState(); })); + } + + private void UpdateMeetingClockState() + { + this.clockSettingsCanBeChanged = false; + switch (this.meetingClockManager.State) + { + case MeetingClockManager.MeetingClockState.NotInitialized: + this.labelMeetingClockState.Text = "not initialized"; + this.labelMeetingClockState.ForeColor = SystemColors.ControlText; + this.UpdateIcon(Properties.Resources.icon_neutral); + this.groupBoxClockSettings.Enabled = false; + break; + case MeetingClockManager.MeetingClockState.NoComPort: + if (this.bluetoothManager.State == BluetoothManager.BluetoothState.On) + { + this.labelMeetingClockState.Text = "not paired"; + } + else + { + this.labelMeetingClockState.Text = "bluetooth disabled"; + } + this.labelMeetingClockState.ForeColor = Color.Red; + this.UpdateIcon(Properties.Resources.icon_error); + this.groupBoxClockSettings.Enabled = false; + break; + case MeetingClockManager.MeetingClockState.Disconnected: + this.labelMeetingClockState.Text = "not connected"; + this.labelMeetingClockState.ForeColor = Color.DarkOrange; + this.UpdateIcon(Properties.Resources.icon_neutral); + this.groupBoxClockSettings.Enabled = false; + break; + case MeetingClockManager.MeetingClockState.Connected: + this.labelMeetingClockState.Text = "connected on " + this.meetingClockManager.Port + ", " + this.meetingClockManager.Version; + this.labelMeetingClockState.ForeColor = Color.Green; + this.UpdateIcon(Properties.Resources.icon_ok); + if (this.clockVersion != null && this.meetingClockManager.Version != this.clockVersion) + { + DialogResult result = MessageBox.Show("A new version of the meeting clock firmware is available.\n\n" + + "Do you want to open " + LINK_URL + " to download the new version now?", "New Firmware Available", MessageBoxButtons.YesNo, MessageBoxIcon.Information); + if (result == DialogResult.Yes) + { + System.Diagnostics.Process.Start(LINK_URL); + } + } + this.groupBoxClockSettings.Enabled = true; + this.ReadClockSettings(); + this.ShowNextAppointment(); + break; + } + } + + private void MeetingClockManager_StateChanged(MeetingClockManager manager, MeetingClockManager.MeetingClockState oldState, MeetingClockManager.MeetingClockState newState) + { + this.BeginInvoke((Action)(() => { this.UpdateMeetingClockState(); })); + } + + private void ShowArchitectureWarning() + { + String computerArchitecture = Environment.Is64BitOperatingSystem ? "x64" : "x86"; + String programArchitecture = Environment.Is64BitProcess ? "x64" : "x86"; + + String message = "" + + "This application cannot access the Bluetooth device on your computer. " + + "This is normally a sign that you downloaded the wrong architecture (x64, x86) of this application.\n" + + "\n" + + "Your computer uses " + computerArchitecture + " architecture.\n" + + "This application is " + programArchitecture + " architecture.\n" + + "\n" + + "This application will only work on Windows 10.\n\n" + + "Please download the correct version of this application from " + LINK_URL + ".\n" + + "\n" + + "This application will now exit!\n" + + "\n" + + "Do you want to open " + LINK_URL + " now?"; + + DialogResult result = MessageBox.Show(message, "Bluetooth Error", MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1); + if (result == DialogResult.Yes) + { + System.Diagnostics.Process.Start(LINK_URL); + } + + Application.Exit(); + } + + private void ButtonOpenSystemSettingsPrivacy_Click(object sender, EventArgs e) + { + System.Diagnostics.Process.Start("ms-settings:privacy-radios"); + } + + private void buttonOpenSystemSettingsBluetooth_Click(object sender, EventArgs e) + { + System.Diagnostics.Process.Start("ms-settings:bluetooth"); + } + + private void buttonWebsite_Click(object sender, EventArgs e) + { + System.Diagnostics.Process.Start(LINK_URL); + } + + private async void ButtonEnableBluetooth_Click(object sender, EventArgs e) + { + Windows.Devices.Radios.RadioAccessStatus result = await this.bluetoothManager.Enable(); + DialogResult open = DialogResult.Cancel; + String openLink = ""; + + switch (result) + { + case Windows.Devices.Radios.RadioAccessStatus.DeniedBySystem: + open = MessageBox.Show( + "The operating system denied access to the bluetooth radio. Please enable bluetooth yourself.\n\nDo you want to open bluetooth settings now?", + "Access denied", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1); + openLink = "ms-settings:bluetooth"; + break; + case Windows.Devices.Radios.RadioAccessStatus.DeniedByUser: + open = MessageBox.Show( + "Switching the bluetooth state automatically is forbidden by your privacy settings.\n\nDo you want to open privacy settings now?", + "Access denied", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1); + openLink = "ms-settings:privacy-radios"; + break; + case Windows.Devices.Radios.RadioAccessStatus.Unspecified: + open = MessageBox.Show( + "Switching the bluetooth state failed for an unknown reason. Please enable bluetooth yourself.\n\nDo you want to open bluetooth settings now?", + "Access denied", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1); + openLink = "ms-settings:bluetooth"; + break; + } + + if (open == DialogResult.Yes) + { + System.Diagnostics.Process.Start(openLink); + } + } + + private void UpdateIcon(Icon newIcon) + { + this.Icon = newIcon; + this.notifyIcon.Icon = newIcon; + } + + private async void CheckForUpdate() + { + HttpResponseMessage response = await this.client.GetAsync(LINK_URL_UPDATE); + if (response.StatusCode == System.Net.HttpStatusCode.OK) + { + string responseBody = await response.Content.ReadAsStringAsync(); + string[] versions = responseBody.Split('\n'); + Debug.WriteLine(String.Format("Versions available:\n{0}", responseBody)); + + if (versions.Length >= 2) + { + string winVersion = versions[0].Trim(); + this.clockVersion = versions[1].Trim(); + + if (winVersion != Properties.Settings.Default.Version) + { + DialogResult result = MessageBox.Show("A new version of this software is available.\n\n" + + "Do you want to open " + LINK_URL + " to download the new version now?", "New Version Available", MessageBoxButtons.YesNo, MessageBoxIcon.Information); + if (result == DialogResult.Yes) + { + System.Diagnostics.Process.Start(LINK_URL); + } + } + } + } else + { + Debug.WriteLine(String.Format("Check for update failed: {0}", response.StatusCode)); + } + } + + private void MainWindow_FormClosed(object sender, FormClosedEventArgs e) + { + Debug.WriteLine(String.Format("Form was closed because of {0}", e.CloseReason.ToString())); + this.bluetoothManager.Stop(); + this.meetingClockManager.Stop(); + } + + private void checkBoxAutostart_CheckedChanged(object sender, EventArgs e) + { + this.settings.Autostart = this.checkBoxAutostart.Checked; + } + + private void checkBoxStartMinimized_CheckedChanged(object sender, EventArgs e) + { + this.settings.StartMinimized = this.checkBoxStartMinimized.Checked; + } + + private void checkBoxCheckForUpdates_CheckedChanged(object sender, EventArgs e) + { + this.settings.CheckForUpdates = this.checkBoxCheckForUpdates.Checked; + } + + private void checkBoxEnableBluetooth_CheckedChanged(object sender, EventArgs e) + { + this.settings.StartBluetooth = this.checkBoxEnableBluetooth.Checked; + } + + private void MainWindow_Resize(object sender, EventArgs e) + { + if (this.WindowState == FormWindowState.Minimized) + { + if (this.showBalloon) + { + this.notifyIcon.ShowBalloonTip(3000); + } + this.ShowInTaskbar = false; + this.FormBorderStyle = FormBorderStyle.SizableToolWindow; + } + } + + private void NotifyIcon_MouseDoubleClick(object sender, MouseEventArgs e) + { + this.FormBorderStyle = FormBorderStyle.Sizable; + this.WindowState = FormWindowState.Normal; + this.ShowInTaskbar = true; + } + + private void timerEnableBalloon_Tick(object sender, EventArgs e) + { + this.showBalloon = true; + this.timerEnableBalloon.Stop(); + } + + private void checkBoxIgnoreAllDayAppointments_CheckedChanged(object sender, EventArgs e) + { + this.settings.IgnoreAllDayAppointments = this.checkBoxIgnoreAllDayAppointments.Checked; + } + + private void checkBoxIgnoreCancelledAppointments_CheckedChanged(object sender, EventArgs e) + { + this.settings.IgnoreCancelledAppointments = this.checkBoxIgnoreCancelledAppointments.Checked; + } + + private void checkBoxIgnoreFreeAppointments_CheckedChanged(object sender, EventArgs e) + { + this.settings.IgnoreFreeAppointments = this.checkBoxIgnoreFreeAppointments.Checked; + } + + private void checkBoxIgnoreOutOfOfficeAppointments_CheckedChanged(object sender, EventArgs e) + { + this.settings.IgnoreOutOfOfficeAppointments = this.checkBoxIgnoreOutOfOfficeAppointments.Checked; + } + + private void checkBoxIgnoreTentativeAppointments_CheckedChanged(object sender, EventArgs e) + { + this.settings.IgnoreTentativeAppointments = this.checkBoxIgnoreTentativeAppointments.Checked; + } + + private void ReadClockSettings() + { + this.numericUpDownTimeInterval.Value = this.meetingClockManager.GetTimeInterval() ?? this.numericUpDownTimeInterval.Value; + this.numericUpDownDateInterval.Value = this.meetingClockManager.GetDateInterval() ?? this.numericUpDownDateInterval.Value; + this.numericUpDownTemperatureInterval.Value = this.meetingClockManager.GetTemperatureInterval() ?? this.numericUpDownTemperatureInterval.Value; + + this.trackBarBrightness.Value = this.meetingClockManager.GetBrightness() ?? this.trackBarBrightness.Value; + this.labelBrightness.Text = this.trackBarBrightness.Value.ToString(); + + this.trackBarScrollSpeed.Value = this.meetingClockManager.GetScrollSpeed() ?? this.trackBarScrollSpeed.Value; + this.labelScrollSpeed.Text = this.trackBarScrollSpeed.Value.ToString(); + + this.numericUpDownScrollWait.Value = (this.meetingClockManager.GetScrollWait() / 10) ?? this.numericUpDownScrollWait.Value; + + this.checkBoxDateEnabled.Checked = this.meetingClockManager.GetDateEnabled() ?? this.checkBoxDateEnabled.Checked; + this.checkBoxTemperatureEnabled.Checked = this.meetingClockManager.GetTemperatureEnabled() ?? this.checkBoxTemperatureEnabled.Checked; + + this.clockSettingsCanBeChanged = true; + } + + private void trackBarBrightness_ValueChanged(object sender, EventArgs e) + { + this.labelBrightness.Text = trackBarBrightness.Value.ToString(); + if (this.clockSettingsCanBeChanged) + { + this.meetingClockManager.SetBrightness(trackBarBrightness.Value); + } + } + + private void trackBarScrollSpeed_ValueChanged(object sender, EventArgs e) + { + this.labelScrollSpeed.Text = trackBarScrollSpeed.Value.ToString(); + if (this.clockSettingsCanBeChanged) + { + this.meetingClockManager.SetScrollSpeed(trackBarScrollSpeed.Value); + this.StartScrollDemo(); + } + } + + private void numericUpDownScrollWait_ValueChanged(object sender, EventArgs e) + { + if (this.clockSettingsCanBeChanged) + { + this.meetingClockManager.SetScrollWait((int)(this.numericUpDownScrollWait.Value * 10)); + this.StartScrollDemo(); + } + } + + private void StartScrollDemo() + { + if (this.timerScrollDemo.Enabled) + { + this.timerScrollDemo.Stop(); + } + else + { + this.meetingClockManager.ScrollText("Beispiel-Text"); + } + + this.timerScrollDemo.Start(); + } + + private void timerScrollDemo_Tick(object sender, EventArgs e) + { + this.meetingClockManager.ScrollText(""); + timerScrollDemo.Stop(); + } + + private void numericUpDownTimeInterval_ValueChanged(object sender, EventArgs e) + { + if (this.clockSettingsCanBeChanged) + { + this.meetingClockManager.SetTimeInterval((int)(this.numericUpDownTimeInterval.Value)); + } + } + + private void numericUpDownDateInterval_ValueChanged(object sender, EventArgs e) + { + if (this.clockSettingsCanBeChanged) + { + this.meetingClockManager.SetDateInterval((int)(this.numericUpDownDateInterval.Value)); + } + } + + private void numericUpDownTemperatureInterval_ValueChanged(object sender, EventArgs e) + { + if (this.clockSettingsCanBeChanged) + { + this.meetingClockManager.SetTemperatureInterval((int)(this.numericUpDownTemperatureInterval.Value)); + } + } + + private void checkBoxDateEnabled_CheckedChanged(object sender, EventArgs e) + { + if (this.clockSettingsCanBeChanged) + { + this.meetingClockManager.SetDateEnabled(this.checkBoxDateEnabled.Checked); + } + } + + private void checkBoxTemperatureEnabled_CheckedChanged(object sender, EventArgs e) + { + if (this.clockSettingsCanBeChanged) + { + this.meetingClockManager.SetTemperatureEnabled(this.checkBoxTemperatureEnabled.Checked); + } + } + + private void buttonResetDefault_Click(object sender, EventArgs e) + { + DialogResult dialogResult = MessageBox.Show("Are you sure? All clock settings will be reset to their default values!", "Confirm Reset", + MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2); + + if (dialogResult == DialogResult.Yes) + { + this.clockSettingsCanBeChanged = false; + this.meetingClockManager.SetBrightness(15); + this.meetingClockManager.SetTimeInterval(35); + this.meetingClockManager.SetDateInterval(3); + this.meetingClockManager.SetDateEnabled(true); + this.meetingClockManager.SetDateInterval(3); + this.meetingClockManager.SetTemperatureEnabled(true); + this.meetingClockManager.SetTemperatureInterval(3); + this.meetingClockManager.SetScrollSpeed(5); + this.meetingClockManager.SetScrollWait(40); + + this.ReadClockSettings(); + } + } + + private void timerAdjustClock_Tick(object sender, EventArgs e) + { + if (this.clockSettingsCanBeChanged) + { + this.meetingClockManager.Adjust(); + } + } + + private void timerGetAppointment_Tick(object sender, EventArgs e) + { + this.ShowNextAppointment(); + } + + private async void ShowNextAppointment() { + if (!this.clockSettingsCanBeChanged) + { + this.currentAppointment = ""; + return; + } + + + Outlook.AppointmentItem appointment = await this.outlookManager.GetNextAppointment( + this.settings.IgnoreAllDayAppointments, this.settings.IgnoreCancelledAppointments, this.settings.IgnoreFreeAppointments, + this.settings.IgnoreOutOfOfficeAppointments, this.settings.IgnoreTentativeAppointments); + + if (appointment == null) + { + Debug.WriteLine("No upcoming appointment send to clock"); + this.currentAppointment = ""; + return; + } + + string appointmentName = String.Format("{0} - {1} {2}", appointment.Start.ToString("t"), appointment.End.ToString("t"), appointment.Subject); + if (appointment.Start > DateTime.Now.AddMinutes(this.settings.ReminderTime)) + { + Debug.WriteLine(String.Format("Upcoming appointment is too far in future, not displaying: {0}", appointmentName)); + this.currentAppointment = ""; + return; + } + + if (this.currentAppointment == appointmentName) + { + Debug.WriteLine("Current appointment is already displayed, not doing anything"); + return; + } + + this.currentAppointment = appointmentName; + this.meetingClockManager.ScrollText(this.currentAppointment); + this.meetingClockManager.NextDate(appointment.Start); + Debug.WriteLine(String.Format("Current appointment is set to: {0}", this.currentAppointment)); + } + + private void numericUpDownReminderTime_ValueChanged(object sender, EventArgs e) + { + this.settings.ReminderTime = (int)this.numericUpDownReminderTime.Value; + } + } +} diff --git a/MainWindow.resx b/MainWindow.resx new file mode 100644 index 0000000..37e890b --- /dev/null +++ b/MainWindow.resx @@ -0,0 +1,372 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + AAABAAIAQEAAAAEACAAoFgAAJgAAAEBAAgABAAEAMAQAAE4WAAAoAAAAQAAAAIAAAAABAAgAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/38AAP+ADQD/gyYA/4QqAP+HOAD/iDsA/4pAAP+KQgD/i0UA/4xHAP+P + TwD/kFEA/5FVAP+TWgD/lV8A/5djAP+YZQD/mWgA/51uAP+ecQD/n3MA/6F3AP+ieAD/onkA/6N6AP+l + fgD/pn8A/6aAAP+ngQD/p4IA/6yJAP+tiwD/ro0A/6+PAP+wkAD/sJEA/7GTAP+0lwD/tZgA/7WZAP+5 + nwD/uqAA/7yjAP+8pAD/vqcA/7+nAP/BqgD/x7QA/8i2AP/JtgD/zbwA/829AP/OvgD/0MAA/9HCAP/S + wwD/0sQA/9PFAP/UxgD/1McA/9XIAP/YywD/2c4A/9vQAP/c0QD/3dIA/9/VAP/f1gD/4toA/+TcAP/l + 3QD/5+AA/+jiAP/p4gD/6eMA/+3oAP/u6QD/7+sA//HtAP/x7gD/8u8A//PvAP/08AD/9PEA//XyAP/1 + 8wD/+PYA//n3AP/5+AD/+/oA//z7AP/9/AD//v0A//7+AP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU0snAQAAAAAAAAAAHF1A + EgAAAAAAAAAAADpWMQYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFNeXk0eAAAAAAAA + ABxeXl1CCgAAAAAAAAA6Xl5XLwAAAAAAAAAPOU1ZXl5eXl5bVEMgAAAAAAAAAAAAAAAAAABTXl5eOgAA + AAAAAAAcXl5eXhwAAAAAAAAAOl5eXlMAAAAAAAAhWV5eXl5eXl5eXl5eXjkAAAAAAAAAAAAAAAAAU15e + XjoAAAAAAAAAHF5eXl4cAAAAAAAAADpeXl5TAAAAAAALWF5eXl5eXl5eXl5eXl5eKAAAAAAAAAAAAAAA + AFNeXl46AAAAAAAAABxeXl5eHAAAAAAAAAA6Xl5eUwAAAAAAMF5eXl5eXl5eXl5eXl5eXksAAAAAAAAA + AAAAAABTXl5eOgAAAAAAAAAcXl5eXhwAAAAAAAAAOl5eXlMAAAAAAEVeXl5dMycmJiYmLVNeXl5eCAAA + AAAAAAAAAAAAU15eXjoAAAAAAAAAHF5eXl4cAAAAAAAAADpeXl5TAAAAAABNXl5eRAAAAAAAAAApXl5e + XhMAAAAAAAAAAAAAAFNeXl46AAAAAAAAABxeXl5eHAAAAAAAAAA6Xl5eUwAAAAAAUl5eXjsAAAAAAAAA + HV5eXl4bAAAAAAAAAAAAAABTXl5eOgAAAAAAAAAcXl5eXhwAAAAAAAAAOl5eXlMAAAAAAFNeXl46AAAA + AAAAABxeXl5eHAAAAAAAAAAAAAAAU15eXjoAAAAAAAAAHF5eXl4cAAAAAAAAADpeXl5TAAAAAABTXl5e + OgAAAAAAAAAOS15eXhwAAAAAAAAAAAAAAFNeXl46AAAAAAAAABxeXl5eHAAAAAAAAAA6Xl5eUwAAAAAA + U15eXjoAAAAAAAAAAAAiR14cAAAAAAAAAAAAAABTXl5eOgAAAAAAAAAcXl5eXhwAAAAAAAAAOl5eXlMA + AAAAAFNeXl46AAAAAAAAAAAAAAAMAwAAAAAAAAAAAAAAU15eXjoAAAAAAAAAHF5eXl4cAAAAAAAAADpe + Xl5TAAAAAABTXl5eOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFNeXl46AAAAAAAAABxeXl5eHAAAAAAA + AAA6Xl5eUwAAAAAAU15eXjoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABTXl5eOgAAAAAAAAAcXl5eXhwA + AAAAAAAAOl5eXlMAAAAAAFNeXl46AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU15eXjoAAAAAAAAAHF5e + Xl4cAAAAAAAAADpeXl5TAAAAAABTXl5eOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFNeXl46AAAAAAAA + ABxeXl5eHAAAAAAAAAA6Xl5eUwAAAAAAU15eXjoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABTXl5eOgAA + AAAAAAAcXl5eXhwAAAAAAAAAOl5eXlMAAAAAAFNeXl46AAAAAAAAABxdTT4uCAAAAAAAAAAAAAAAU15e + XjoAAAAAAAAAHF5eXl4cAAAAAAAAADpeXl5TAAAAAABTXl5eOgAAAAAAAAAcXl5eXhwAAAAAAAAAAAAA + AFNeXl46AAAAAAAAABxeXl5eHAAAAAAAAAA6Xl5eUwAAAAAAU15eXjoAAAAAAAAAHF5eXl4cAAAAAAAA + AAAAAABOXl5eQAAAAAAAAAAkXl5eXiQAAAAAAAAAQF5eXk4AAAAAAE9eXl4/AAAAAAAAAB5eXl5eFQAA + AAAAAAAAAAAASV5eXlgZAQAAAAAKRl5eXl5GCgAAAAABGVheXl5IAAAAAABKXl5eVxgBAAAAAAlBXl5e + Xg0AAAAAAAAAAAAAADheXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eNwAAAAAAOV5eXl5eXl5eXl5e + Xl5eXlUAAAAAAAAAAAAAAAAUXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXhMAAAAAABZeXl5eXl5e + Xl5eXl5eXl40AAAAAAAAAAAAAAAAADNeXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXjIAAAAAAAAANV5e + Xl5eXl5eXl5eXl5MBAAAAAAAAAAAAAAAAAAAK1BeXl5eXl5eXl5cPTZaXl5eXl5eXl5eUCoAAAAAAAAA + AAAsUV5eXl5eXl5eXlk8BgAAAAAAAAAAAAAAAAAAAAAAEB8lJiYmJiQdBwAABRokJiYmJiUfEAAAAAAA + AAAAAAAAAAARHyUmJiYmIxcCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAACgAAABAAAAAgAAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAA= + + + + 123, 17 + + + 280, 17 + + + 423, 17 + + + 568, 17 + + + + AAABAAIAQEAAAAEACAAoFgAAJgAAAEBAAgABAAEAMAQAAE4WAAAoAAAAQAAAAIAAAAABAAgAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/38AAP+ADQD/gyYA/4QqAP+HOAD/iDsA/4pAAP+KQgD/i0UA/4xHAP+P + TwD/kFEA/5FVAP+TWgD/lV8A/5djAP+YZQD/mWgA/51uAP+ecQD/n3MA/6F3AP+ieAD/onkA/6N6AP+l + fgD/pn8A/6aAAP+ngQD/p4IA/6yJAP+tiwD/ro0A/6+PAP+wkAD/sJEA/7GTAP+0lwD/tZgA/7WZAP+5 + nwD/uqAA/7yjAP+8pAD/vqcA/7+nAP/BqgD/x7QA/8i2AP/JtgD/zbwA/829AP/OvgD/0MAA/9HCAP/S + wwD/0sQA/9PFAP/UxgD/1McA/9XIAP/YywD/2c4A/9vQAP/c0QD/3dIA/9/VAP/f1gD/4toA/+TcAP/l + 3QD/5+AA/+jiAP/p4gD/6eMA/+3oAP/u6QD/7+sA//HtAP/x7gD/8u8A//PvAP/08AD/9PEA//XyAP/1 + 8wD/+PYA//n3AP/5+AD/+/oA//z7AP/9/AD//v0A//7+AP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU0snAQAAAAAAAAAAHF1A + EgAAAAAAAAAAADpWMQYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFNeXk0eAAAAAAAA + ABxeXl1CCgAAAAAAAAA6Xl5XLwAAAAAAAAAPOU1ZXl5eXl5bVEMgAAAAAAAAAAAAAAAAAABTXl5eOgAA + AAAAAAAcXl5eXhwAAAAAAAAAOl5eXlMAAAAAAAAhWV5eXl5eXl5eXl5eXjkAAAAAAAAAAAAAAAAAU15e + XjoAAAAAAAAAHF5eXl4cAAAAAAAAADpeXl5TAAAAAAALWF5eXl5eXl5eXl5eXl5eKAAAAAAAAAAAAAAA + AFNeXl46AAAAAAAAABxeXl5eHAAAAAAAAAA6Xl5eUwAAAAAAMF5eXl5eXl5eXl5eXl5eXksAAAAAAAAA + AAAAAABTXl5eOgAAAAAAAAAcXl5eXhwAAAAAAAAAOl5eXlMAAAAAAEVeXl5dMycmJiYmLVNeXl5eCAAA + AAAAAAAAAAAAU15eXjoAAAAAAAAAHF5eXl4cAAAAAAAAADpeXl5TAAAAAABNXl5eRAAAAAAAAAApXl5e + XhMAAAAAAAAAAAAAAFNeXl46AAAAAAAAABxeXl5eHAAAAAAAAAA6Xl5eUwAAAAAAUl5eXjsAAAAAAAAA + HV5eXl4bAAAAAAAAAAAAAABTXl5eOgAAAAAAAAAcXl5eXhwAAAAAAAAAOl5eXlMAAAAAAFNeXl46AAAA + AAAAABxeXl5eHAAAAAAAAAAAAAAAU15eXjoAAAAAAAAAHF5eXl4cAAAAAAAAADpeXl5TAAAAAABTXl5e + OgAAAAAAAAAOS15eXhwAAAAAAAAAAAAAAFNeXl46AAAAAAAAABxeXl5eHAAAAAAAAAA6Xl5eUwAAAAAA + U15eXjoAAAAAAAAAAAAiR14cAAAAAAAAAAAAAABTXl5eOgAAAAAAAAAcXl5eXhwAAAAAAAAAOl5eXlMA + AAAAAFNeXl46AAAAAAAAAAAAAAAMAwAAAAAAAAAAAAAAU15eXjoAAAAAAAAAHF5eXl4cAAAAAAAAADpe + Xl5TAAAAAABTXl5eOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFNeXl46AAAAAAAAABxeXl5eHAAAAAAA + AAA6Xl5eUwAAAAAAU15eXjoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABTXl5eOgAAAAAAAAAcXl5eXhwA + AAAAAAAAOl5eXlMAAAAAAFNeXl46AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU15eXjoAAAAAAAAAHF5e + Xl4cAAAAAAAAADpeXl5TAAAAAABTXl5eOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFNeXl46AAAAAAAA + ABxeXl5eHAAAAAAAAAA6Xl5eUwAAAAAAU15eXjoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABTXl5eOgAA + AAAAAAAcXl5eXhwAAAAAAAAAOl5eXlMAAAAAAFNeXl46AAAAAAAAABxdTT4uCAAAAAAAAAAAAAAAU15e + XjoAAAAAAAAAHF5eXl4cAAAAAAAAADpeXl5TAAAAAABTXl5eOgAAAAAAAAAcXl5eXhwAAAAAAAAAAAAA + AFNeXl46AAAAAAAAABxeXl5eHAAAAAAAAAA6Xl5eUwAAAAAAU15eXjoAAAAAAAAAHF5eXl4cAAAAAAAA + AAAAAABOXl5eQAAAAAAAAAAkXl5eXiQAAAAAAAAAQF5eXk4AAAAAAE9eXl4/AAAAAAAAAB5eXl5eFQAA + AAAAAAAAAAAASV5eXlgZAQAAAAAKRl5eXl5GCgAAAAABGVheXl5IAAAAAABKXl5eVxgBAAAAAAlBXl5e + Xg0AAAAAAAAAAAAAADheXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eNwAAAAAAOV5eXl5eXl5eXl5e + Xl5eXlUAAAAAAAAAAAAAAAAUXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXhMAAAAAABZeXl5eXl5e + Xl5eXl5eXl40AAAAAAAAAAAAAAAAADNeXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXjIAAAAAAAAANV5e + Xl5eXl5eXl5eXl5MBAAAAAAAAAAAAAAAAAAAK1BeXl5eXl5eXl5cPTZaXl5eXl5eXl5eUCoAAAAAAAAA + AAAsUV5eXl5eXl5eXlk8BgAAAAAAAAAAAAAAAAAAAAAAEB8lJiYmJiQdBwAABRokJiYmJiUfEAAAAAAA + AAAAAAAAAAARHyUmJiYmIxcCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAACgAAABAAAAAgAAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAA= + + + \ No newline at end of file diff --git a/Meeting-Clock.csproj b/Meeting-Clock.csproj new file mode 100644 index 0000000..4aa8736 --- /dev/null +++ b/Meeting-Clock.csproj @@ -0,0 +1,163 @@ + + + + + Debug + AnyCPU + {97CA08CF-C8F9-4D6C-8C15-77695A995169} + WinExe + MeetingClock + Meeting Clock + v4.7.2 + 512 + true + true + + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + MeetingClock.MeetingClock + + + + + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + 7.3 + prompt + true + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + 7.3 + prompt + true + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + 7.3 + prompt + true + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + 7.3 + prompt + true + + + + True + + + + + + + + + + + + + + + + + Form + + + MainWindow.cs + + + + + + + + MainWindow.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + 10.0.19041.1 + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Meeting-Clock.sln b/Meeting-Clock.sln new file mode 100644 index 0000000..c7a42df --- /dev/null +++ b/Meeting-Clock.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30717.126 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Meeting-Clock", "Meeting-Clock.csproj", "{97CA08CF-C8F9-4D6C-8C15-77695A995169}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {97CA08CF-C8F9-4D6C-8C15-77695A995169}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {97CA08CF-C8F9-4D6C-8C15-77695A995169}.Debug|Any CPU.Build.0 = Debug|Any CPU + {97CA08CF-C8F9-4D6C-8C15-77695A995169}.Debug|x64.ActiveCfg = Debug|x64 + {97CA08CF-C8F9-4D6C-8C15-77695A995169}.Debug|x64.Build.0 = Debug|x64 + {97CA08CF-C8F9-4D6C-8C15-77695A995169}.Debug|x86.ActiveCfg = Debug|x86 + {97CA08CF-C8F9-4D6C-8C15-77695A995169}.Debug|x86.Build.0 = Debug|x86 + {97CA08CF-C8F9-4D6C-8C15-77695A995169}.Release|Any CPU.ActiveCfg = Release|Any CPU + {97CA08CF-C8F9-4D6C-8C15-77695A995169}.Release|Any CPU.Build.0 = Release|Any CPU + {97CA08CF-C8F9-4D6C-8C15-77695A995169}.Release|x64.ActiveCfg = Release|x64 + {97CA08CF-C8F9-4D6C-8C15-77695A995169}.Release|x64.Build.0 = Release|x64 + {97CA08CF-C8F9-4D6C-8C15-77695A995169}.Release|x86.ActiveCfg = Release|x86 + {97CA08CF-C8F9-4D6C-8C15-77695A995169}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8BF71566-EA72-4AF7-B52D-0D54EE96FC46} + EndGlobalSection +EndGlobal diff --git a/MeetingClock.cs b/MeetingClock.cs new file mode 100644 index 0000000..e824fc8 --- /dev/null +++ b/MeetingClock.cs @@ -0,0 +1,19 @@ +using System; +using System.Windows.Forms; + +namespace MeetingClock +{ + static class MeetingClock + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainWindow()); + } + } +} diff --git a/MeetingClockManager.cs b/MeetingClockManager.cs new file mode 100644 index 0000000..14d0956 --- /dev/null +++ b/MeetingClockManager.cs @@ -0,0 +1,479 @@ +using Microsoft.Win32; +using System; +using System.Diagnostics; +using System.IO.Ports; +using System.Text; +using System.Timers; +using System.Windows.Forms; + +namespace MeetingClock +{ + public class MeetingClockManager + { + private const string MTC = "MTC"; + + public enum MeetingClockState + { + NotInitialized, + NoComPort, + Disconnected, + Connected + } + + public MeetingClockState State { get; private set; } = MeetingClockState.NotInitialized; + public string Version { get; private set; } + public string Port { + get + { + if (this.serialPort != null && this.serialPort.IsOpen) + { + return this.serialPort.PortName; + } + return ""; + } + } + + public delegate void MeetingClockStateChangeHandler(MeetingClockManager manager, MeetingClockState oldState, MeetingClockState newState); + public event MeetingClockStateChangeHandler StateChanged; + + private System.Timers.Timer startTimer; + private System.Timers.Timer checkTimer; + private BluetoothManager bluetoothManager; + private SerialPort serialPort; + + public MeetingClockManager(BluetoothManager bluetoothManager) + { + this.NewSerialPort(); + + this.startTimer = new System.Timers.Timer(1000); + this.startTimer.AutoReset = false; + this.startTimer.Elapsed += ConnectTimer_Elapsed; + + this.checkTimer = new System.Timers.Timer(30000); + this.checkTimer.AutoReset = false; + this.checkTimer.Elapsed += CheckTimer_Elapsed; + this.checkTimer.Start(); + + this.bluetoothManager = bluetoothManager; + this.bluetoothManager.StateChanged += BluetoothManager_StateChanged; + } + + private void NewSerialPort() { + lock (this) { + if (this.serialPort != null) + { + try + { + this.serialPort.Close(); + } + catch (Exception) + { + // ignored + } + } + this.serialPort = new SerialPort(); + this.serialPort.BaudRate = 9600; + this.serialPort.Parity = Parity.None; + this.serialPort.DataBits = 8; + this.serialPort.StopBits = StopBits.One; + this.serialPort.Encoding = Encoding.GetEncoding("iso8859-1"); + this.serialPort.ReadTimeout = 1000; + this.serialPort.WriteTimeout = 1000; + } + } + + private void BluetoothManager_StateChanged(BluetoothManager manager, BluetoothManager.BluetoothState oldState, BluetoothManager.BluetoothState newState) + { + switch (newState) + { + case BluetoothManager.BluetoothState.On: + this.startTimer.Start(); + break; + default: + this.Disconnect(); + break; + } + } + + private void ConnectTimer_Elapsed(object sender, ElapsedEventArgs e) + { + this.Connect(); + } + + private void Connect() + { + lock (this) + { + if (this.State == MeetingClockState.Connected && this.serialPort.IsOpen) + { + Debug.WriteLine("Meeting clock already connected. Not trying to connect again."); + return; + } + + string[] portNames = SerialPort.GetPortNames(); + if (portNames.Length == 0) + { + Debug.WriteLine("No COM ports are available at the moment."); + this.ChangeState(MeetingClockState.NoComPort); + return; + } + + this.ChangeState(MeetingClockState.Disconnected); + this.NewSerialPort(); + + foreach (string portName in portNames) + { + Debug.WriteLine(String.Format("Trying to connect to {0}", portName)); + try + { + this.serialPort.PortName = portName; + this.serialPort.Open(); + + if (this.Handshake()) + { + Debug.WriteLine(String.Format("Successfully connected to meeting clock {0} on port {1}", this.Version, portName)); + this.Adjust(); + this.ScrollText(""); + this.NextDate(DateTime.Now.AddMinutes(-5)); + this.ChangeState(MeetingClockState.Connected); + return; + } + else + { + Debug.WriteLine(String.Format("Failed to connect to meeting clock on port {0}. Invalid Handshake.", portName)); + } + } + catch (Exception exception) + { + Debug.WriteLine(String.Format("Failed to connect to meeting clock on port {0}. {1}", portName, exception.Message)); + } + + this.Disconnect(); + } + } + } + + private void Disconnect() + { + lock (this) + { + if (this.serialPort.IsOpen) + { + Debug.WriteLine(String.Format("Closing connection on port {0}", this.serialPort.PortName)); + try + { + this.serialPort.Close(); + } + catch (Exception) + { + // ignored + } + } + + this.ChangeState(MeetingClockState.Disconnected); + this.NewSerialPort(); + } + } + + private bool Handshake() + { + string rx = this.SendAndReceive(MTC); + + if (rx == null) + { + return false; + } + + if (rx.StartsWith(MTC)) + { + this.Version = rx.Substring(MTC.Length).Trim(); + return true; + } + + return false; + } + + public void Adjust() + { + this.SendAndReceive(String.Format("ADJ {0}", DateTime.Now.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss"))); + } + + private string SendAndReceive(string tx) + { + lock (this) + { + try + { + if (this.serialPort.IsOpen) + { + Debug.WriteLine(String.Format(">>> {0}", tx)); + this.serialPort.WriteLine(tx); + string rx = this.serialPort.ReadLine().Trim(); + Debug.WriteLine(String.Format("<<< {0}", rx)); + return rx; + } + } + catch (Exception exception) + { + Debug.WriteLine(String.Format("Failed to send/receiv on port {0}. {1}", this.serialPort.PortName, exception.Message)); + this.Disconnect(); + } + + return null; + } + } + + private void ChangeState(MeetingClockState newState) + { + MeetingClockState oldState = this.State; + this.State = newState; + + if (newState != oldState) + { + Debug.WriteLine("Meeting Clock state change detected. Old state: {0}, new state {1}.", oldState, newState); + + if (this.StateChanged != null) + { + this.StateChanged(this, oldState, newState); + } + } + } + + private void CheckTimer_Elapsed(object sender, ElapsedEventArgs e) + { + if (this.serialPort.IsOpen) + { + if (!this.Handshake()) + { + this.Disconnect(); + } + } + else if (this.bluetoothManager.State == BluetoothManager.BluetoothState.On) + { + this.Connect(); + } + + this.checkTimer.Start(); + } + + public void Stop() + { + this.Disconnect(); + this.checkTimer.Stop(); + this.startTimer.Stop(); + } + + public int? GetTimeInterval() + { + try + { + string rx = this.SendAndReceive("GET TI").Substring(7); + return int.Parse(rx); + } + catch (Exception) + { + return null; + } + } + + public void SetTimeInterval(int value) + { + try + { + this.SendAndReceive("SET TI " + value); + } + catch (Exception) + { + } + } + + public int? GetDateInterval() + { + try + { + string rx = this.SendAndReceive("GET DI").Substring(7); + return int.Parse(rx); + } + catch (Exception) + { + return null; + } + } + + public void SetDateInterval(int value) + { + try + { + this.SendAndReceive("SET DI " + value); + } + catch (Exception) + { + } + } + + public int? GetTemperatureInterval() + { + try + { + string rx = this.SendAndReceive("GET CI").Substring(7); + return int.Parse(rx); + } + catch (Exception) + { + return null; + } + } + public void SetTemperatureInterval(int value) + { + try + { + this.SendAndReceive("SET CI " + value); + } + catch (Exception) + { + } + } + + public int? GetBrightness() + { + try + { + string rx = this.SendAndReceive("GET IN").Substring(7); + return int.Parse(rx); + } + catch (Exception) + { + return null; + } + } + + public int? GetScrollSpeed() + { + try + { + string rx = this.SendAndReceive("GET SS").Substring(7); + return int.Parse(rx); + } + catch (Exception) + { + return null; + } + } + + public int? GetScrollWait() + { + try + { + string rx = this.SendAndReceive("GET SW").Substring(7); + return int.Parse(rx); + } + catch (Exception) + { + return null; + } + } + + public void SetBrightness(int value) + { + try + { + this.SendAndReceive("SET IN " + value); + } + catch (Exception) + { + } + } + + public void SetScrollSpeed(int value) + { + try + { + this.SendAndReceive("SET SS " + value); + } + catch (Exception) + { + } + } + + public void SetScrollWait(int value) + { + try + { + this.SendAndReceive("SET SW " + value); + } + catch (Exception) + { + } + } + + public void ScrollText(string value) + { + try + { + this.SendAndReceive("SCR " + value); + } + catch (Exception) + { + } + } + + public bool? GetDateEnabled() + { + try + { + string rx = this.SendAndReceive("GET DE").Substring(7); + return int.Parse(rx) > 0; + } + catch (Exception) + { + return null; + } + } + + public void SetDateEnabled(bool value) + { + try + { + this.SendAndReceive("SET DE " + (value ? "1" : "0")); + } + catch (Exception) + { + } + } + + public bool? GetTemperatureEnabled() + { + try + { + string rx = this.SendAndReceive("GET CE").Substring(7); + return int.Parse(rx) > 0; + } + catch (Exception) + { + return null; + } + } + + public void SetTemperatureEnabled(bool value) + { + try + { + this.SendAndReceive("SET CE " + (value ? "1" : "0")); + } + catch (Exception) + { + } + } + + internal void NextDate(DateTime value) + { + try + { + this.SendAndReceive("NXT " + value.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss")); + } + catch (Exception) + { + } + } + } +} diff --git a/OutlookManager.cs b/OutlookManager.cs new file mode 100644 index 0000000..09b6886 --- /dev/null +++ b/OutlookManager.cs @@ -0,0 +1,181 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Outlook = Microsoft.Office.Interop.Outlook; + +namespace MeetingClock +{ + public class OutlookManager + { + private Outlook.Application application; + + public OutlookManager() + { + } + + public async Task GetNextAppointment( + bool ignoreAllDayEvents, bool ignoreCancelledMeetings, bool ignoreFreeMeetings, bool ignoreOutOfOfficeMeetings, bool ignoreTentativeMeetings) + { + await Task.Run(() => + { + lock(this) + { + int retries = 5; + while (this.application == null && retries-- > 0) + { + try + { + this.application = new Outlook.Application(); + } + catch (Exception exception) + { + this.application = null; + Debug.WriteLine(String.Format("Failed to start outlook application: {0}", exception.Message)); + Thread.Sleep(3000); + } + } + } + }); + + List appointmentItems = new List(); + + lock (this) + { + if (this.application == null) + { + return null; // not available at the moment + } + try + { + Outlook.Folder calendarFolder = this.application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar) as Outlook.Folder; + DateTime start = DateTime.Now; + DateTime end = start.AddHours(2); + + string filter = String.Format("[Start] >= '{0}' AND [Start] <= '{1}'", start.ToString("g"), end.ToString("g")); + Debug.WriteLine(String.Format("Filtering Outlook Events: {0}", filter)); + + Outlook.Items appointments = calendarFolder.Items; + appointments.IncludeRecurrences = true; + appointments.Sort("[Start]", Type.Missing); + Outlook.Items filteredAppointments = appointments.Restrict(filter); + + Debug.WriteLine(String.Format("Found {0} outlook appointments between {1} and {2}", filteredAppointments.Count, start.ToString("g"), end.ToString("g"))); + + DateTime? firstAppointmentTime = null; + + foreach (Outlook.AppointmentItem appointment in filteredAppointments) + { + Debug.WriteLine(String.Format("{0}-{5} ({6}): {1} ({2}), allday: {3}, busy: {4}, importance: {7}, recurring: {8}, scheduled: {9}, conflict: {10}", + appointment.Start.ToString("g"), appointment.Subject, appointment.MeetingStatus, appointment.AllDayEvent, appointment.BusyStatus, appointment.End.ToString("g"), + appointment.Duration, appointment.Importance, appointment.RecurrenceState, appointment.CreationTime.ToString("g"), appointment.IsConflict)); + + if (ignoreAllDayEvents && appointment.AllDayEvent) + { + continue; // ignore all day events + } + if (ignoreCancelledMeetings + && (appointment.MeetingStatus == Outlook.OlMeetingStatus.olMeetingCanceled || appointment.MeetingStatus == Outlook.OlMeetingStatus.olMeetingReceivedAndCanceled)) + { + continue; // ignore cancelled meetings + } + + if (ignoreFreeMeetings && appointment.BusyStatus == Outlook.OlBusyStatus.olFree) + { + continue; // ignore free meetings + } + + if (ignoreOutOfOfficeMeetings && appointment.BusyStatus == Outlook.OlBusyStatus.olOutOfOffice) + { + continue; // ignore out of office meetings + } + + if (ignoreTentativeMeetings && appointment.BusyStatus == Outlook.OlBusyStatus.olTentative) + { + continue; // ignore tentative meetings + } + + if (firstAppointmentTime == null) + { + firstAppointmentTime = appointment.Start; + } + + // ignore appointments that do not start first + if (firstAppointmentTime < appointment.Start) + { + continue; // ignore later appointments + } + + appointmentItems.Add(appointment); + Debug.WriteLine(String.Format("Next possible appointment is {0}-{1}: {2}", appointment.Start.ToString("t"), appointment.End.ToString("t"), appointment.Subject)); + } + + } + catch (Exception exception) + { + Debug.WriteLine(String.Format("Exception getting outlook appointments: {0}", exception.Message)); + this.application = null; + } + } + + if (appointmentItems.Count == 0) + { + return null; // no appointments upcoming + } + + if (appointmentItems.Count == 1) + { + return appointmentItems[0]; // exactly one appointment upcoming + } + + // remove cancelled events + appointmentItems = appointmentItems.AsQueryable() + .Where(item => item.MeetingStatus != Outlook.OlMeetingStatus.olMeetingCanceled && item.MeetingStatus != Outlook.OlMeetingStatus.olMeetingReceivedAndCanceled).ToList(); + if (appointmentItems.Count == 1) + { + return appointmentItems[0]; // one appointment still left + } + + // remove duplicates by priority, select highest priority + Outlook.OlImportance importance = appointmentItems.AsQueryable().OrderByDescending(item => (int)item.Importance).Select(item => item.Importance).First(); + appointmentItems = appointmentItems.AsQueryable().Where(item => item.Importance == importance).ToList(); + if (appointmentItems.Count == 1) + { + return appointmentItems[0]; // one appointment still left + } + + // remove all day events + appointmentItems = appointmentItems.AsQueryable().Where(item => !item.AllDayEvent).ToList(); + if (appointmentItems.Count == 1) + { + return appointmentItems[0]; // one appointment still left + } + + // remove free appointment + appointmentItems = appointmentItems.AsQueryable().Where(item => item.BusyStatus != Outlook.OlBusyStatus.olFree).ToList(); + if (appointmentItems.Count == 1) + { + return appointmentItems[0]; // one appointment still left + } + + // remove tentative appointment + appointmentItems = appointmentItems.AsQueryable().Where(item => item.BusyStatus != Outlook.OlBusyStatus.olTentative).ToList(); + if (appointmentItems.Count == 1) + { + return appointmentItems[0]; // one appointment still left + } + + // remove out of office appointment + appointmentItems = appointmentItems.AsQueryable().Where(item => item.BusyStatus != Outlook.OlBusyStatus.olOutOfOffice).ToList(); + if (appointmentItems.Count == 1) + { + return appointmentItems[0]; // one appointment still left + } + + return appointmentItems[0]; + } + } +} diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..fbd51d2 --- /dev/null +++ b/Properties/AssemblyInfo.cs @@ -0,0 +1,38 @@ +using System.Resources; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Meeting-Clock")] +[assembly: AssemblyDescription("Meeting Clock")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Frank Zechert")] +[assembly: AssemblyProduct("Meeting-Clock")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("97ca08cf-c8f9-4d6c-8c15-77695a995169")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: NeutralResourcesLanguage("en")] diff --git a/Properties/Resources.Designer.cs b/Properties/Resources.Designer.cs new file mode 100644 index 0000000..9d34586 --- /dev/null +++ b/Properties/Resources.Designer.cs @@ -0,0 +1,113 @@ +//------------------------------------------------------------------------------ +// +// 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. +// +//------------------------------------------------------------------------------ + +namespace MeetingClock.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // 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() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [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("MeetingClock.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). + /// + internal static System.Drawing.Icon icon_error { + get { + object obj = ResourceManager.GetObject("icon_error", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). + /// + internal static System.Drawing.Icon icon_neutral { + get { + object obj = ResourceManager.GetObject("icon_neutral", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). + /// + internal static System.Drawing.Icon icon_off { + get { + object obj = ResourceManager.GetObject("icon_off", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). + /// + internal static System.Drawing.Icon icon_ok { + get { + object obj = ResourceManager.GetObject("icon_ok", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). + /// + internal static System.Drawing.Icon icon_warning { + get { + object obj = ResourceManager.GetObject("icon_warning", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + } +} diff --git a/Properties/Resources.resx b/Properties/Resources.resx new file mode 100644 index 0000000..a1c5f61 --- /dev/null +++ b/Properties/Resources.resx @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\icons\icon-error.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icons\icon-neutral.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icons\icon-off.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icons\icon-ok.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icons\icon-warning.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/Properties/Settings.Designer.cs b/Properties/Settings.Designer.cs new file mode 100644 index 0000000..cf6eef9 --- /dev/null +++ b/Properties/Settings.Designer.cs @@ -0,0 +1,143 @@ +//------------------------------------------------------------------------------ +// +// 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. +// +//------------------------------------------------------------------------------ + +namespace MeetingClock.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.8.1.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + + [global::System.Configuration.ApplicationScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("v. 1.0.0")] + public string Version { + get { + return ((string)(this["Version"])); + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool CheckForUpdates { + get { + return ((bool)(this["CheckForUpdates"])); + } + set { + this["CheckForUpdates"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool StartMinimized { + get { + return ((bool)(this["StartMinimized"])); + } + set { + this["StartMinimized"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool StartBluetooth { + get { + return ((bool)(this["StartBluetooth"])); + } + set { + this["StartBluetooth"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool IgnoreAllDayAppointments { + get { + return ((bool)(this["IgnoreAllDayAppointments"])); + } + set { + this["IgnoreAllDayAppointments"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool IgnoreCancelledAppointments { + get { + return ((bool)(this["IgnoreCancelledAppointments"])); + } + set { + this["IgnoreCancelledAppointments"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool IgnoreFreeAppointments { + get { + return ((bool)(this["IgnoreFreeAppointments"])); + } + set { + this["IgnoreFreeAppointments"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool IgnoreOutOfOfficeAppointments { + get { + return ((bool)(this["IgnoreOutOfOfficeAppointments"])); + } + set { + this["IgnoreOutOfOfficeAppointments"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool IgnoreTentativeAppointments { + get { + return ((bool)(this["IgnoreTentativeAppointments"])); + } + set { + this["IgnoreTentativeAppointments"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("10")] + public int ReminderTime { + get { + return ((int)(this["ReminderTime"])); + } + set { + this["ReminderTime"] = value; + } + } + } +} diff --git a/Properties/Settings.settings b/Properties/Settings.settings new file mode 100644 index 0000000..46d7fbd --- /dev/null +++ b/Properties/Settings.settings @@ -0,0 +1,36 @@ + + + + + + v. 1.0.0 + + + True + + + False + + + False + + + True + + + True + + + False + + + False + + + False + + + 10 + + + \ No newline at end of file diff --git a/Settings.cs b/Settings.cs new file mode 100644 index 0000000..5f4b574 --- /dev/null +++ b/Settings.cs @@ -0,0 +1,164 @@ +using Microsoft.Win32; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace MeetingClock +{ + public class Settings + { + + private readonly string AUTOSTART_REGKEY = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run"; + private readonly string AUTOSTART_VALUE = "Meeting-Clock"; + + public bool Autostart + { + get + { + using (RegistryKey key = Registry.CurrentUser.OpenSubKey(AUTOSTART_REGKEY, false)) + { + return (string) key.GetValue(AUTOSTART_VALUE) == "\"" + Application.ExecutablePath + "\""; + } + } + + set + { + using (RegistryKey key = Registry.CurrentUser.OpenSubKey(AUTOSTART_REGKEY, true)) + { + if (value) + { + key.SetValue(AUTOSTART_VALUE, "\"" + Application.ExecutablePath + "\""); + } + else + { + key.DeleteValue(AUTOSTART_VALUE, false); + } + } + } + } + + public bool StartMinimized + { + get + { + return Properties.Settings.Default.StartMinimized; + } + set + { + Properties.Settings.Default.StartMinimized = value; + Properties.Settings.Default.Save(); + } + } + + public bool CheckForUpdates + { + get + { + return Properties.Settings.Default.CheckForUpdates; + } + set + { + Properties.Settings.Default.CheckForUpdates = value; + Properties.Settings.Default.Save(); + } + } + + public bool StartBluetooth + { + get + { + return Properties.Settings.Default.StartBluetooth; + } + set + { + Properties.Settings.Default.StartBluetooth = value; + Properties.Settings.Default.Save(); + } + } + + public bool IgnoreAllDayAppointments + { + get + { + return Properties.Settings.Default.IgnoreAllDayAppointments; + } + set + { + Properties.Settings.Default.IgnoreAllDayAppointments = value; + Properties.Settings.Default.Save(); + } + } + + public bool IgnoreCancelledAppointments + { + get + { + return Properties.Settings.Default.IgnoreCancelledAppointments; + } + set + { + Properties.Settings.Default.IgnoreCancelledAppointments = value; + Properties.Settings.Default.Save(); + } + } + + public bool IgnoreFreeAppointments + { + get + { + return Properties.Settings.Default.IgnoreFreeAppointments; + } + set + { + Properties.Settings.Default.IgnoreFreeAppointments = value; + Properties.Settings.Default.Save(); + } + } + + public bool IgnoreOutOfOfficeAppointments + { + get + { + return Properties.Settings.Default.IgnoreOutOfOfficeAppointments; + } + set + { + Properties.Settings.Default.IgnoreOutOfOfficeAppointments = value; + Properties.Settings.Default.Save(); + } + } + + public bool IgnoreTentativeAppointments + { + get + { + return Properties.Settings.Default.IgnoreTentativeAppointments; + } + set + { + Properties.Settings.Default.IgnoreTentativeAppointments = value; + Properties.Settings.Default.Save(); + } + } + + public int ReminderTime + { + get + { + return Properties.Settings.Default.ReminderTime; + } + set + { + Properties.Settings.Default.ReminderTime = value; + Properties.Settings.Default.Save(); + } + } + + + } +} + diff --git a/icons/icon-error.ico b/icons/icon-error.ico new file mode 100644 index 0000000000000000000000000000000000000000..0dd53ea806105999961f27d715624a08934031e8 GIT binary patch literal 6782 zcmeHLSx8h-82+?{= z=wKiUpg54?0K{|zR!}aQ+%F=Fpgy3*=0jR+IjqIjA}zKNwja}C$8jBY7VD6GLWkWab;u#)p3-5@X&v^S z(IbzLU!q6BSv?8~2QTPxsMLVNmkc;^*?^)l1CA1oT`{2eD&blaP7u!AXhI3$+^r^@ zziq_DJ4Tce%I+C){c$sHmJ=$Parc=C_Zgm>@Zg0B4_}(_sM3VTm1dMznNjh|j3-~D5!yYG6%*YDU_b~vbe6gsmyx%Au)C$(eAd!S#-GU&N;bpY7}u)2Rz}BwR>c;f z=b#8~krRZeaz0{PRb}B6sd1VtCkQL(L0N9&(tYJkbEaqcg7mSzuJNmV*$uOQ|5XVZ z7Re6Bh_Eg|ry&u{j~o`{V>73(r)AWjz!qs9a0R#mTmh~CSKuEjz@8#hgj@pq|Ck$B LfGfZiP*UJ0iHhb{ literal 0 HcmV?d00001 diff --git a/icons/icon-error.xcf b/icons/icon-error.xcf new file mode 100644 index 0000000000000000000000000000000000000000..a6dfabd6c3b2483c92174d85892b35755f574681 GIT binary patch literal 4000 zcmeHKZ)h837=N#qr0Jjhsdh@8gSY9#ZWx=y{z;*$p%v!}bsd5*Das|er00@LO)gua zA3Ej-K?kh}f*%B#2%>)Si|msqew_##s4%ghpM=>D8>nk?ufOMVw_P)B#TAsXC;aaD zJ%8@K_nzlDa+lYN%e1G0+za?;kwk#>10Em* z+-Gx2-UD0(0(o34nkf~Fs&2q$*0Qr@RWZ~oKcyK<{P29!s)*V$GP>RaILbeWHdd`<1twE zEtYLWtGZ@zP0uW;6*{Ao%T-i^Tlp^DqFa+`&n}V9wv0e;O9zj;f)1Soc^II|$n&%0 zrb?6e0IIG428lm@8b@>hAU~bbWpgMNaq$OToO($4Bph&fkBie59e=>Zsk6@Y$lqzl zX#Iz54#oBp7ZB(n7k4Iv_KB&G%FwM=8*0sn7L>Y5F1i=#+2Nv6K2crfk*OA$o=Q(o zp)ESkmC9H3MwUlZJ(^F` zN@=B{MzdO3%@|rq=LMq-XZy_3z&<)UnT$O)nTU^#C&v>Lqhkqfjqr=rilOD|JcDOO zrIR&13(6DYw0fx)Etaw>&(?LNsAX)IHM2K%xujv67;m>BfUryZgv>etAAH0K9^`rf4}2}Yo4#<{ z`nPL$GwGH+`aP=FyqKUe+8Uck`*Zw~LuCT=t8` z<~y(d<`?GW=l#q~|KJzRYi|X7Oq>}I;xzPYy~6ya+r!L9%mHDV2R%&0f6lIh%XTR3ehVGiiSUsg?K<_;yZ-S;Tm(W z=b+EQ{uZg0)?u%~PQp$?ufbkN-WLDv*5O z%)H;X(@pqU<;(hW9GiEQT2b2*y_?Y3;u|8-bAq`(ani%@-89oQ{+8|yo1~1 zeTKnmoH-^hm>CR&X>QlJQyA3??UQq}apsq1;i`PlWO z5Y3PJeQa}0h$~eeYw*=e*F2)}$4?(W0c-ujF{zU^l8yI=QR=l{Y61FFgrscH%XHt2 zk~z_O&E&K6l>y)X>Mfl1L-KFm!s$!EB|-X5b0h^qu-^rP*0&*Sl9Uao;1L`wSqZaW zfmeVSKyUsj8&u4mo5h56N0pI2h+Gm{bQvjdf?dW?4cw6w2mumWYiY(%Iyc0hOQtc! literal 0 HcmV?d00001 diff --git a/icons/icon-neutral.ico b/icons/icon-neutral.ico new file mode 100644 index 0000000000000000000000000000000000000000..e8d2ff2759b1b6eeb154ef6730bd9def53256af0 GIT binary patch literal 6782 zcmeHLS4>nv6g^VDE~@JG*b!2l|p#6MvkWoSoaw&b~9Vv+pesfIzrhkg+n_gaF}y z#DNkApi6lmPI7H@PLLwdeNM(j08^@iOT)os?ZD-Iz!iPLRW89`aP=^7&2VsCJh*-= zxFHeTI2qhD4NRR5Zk_?A%>=j10=Lcv)8~NO=Yl)t3Fd;DNQ^!FAxF^@0uH;f-KsDtKhGAPqd04j$hIW@QL=f+zQYrvzvAg4vm1&Qb7^ z;7XR@1ekjgym}hEb{4#TPH-N)aRIz}QIHMh<$$*@gLiVldso5x*TDSi;DbEDEwJD& z`1n5fBp-bG5G*VJi!>gA#f9MWBJjmC@Kv$kIr#bo_(t&drQj9#?zP|z`0+jX>4V@S z_~kSB^$S??75r8r_y&?rOJedy0i%FXz$jo8FbepmKtfDJfVVR=*;U)?BWgm|ioU?v zNl+@bsZ|bDDtT~_6+|gDv9smZjEtS6v`ra5q`8%|2H~qH%NM>!lRQN4tG>hYnIHTvUZOR|_{ie;!5=2PP6G~r;(nRwc{~q6Q3jH>Y#UJZuZ>bR@^Lv;05BNaK;eW>ms+Ifm>$fpI zuKnU1_OHF=f9HoL#}4T9oBQ9cUnz;Tn2yC?@4uh;ak3v>)~bZ*FGrXaxWtch`|;up zw6aabSM{tw4C&_OGL;0Hk_f~cSNMfOP)zfOb=RG3)MPr~Sj4b(Nc*WYuw+pd|m;tI;x6Mpyn zz31M0p6AH>=C$GquV!-mxKA;PD zz>z6yqc{Jl5nY!iLyFGHqBS#>+&m()gkK zI5HSJK(YXV4|!yFGH9Kc2B`$zY_X|U%~(OHsbr#ekzN=sDy0*Z6&{^#3NzE`nQ62` z=Q*RK=1WFJ&px>n9m?6X6m^_s?KKtV$>hWsYzuSKBXrNqO@<^RPQoZUnKN{gN1roJ zD*X9ZD@sXqjWJ5ZClgMLtu`CGqE*!bO@X4Dno`h|GOyWFQBd@J1*6KNsvgUyDN|Z0 ztFf$BQZuGz=)7Q-U~HXL8q~+frjnyiOeNyu6Um9hQaMuUX zH}2Y3r30)(NI*Bx!TLpzg+zeu2O`4927n$94+xpH0|D4bCioER2Yj$K<-N4^wB)~2 zy^~3|tvSf#+idhsd-oo_ExD+s-nwnq{VXi}9)Ey!qrS3e2WYLU(#Pyx=ct1BI_J*O z-p#5{-03&gdjH+@%{2yRkIIX`&rgN1J(`%87aK=s2fJBgh|G;=Ra!< z`CCv}S6&J-EB#|oG_JoB3NUe|Ux?G-Z*&Xm+fE;|9<%y|WgYS{F&Y-)b?~$Mg?I~m z4f-$OU$u$G=C~v?tM7s=tP6cIYe?gpZ9;qr@7M5NO^~l~gj4}Bi| z9Q5xH`UCg}&{MFFAZ`QtI`ky;B=|b?4a9A;?_J!DWc||n`N(bwds-IIy0HJ+-^r{8 z1G~LMkkt==fx_;G$t8v!8&5#hs|1QAKtY@xu39;s9TN^@LN(I=Bq!5iy z`T}fgU5Kld0IT!0%h!FP{>RUsJ`HW-;xVb6)syuPhf(VFU#lVdQv{_P(6*>|R>_=b zZZr8Doi1QwblxHQKkdewEBg1laXJxrC`{)xmr@W2&Ym!ApADfCr5u2TkKkg{Y7b+; yDj*0jrW{aFyKWT~+FeyfIv9BzMMu@rLAi~jp_RUfR7zzGuac7RIyo7sDJgi9nu@n+X?T~Oj?9b< zWMyXJeO4A!+1bd=$w8hdV0`H#*f}!^!N3lzrP;?0|OWu9K_F| zAq)=>V`O9mqobo38ymy;_&6peCNMcUiK(e6Oixc^hK$*n8O+YkVs35@^YimqSXjW~ z;v$xomax3MjFpuYtgfzNZEX$f>+9Iq*bv(aR%Z?{2bcrQ0pO_4 zh@Okk;|qE*?UL~33Hr$d{h?^R(C|v{@Qh)C{+dC^&ml%J0Ve1l5M8{di!+HUl+Fon zDoxNUh$N7|rj+VW2tI%b`fwug?$<9+>Y;FP5^Antaoex|f7eUm6@G3z{QiqtOwAN+Ztwr5Eu#8RvSt1hkZ`2? z=cvc5foKIc>^y2cVf9J#>O}#9)Gyr*)KrGDY!)WdU2SCD$}#Os0@$2}qs%EE9BGq&UI z+=w+MVXj8j(28?~x(-2@6y+wlNv})pt;x-n z`qD8U1Rb;@2tEih5k!63i|k1hUnjx_DoiZslQ84 z&$;J(-*?HmMYX)d>$w6yHJnT`P{skt?*cu5&xhdwpcCMv@HPw&0-+fM5kS3w9|!;s zIWh(B0j>k#A|95=>E*Jb8PJ)v>`X3fX-g+1ni- zt^cSagRui73lR8#M|L}e&V;V;Rlx018%o_sl;mZFOmr6C3xj33a!J>t@tYR)lPJ$q}Hiz>E>Cb#xT+4Yd0I>sfp`JBr8siH2q zKIs0#u5rb8fOQBT&<%93J`rMJ5oG&-sPMD>K+MB~LSpSe5H^wte#8acX z`gf~$GT$A04l(Ht8=YzQ&e7Ad7Uk5Nx2<}BMMS{k53+9LR}$?2?RCZXF}q(m%HaLV zxqY;Iz3LZt`;N8Fzn9**X8-gtY5w=wi3np|W3$qH^VoEMH){@%x%q4|(80`?uZBcp z^Sw8J3kmb;OCe@ve+-G{jd#L9CeHQ=aR&U2Zef1g>1XESW}h(4Lw+WPBSO3mer}%- zZ-K8u{{{T3HqqP|^-0X^y(kIuVz0!SzR`^~A-;t7Yk04v$Q%1e65?TriSOY$k7vw6 zp9Mb;{X2yI0R92=4D3UQTZg^|JqNOmJPIS?7#MR zGIMWmr$dBT<(uMGIReo$ofABw5znufAiJ3s zqWMX0kZrCBajh0)4ZeEihF>)P`1#YPp{-v!?rUd_bmPN8q(QOBo0R=Pnqrz73%hWgLJ-j$*KACB^~{ z_JY&RKjVOs*>yXa(C(=;x*tk(E>LvA=GK_ONN{4Jb;vGdAP_*&HJdYr)OjKP1X!yu AF#rGn literal 0 HcmV?d00001 diff --git a/icons/icon-ok.ico b/icons/icon-ok.ico new file mode 100644 index 0000000000000000000000000000000000000000..43b00044af19d42bf6f923f684449ac30a4104a2 GIT binary patch literal 6782 zcmeHLS4>k;82*YI7cLYn;$XQ^6kG`6Kv1wE$nZXBqR|(P4<;rW6Jm^sBd!-?To3Z3 z(P(@iL_kH^lqD1}EZKWgMj8I6y{#AICIu5;Jb&`#e*gG-d%n}0-WE{60$yIA>r^;f z1C9XY7L+UCG7$)%nlq~rA_#0wE}{}th)M`VbYdu?lfv;a`2^u4Vp2{KP7}@`Hsvhh zQqLhS?L0oEUBKt`i}<3xgn0F3#AjT=*Nm%3$htPO6NXov6q?}tw&bdvvgOu-g z3HJ#1k(&E}@DS;mM^I}XBP0I_;VI!6GV`A!v)~1?3ttijq(OaiAsSnX(cD^!=C(4lwpXCFqmodCHbO^NJvy}w=+ZV4nxO4&CbXct zrhk=293=R$u1~D|mFeJAXyv`lq4sZv! z1Ka`bz}Os6`8X+z3T3#*TqB43(T$T$i9AsWg6~qXtrUdgo|agRrHfNCbB&7|ef|HtUK#GYWBnLE|FRY{Gi95j z`#)@pnEnuLnFk{j_H6&`4ICcC59&D^*(p|+vXKR1!Y=zL54O=Cp_bmP>8(Ei6*lb9 z*{dJiPb_GWeq`D%HZoJ9cVh*)aMKU6l}IB{BFB7bXCyZq6xJiku2MZ*M|36WCUJ1H zq$UUl=!dd2*7%#+VcWNaniBujrm3|7rfSHxKfhJ1>>SwPXm2|On6%iQaR)mqlbVq^ shLM#EErykO!X4laa0j>p+<|}W0Q(i;MTj7<|Brca2e<>=0XYYL0ft%8MF0Q* literal 0 HcmV?d00001 diff --git a/icons/icon-ok.xcf b/icons/icon-ok.xcf new file mode 100644 index 0000000000000000000000000000000000000000..6e6f909eccdd9aca1ed5c4e9422f655effc9bb9f GIT binary patch literal 4000 zcmeHKUuauZ7(cf+Nz*_1Q|**G2dC-8ZW!Ct{z;*$p%v!}bsd5*DauW9lU|qH)Z}JM zeCe1Ef(}{{1Rn&M2%tq19eUA@%P<7+ij+;xPmhFh2Q!9 zo^#LnzVDKA^ICD4*D^VNayXG-pp*lW-vN36Ny2a+&h_K-)8Kz5%;_IAfd z>p$YiU~E6h0t7zbk=+iVGodS_GPqr8L#-L{f>Kw>L}!tnA1o^66V+uNo3e%Jsr2*| z%A)gJsjTM9rK+Aiv=|%6S+p2)oE7a=73PWL_$X}ivr|JfXZj|?B16uCF;p~H(hVMa zwscbA&%IJr%BpLO(?Wb=#EG#~yTHp@O)XG2D7v931x=~&y44*8MbB5!vOK2h@qC(A zN-GsLp4G}~#?VSSFBoMQTYHuo_VLllx1q)#{e6ZQ_ZrY+P z>))x~$)wx%9AxrsHagSpouj8^Ey}4kZ(DUg3k$!;A7I_cuPoXD+Utt+5xZA8%HX}q zxqY;Iz3LNp`i`~Eznk80{<&W}h(4gFYsP!$Q0Ues-@A zZ-TEv{{{TZHqqP|lVoQ0UXX=(p;u;2X>6lSh%ey%3f`+D<(uMFmvBG$ofABw5znufFi#E5$6h?v*6RAOVDFuN5imch3F{I85@h6As BG28$E literal 0 HcmV?d00001 diff --git a/icons/icon-warning.ico b/icons/icon-warning.ico new file mode 100644 index 0000000000000000000000000000000000000000..c37ee0c039505cae5b9e48b572f18952bfed71d5 GIT binary patch literal 6782 zcmeI0TTqN)7{~wRoKr+jC5NaGIa{Klk|>FyLVYvFxHDs1ILy#+XN<$Rz#TITGp=!i z8HXVx6&fO^45iW@YTI-E@9wwjtL)6ij2rJW^Xq$__j&&N_5HuEx7`JT5RBwx@Hh~$ z;lOl&bujB7B=iNcxfUzdNGTC>{$gO69$_Tzu^#bH^w2#uAd#ey)N%vTNe0PzW7#C za)O+E(}q*zG&xh-hO=+magLlP7wXz^kz9Ij#^n!YTp?G_jJ#AsvtoNC%_?(gEo}uN}zCj0y6JB8rnndUNQu%uP6~}LA{da$tQcnqRa43dwK!r2N!yT z-k;(fo-YE>CwPVGG1Dhz5`aFHy5jjU(;4w%T+zO%3_zbv$tv}naY7%a`2_;dZ=z(W zDv1>O3BA+%J%xA~zs+CwPdhSfEzj@0#ebj&rlkL!9vIT+&#zyj^rYI0^Yi>_NB(zx zL~+*g*}Z)Jwf=RnSeWUz`TOUuhdzhTW0HDTqQxIav|1!FU+>O0Fk7LnP81`f)j}LH zSQn0SZ=oS+qM7F20E5PfO=q=xa1FD9vF?#U$zo)vM!!TX_>0BvL2)J8*sPIbl(y47 z_iPm5-If<<^_btSt10KHg9|llin5L$l(jK4*Vo>jxM-`d$erPvnzhllTC}X^f0fXv zX<~DXjvN5=8y_w5X;Gm*wMa&IMy8Gl?y@Wk>40=VIv^d84*X*W#HWa4QcA@4$1sS3c>LE literal 0 HcmV?d00001 diff --git a/icons/icon-warning.xcf b/icons/icon-warning.xcf new file mode 100644 index 0000000000000000000000000000000000000000..1d156020a617a4a6a79f69d82cb501d0261ff2ed GIT binary patch literal 4000 zcmeHKUuauZ7(cf+Nz*_1Q|**G2dC-8ZW!Cd{z;*$p%v!}bsd5*DavhflU|qH)Z}JM zeCe1Ef(}{{1Rn&M2%a`6<1KkzVJKW z-*fIc-}hZ|ZeA-c^I9gyPYx#%43u_2@>@U;AW0bR0XhNRMgv*y1%fjOB7k}UAK(Y> zb7YF!16&0{c|0thDHV&VZa`<&vNL5>G1M$Sr5Q{7@R7NB@>=r_t%SO59zO1Iy5as)k4@Ub)a2sS zB+8=mT&b+)%cZKGJ+u%T$XT=ybDS0JWfkV})Yu4Yb2F1eG-v7t!y-e@f-zJySJDk0 zd%AQ|;m^EORm!SsjMGAVJn6((s$Jk^t)>>J8x-Bpl!B&Ic-`ubf}-cEXjvXp^>}`f zR$5dlYCNlz)r_H)bY3vZFt+wAHSD7!6RF|HCX$KKvD8>{d}K7qtrmWA){<=MKf6t#?FvU>K$E|)ZH6HRXIk+SO{A9ajNZu2>n_fbV% za(&Q!hg{=|w4Zed3FrnoSf2>8kO;87Kt%Z1J|ODh0U@(?AOIW51RrAkfDblX-c4Jy zW&PXLJDGILo`X!j#YSh^y>s-mtVKEX=54F)XJO&@_yepP`ISXGKzm)0K45n%M;W|Z zIk%5?uUCEIcHgnq`FGMg*X*A@D$oBuI}v8AYiw4YZyufQ?`F*bGB=+}_&b>S!sVc7 zY`*>4Z$V*Rem=;|#UFyAdF{|fS=tf z#OvUz(0>O1qD?e6MkSe~x4AYaIRziQVBW0cP&|8d?7bfp(R)S@1`!^9GVNfohI#6L$%5pCIlz#2wrw z?o%{YYEI>4@{ zglK-)8(^DjLR_f^Sc9)#y5yuT>K0D>A^NwsaM_;jj$!&vb14mh;M@hn*0&*aqO=3B@DU6atwh