/// <summary>
        /// Initializes a new instance of the class. Initializes the communication interface and read/write locks.
        /// </summary>
        public ThreadCommTarget(MdiPTU mainForm)
        {
            m_MainForm = mainForm;

            m_MutexPause              = new Mutex();
            m_MutexPauseFeedback      = new Mutex();
            m_MutexCommunicationFault = new Mutex();

            m_ResponseCount        = 0;
            m_PollScheduler        = new PollScheduler();
            m_ReadTimeoutCountdown = ReadTimeoutCountdown;
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Clean up the resources used by the form.
        /// </summary>
        /// <param name="disposing">True to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
        protected virtual void Cleanup(bool disposing)
        {
            // Skip, if the Dispose() method has been called.
            if (IsDisposed)
            {
                return;
            }

            // Restore the ToolStripButtons
            #region - [Online] -
            m_ToolStripButtonOnline.Text = Resources.FunctionKeyTextOnline;
            m_ToolStripButtonOnline.ToolTipText = Resources.FunctionKeyToolTipTextOnline;
            m_ToolStripButtonOnline.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText;
            m_ToolStripButtonOnline.TextAlign = ContentAlignment.BottomCenter;
            m_ToolStripButtonOnline.Size = new Size(70,50);
            m_ToolStripButtonOnline.Margin = new Padding(0, 1, 0, 2);
            ToolStripSeparator toolStripSeparatorOnlineLHS = (ToolStripSeparator)MainWindow.ToolStripFunctionKeys.Items[CommonConstants.KeyToolStripSeparatorOnlineLHS];
            Debug.Assert(toolStripSeparatorOnlineLHS != null, "ControlPanel.InitializeControlPanel() - toolStripSeparatorOnlineLHS != null");
            toolStripSeparatorOnlineLHS.Visible = false;
            toolStripSeparatorOnlineLHS.Margin = new Padding(0, 0, 0, 0);
            #endregion - [Online] -

            #region - [Offline] -
            m_ToolStripButtonOffline.Text = Resources.FunctionKeyTextOffline;
            m_ToolStripButtonOffline.ToolTipText = Resources.FunctionKeyToolTipTextOffline;
            m_ToolStripButtonOffline.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText;
            m_ToolStripButtonOffline.TextAlign = ContentAlignment.BottomCenter;
            m_ToolStripButtonOffline.Size = new Size(70, 50);
            m_ToolStripButtonOffline.Margin = new Padding(0, 1, 0, 2);
            ToolStripSeparator toolStripSeparatorOfflineLHS = (ToolStripSeparator)MainWindow.ToolStripFunctionKeys.Items[CommonConstants.KeyToolStripSeparatorOfflineLHS];
            Debug.Assert(toolStripSeparatorOfflineLHS != null, "ControlPanel.InitializeControlPanel() - toolStripSeparatorOfflineLHS != null");
            toolStripSeparatorOfflineLHS.Visible = false;
            toolStripSeparatorOnlineLHS.Margin = new Padding(0, 0, 0, 0);
            #endregion - [Offline] -

            MainWindow.ToolStripFunctionKeys.AutoSize = true;

            // Restore the Visible property of those StatusLabels that were modified to their default state.
            m_ToolStripStatusLabelLogStatus.Visible = true;
            m_ToolStripStatusLabelCarNumber.Visible = true;
            m_ToolStripStatusLabelWibuBoxStatus.Visible = false;

            // Restore the Visible property of the ToolStripFunctionKeys ToolStrip.
            if (MainWindow != null)
            {
                MainWindow.ToolStripFunctionKeys.Visible = true;
            }

            try
            {
                if (disposing)
                {
                    // Cleanup managed objects by calling their Dispose() methods.
                    if (components != null)
                    {
                        components.Dispose();
                    }
                }

                // Whether called by consumer code or the garbage collector free all unmanaged resources and set the value of managed data members to null.
                #region - [Detach the event handler methods.] -
                m_ToolStripButtonOnline.CheckedChanged -= new EventHandler(Online_CheckedChanged);
                m_ToolStripButtonOffline.CheckedChanged -= new EventHandler(Offline_CheckedChanged);

                m_ToolStripStatusLabelLogStatus.TextChanged -= new EventHandler(LogStatus_TextChanged);
                m_ToolStripStatusLabelWibuBoxStatus.TextChanged -= new EventHandler(WibuBoxStatus_TextChanged);
                m_ToolStripStatusLabelCarNumber.TextChanged -= new EventHandler(CarNumber_TextChanged);
                m_ToolStripStatusLabelMode.TextChanged -= new EventHandler(Mode_TextChanged);
                m_ToolStripStatusLabelSecurityLevel.TextChanged -= new EventHandler(SecurityLevel_TextChanged);

                m_ToolStripMenuItemView.EnabledChanged -= new EventHandler(ViewWatchWindow_EnabledChanged);
                m_ToolStripMenuItemView.EnabledChanged -= new EventHandler(ViewSystemInformation_EnabledChanged);

                m_ToolStripMenuItemViewWatchWindow.EnabledChanged -= new EventHandler(ViewWatchWindow_EnabledChanged);
                m_ToolStripMenuItemViewSystemInformation.EnabledChanged -= new EventHandler(ViewSystemInformation_EnabledChanged);

                m_ToolStripMenuItemDiagnostics.EnabledChanged -= new EventHandler(DiagnosticsEventLog_EnabledChanged);
                m_ToolStripMenuItemDiagnosticsEventLog.EnabledChanged -= new EventHandler(DiagnosticsEventLog_EnabledChanged);

                m_ToolStripMenuItemDiagnostics.EnabledChanged -= new EventHandler(DiagnosticsSelfTests_EnabledChanged);
                m_ToolStripMenuItemDiagnosticsSelfTests.EnabledChanged -= new EventHandler(DiagnosticsSelfTests_EnabledChanged);

                m_ToolStripMenuItemDiagnostics.EnabledChanged -= new EventHandler(DiagnosticsSelfTests_EnabledChanged);
                m_ToolStripMenuItemDiagnosticsInitializeEventLogs.EnabledChanged -= new EventHandler(DiagnosticsInitializeEventLogs_EnabledChanged);

                m_MdiPTU.MdiChildActivate -= new EventHandler(MdiChildActivate);
                m_MdiPTU.MenuUpdated -= new EventHandler(MenuUpdated);

                if (MainWindow != null)
                {
                    MainWindow.FontChanged -= new System.EventHandler(ChangeFont);
                }
                #endregion - [Detach the event handler methods.] -

                m_MdiPTU = null;
                m_MainWindow = null;
                m_ToolStripButtonOnline = null;
                m_ToolStripButtonOffline = null;
                m_ToolStripMenuItemView = null;
                m_ToolStripMenuItemViewWatchWindow = null;
                m_ToolStripMenuItemViewSystemInformation = null;
                m_ToolStripMenuItemDiagnostics = null;
                m_ToolStripMenuItemDiagnosticsEventLog = null;
                m_ToolStripMenuItemDiagnosticsSelfTests = null;
                m_ToolStripMenuItemDiagnosticsInitializeEventLogs = null;
                m_ToolStripStatusLabelLogStatus = null;
                m_ToolStripStatusLabelWibuBoxStatus = null;
                m_ToolStripStatusLabelCarNumber = null;
                m_ToolStripStatusLabelMode = null;
                m_ToolStripStatusLabelSecurityLevel = null;

                #region - [Component Designer Variables] -
                #endregion - [Component Designer Variables] -
            }
            catch (Exception)
            {
                // Don't do anything, just ensure that an exception isn't thrown.
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Initializes the ControlPanel UserControl.
        /// </summary>
        /// <param name="mainWindow">Reference to the IMAinWindow interface.</param>
        public void InitializeControlPanel(IMainWindow mainWindow)
        {
            // Skip, if the Dispose() method has been called.
            if (IsDisposed)
            {
                return;
            }

            MainWindow = mainWindow;
            if (MainWindow == null)
            {
                return;
            }

            // Attach the FontChaged event in the PTU main application window to the ChangeFont event handler.
            MainWindow.FontChanged += new System.EventHandler(ChangeFont);

            #region - [ToolStripButtons] -
            // ---------------------------------------------------------------------------------------------------------------------------
            // Updated the layout of the 'Online' and 'Offline' ToolStripButton controls to match the requirements of the current project.
            // ---------------------------------------------------------------------------------------------------------------------------

            // Get the references to the ToolStripButton controls on the ToolStripFunctionKeys ToolStrip.
            m_ToolStripButtonOnline = (ToolStripButton)MainWindow.ToolStripFunctionKeys.Items[CommonConstants.KeyToolStripButtonOnline];
            m_ToolStripButtonOffline = (ToolStripButton)MainWindow.ToolStripFunctionKeys.Items[CommonConstants.KeyToolStripButtonOffline];

            Debug.Assert(m_ToolStripButtonOnline != null, "ControlPanel.InitializeControlPanel() - m_ToolStripButtonOnline != null");
            Debug.Assert(m_ToolStripButtonOffline != null, "ControlPanel.InitializeControlPanel() - m_ToolStripButtonOffline != null");

            MainWindow.ToolStripFunctionKeys.AutoSize = false;

            #region - [Online] -
            m_ToolStripButtonOnline.DisplayStyle = ToolStripItemDisplayStyle.Text;
            m_ToolStripButtonOnline.TextAlign = ContentAlignment.MiddleCenter;
            m_ToolStripButtonOnline.Size = new Size(136, 32);
            m_ToolStripButtonOnline.Margin = new Padding(13, 0, 13, 0);
            ToolStripSeparator toolStripSeparatorOnlineLHS = (ToolStripSeparator)MainWindow.ToolStripFunctionKeys.Items[CommonConstants.KeyToolStripSeparatorOnlineLHS];
            Debug.Assert(toolStripSeparatorOnlineLHS != null, "ControlPanel.InitializeControlPanel() - toolStripSeparatorOnlineLHS != null");
            toolStripSeparatorOnlineLHS.Visible = true;
            toolStripSeparatorOnlineLHS.Margin = new Padding(8, 0, 0, 0);
            #endregion - [Online] -

            #region - [Offline] -
            m_ToolStripButtonOffline.DisplayStyle = ToolStripItemDisplayStyle.Text;
            m_ToolStripButtonOffline.TextAlign = ContentAlignment.MiddleCenter;
            m_ToolStripButtonOffline.Size = new Size(136, 32);
            m_ToolStripButtonOffline.Margin = new Padding(13, 0, 13, 0);
            ToolStripSeparator toolStripSeparatorOfflineLHS = (ToolStripSeparator)MainWindow.ToolStripFunctionKeys.Items[CommonConstants.KeyToolStripSeparatorOfflineLHS];
            Debug.Assert(toolStripSeparatorOfflineLHS != null, "ControlPanel.InitializeControlPanel() - toolStripSeparatorOfflineLHS != null");
            toolStripSeparatorOfflineLHS.Visible = true;
            toolStripSeparatorOfflineLHS.Margin = new Padding(16, 0, 0, 0);
            #endregion - [Offline] -

            // Attach the CheckedChanged events to the event handlers.
            m_ToolStripButtonOnline.CheckedChanged += new EventHandler(Online_CheckedChanged);
            m_ToolStripButtonOffline.CheckedChanged += new EventHandler(Offline_CheckedChanged);

            // Call each of the CheckedChanged event handlers to ensure that the Text property of the ToolStripButton controls matches the current Checked state.
            Online_CheckedChanged(this, new EventArgs());
            Offline_CheckedChanged(this, new EventArgs());
            #endregion - [ToolStripButtons] -

            #region - [StatusLabels] -
            // Get the references to the ToolStripStatusLabel controls.
            m_ToolStripStatusLabelLogStatus = (ToolStripStatusLabel)MainWindow.StatusStrip.Items[CommonConstants.KeyToolStripStatusLabelLogStatus];
            m_ToolStripStatusLabelWibuBoxStatus = (ToolStripStatusLabel)MainWindow.StatusStrip.Items[CommonConstants.KeyToolStripStatusLabelWibuBoxStatus];
            m_ToolStripStatusLabelCarNumber = (ToolStripStatusLabel)MainWindow.StatusStrip.Items[CommonConstants.KeyToolStripStatusLabelCarNumber];
            m_ToolStripStatusLabelMode = (ToolStripStatusLabel)MainWindow.StatusStrip.Items[CommonConstants.KeyToolStripStatusLabelMode];
            m_ToolStripStatusLabelSecurityLevel = (ToolStripStatusLabel)MainWindow.StatusStrip.Items[CommonConstants.KeyToolStripStatusLabelSecurityLevel];

            Debug.Assert(m_ToolStripStatusLabelLogStatus != null, "ControlPanel.InitializeControlPanel() - m_ToolStripStatusLabelLogStatus != null");
            Debug.Assert(m_ToolStripStatusLabelWibuBoxStatus != null, "ControlPanel.InitializeControlPanel() - m_ToolStripStatusLabelWibuBoxStatus != null");
            Debug.Assert(m_ToolStripStatusLabelCarNumber != null, "ControlPanel.InitializeControlPanel() - m_ToolStripStatusLabelCarNumber != null");
            Debug.Assert(m_ToolStripStatusLabelMode != null, "ControlPanel.InitializeControlPanel() - m_ToolStripStatusLabelMode != null");
            Debug.Assert(m_ToolStripStatusLabelSecurityLevel != null, "ControlPanel.InitializeControlPanel() - m_ToolStripStatusLabelSecurityLevel != null");

            // Attach the TextChanged events to the event handlers.
            m_ToolStripStatusLabelLogStatus.TextChanged += new EventHandler(LogStatus_TextChanged);
            m_ToolStripStatusLabelWibuBoxStatus.TextChanged += new EventHandler(WibuBoxStatus_TextChanged);
            m_ToolStripStatusLabelCarNumber.TextChanged +=new EventHandler(CarNumber_TextChanged);
            m_ToolStripStatusLabelMode.TextChanged += new EventHandler(Mode_TextChanged);
            m_ToolStripStatusLabelSecurityLevel.TextChanged += new EventHandler(SecurityLevel_TextChanged);

            // Call each of the event handlers to ensure that the Text property of the Labels accurately reflect the Text property of its associated
            // ToolStripStatusLabel.
            LogStatus_TextChanged(this, new EventArgs());
            WibuBoxStatus_TextChanged(this, new EventArgs());
            CarNumber_TextChanged(this, new EventArgs());
            Mode_TextChanged(this, new EventArgs());
            SecurityLevel_TextChanged(this, new EventArgs());

            // Hide the ToolStripStatusLabel controls that are displayed on the Control Panel.
            m_ToolStripStatusLabelLogStatus.Visible = false;
            m_ToolStripStatusLabelCarNumber.Visible = false;
            m_ToolStripStatusLabelWibuBoxStatus.Visible = false;
            m_ToolStripStatusLabelMode.Visible = false;
            m_ToolStripStatusLabelSecurityLevel.Visible = false;
            #endregion - [StatusLabels] -

            #region - [Menu Items] -
            #region - [File] -
            m_ToolStripMenuItemFile = ((ToolStripMenuItem)MainWindow.MenuStrip.Items[CommonConstants.KeyMenuItemFile]);
            Debug.Assert(m_ToolStripMenuItemFile != null, "ControlPanel.InitializeControlPanel() - m_ToolStripMenuItemFile != null");
            m_ToolStripMenuItemFileExit = ((ToolStripMenuItem)m_ToolStripMenuItemFile.DropDownItems[CommonConstants.KeyMenuItemFileExit]);
            m_ToolStripSeparatorFileOpenDataDictionary =
                ((ToolStripSeparator)m_ToolStripMenuItemFile.DropDownItems[CommonConstants.KeyToolStripSeparatorFileOpenDataDictionary]);
            Debug.Assert(m_ToolStripMenuItemFileExit != null, "ControlPanel.InitializeControlPanel() - m_ToolStripMenuItemFileExit != null");
            Debug.Assert(m_ToolStripSeparatorFileOpenDataDictionary != null, 
                "ControlPanel.InitializeControlPanel() - m_ToolStripSeparatorFileOpenDataDictionary != null");
            #endregion - [File] -

            #region - [View] -
            m_ToolStripMenuItemView = ((ToolStripMenuItem)MainWindow.MenuStrip.Items[CommonConstants.KeyMenuItemView]);
            Debug.Assert(m_ToolStripMenuItemView != null, "ControlPanel.InitializeControlPanel() - m_ToolStripMenuItemView != null");
            m_ToolStripMenuItemViewWatchWindow = ((ToolStripMenuItem)m_ToolStripMenuItemView.DropDownItems[CommonConstants.KeyMenuItemViewWatchWindow]);
            m_ToolStripMenuItemViewSystemInformation = ((ToolStripMenuItem)m_ToolStripMenuItemView.DropDownItems[CommonConstants.KeyMenuItemViewSystemInformation]);
            Debug.Assert(m_ToolStripMenuItemViewWatchWindow != null, "ControlPanel.InitializeControlPanel() - m_ToolStripMenuItemViewWatchWindow != null");
            Debug.Assert(m_ToolStripMenuItemViewSystemInformation != null, "ControlPanel.InitializeControlPanel() - m_ToolStripMenuItemViewSystemInformation != null");

            // Attach the EnabledChanged events to the event handlers.
            m_ToolStripMenuItemView.EnabledChanged += new EventHandler(ViewWatchWindow_EnabledChanged);
            m_ToolStripMenuItemViewWatchWindow.EnabledChanged += new EventHandler(ViewWatchWindow_EnabledChanged);

            m_ToolStripMenuItemView.EnabledChanged += new EventHandler(ViewSystemInformation_EnabledChanged);
            m_ToolStripMenuItemViewSystemInformation.EnabledChanged += new EventHandler(ViewSystemInformation_EnabledChanged);

            // Call each 'View' event handler in turn to ensure that the Enabled property of each button matches that of the corresponding ToolStripMenuItem.
            ViewWatchWindow_EnabledChanged(this, new EventArgs());
            ViewSystemInformation_EnabledChanged(this, new EventArgs());
            #endregion - [View] -

            #region - [Diagnostics] -
            m_ToolStripMenuItemDiagnostics = ((ToolStripMenuItem)MainWindow.MenuStrip.Items[CommonConstants.KeyMenuItemDiagnostics]);
            Debug.Assert(m_ToolStripMenuItemDiagnostics != null, "ControlPanel.InitializeControlPanel() - m_ToolStripMenuItemDiagnostics != null");
            m_ToolStripMenuItemDiagnosticsEventLog = ((ToolStripMenuItem)m_ToolStripMenuItemDiagnostics.DropDownItems[CommonConstants.KeyMenuItemDiagnosticsEventLog]);
            m_ToolStripMenuItemDiagnosticsSelfTests = ((ToolStripMenuItem)m_ToolStripMenuItemDiagnostics.DropDownItems[CommonConstants.KeyMenuItemDiagnosticsSelfTests]);
            m_ToolStripMenuItemDiagnosticsInitializeEventLogs =
                ((ToolStripMenuItem)m_ToolStripMenuItemDiagnostics.DropDownItems[CommonConstants.KeyMenuItemDiagnosticsInitializeEventLogs]);
            Debug.Assert(m_ToolStripMenuItemDiagnosticsEventLog != null, "ControlPanel.InitializeControlPanel() - m_ToolStripMenuItemDiagnosticsEventLog != null");
            Debug.Assert(m_ToolStripMenuItemDiagnosticsSelfTests != null, "ControlPanel.InitializeControlPanel() - m_ToolStripMenuItemDiagnosticsSelfTests != null");
            Debug.Assert(m_ToolStripMenuItemDiagnosticsInitializeEventLogs != null,
                         "ControlPanel.InitializeControlPanel() - m_ToolStripMenuItemDiagnosticsInitializeEventLogs != null");

            // Attach the EnabledChanged events to the event handlers.
            m_ToolStripMenuItemDiagnostics.EnabledChanged += new EventHandler(DiagnosticsEventLog_EnabledChanged);
            m_ToolStripMenuItemDiagnosticsEventLog.EnabledChanged += new EventHandler(DiagnosticsEventLog_EnabledChanged);

            m_ToolStripMenuItemDiagnostics.EnabledChanged += new EventHandler(DiagnosticsSelfTests_EnabledChanged);
            m_ToolStripMenuItemDiagnosticsSelfTests.EnabledChanged += new EventHandler(DiagnosticsSelfTests_EnabledChanged);

            m_ToolStripMenuItemDiagnostics.EnabledChanged += new EventHandler(DiagnosticsInitializeEventLogs_EnabledChanged);
            m_ToolStripMenuItemDiagnosticsInitializeEventLogs.EnabledChanged += new EventHandler(DiagnosticsInitializeEventLogs_EnabledChanged);

            // Call each 'Diagnostics'event handler in turn to ensure that the Enabled property of each button matches that of the corresponding ToolStripMenuItem.
            DiagnosticsEventLog_EnabledChanged(this, new EventArgs());
            DiagnosticsSelfTests_EnabledChanged(this, new EventArgs());
            DiagnosticsInitializeEventLogs_EnabledChanged(this, new EventArgs());
            #endregion - [Diagnostics] -

            #region - [Configure] -
            m_ToolStripMenuItemConfigure = ((ToolStripMenuItem)MainWindow.MenuStrip.Items[CommonConstants.KeyMenuItemConfigure]);
            Debug.Assert(m_ToolStripMenuItemConfigure != null, "ControlPanel.InitializeControlPanel() - m_ToolStripMenuItemConfigure != null");
            m_ToolStripMenuItemConfigurePasswordProtection =
                    ((ToolStripMenuItem)m_ToolStripMenuItemConfigure.DropDownItems[CommonConstants.KeyMenuItemConfigurePasswordProtection]);
            m_ToolStripSeparatorConfigurePasswordProtection =
                ((ToolStripSeparator)m_ToolStripMenuItemConfigure.DropDownItems[CommonConstants.KeyToolStripSeparatorConfigurePasswordProtection]);
            Debug.Assert(m_ToolStripMenuItemConfigurePasswordProtection != null,
                         "ControlPanel.InitializeControlPanel() - m_ToolStripMenuItemConfigurePasswordProtection != null");

            // Attach the EnabledChanged events to the event handlers.
            m_ToolStripMenuItemConfigure.EnabledChanged +=new EventHandler(ConfigurePasswordProtection_EnabledChanged);
            m_ToolStripMenuItemConfigurePasswordProtection.EnabledChanged += new EventHandler(ConfigurePasswordProtection_EnabledChanged);

            // Call each 'Diagnostics'event handler in turn to ensure that the Enabled property of each button matches that of the corresponding ToolStripMenuItem.
            ConfigurePasswordProtection_EnabledChanged(this, new EventArgs());
            #endregion - [Configure] -

            #region - [Help] -
            m_ToolStripMenuItemHelp = ((ToolStripMenuItem)MainWindow.MenuStrip.Items[CommonConstants.KeyMenuItemHelp]);
            Debug.Assert(m_ToolStripMenuItemHelp != null, "ControlPanel.InitializeControlPanel() - m_ToolStripMenuItemHelp != null");
            m_ToolStripMenuItemHelpPTUHelp = ((ToolStripMenuItem)m_ToolStripMenuItemHelp.DropDownItems[CommonConstants.KeyMenuItemHelpPTUHelp]);
            m_ToolStripSeparatorHelpPTUHelp = ((ToolStripSeparator)m_ToolStripMenuItemHelp.DropDownItems[CommonConstants.KeyToolStripSeparatorHelpPTUHelp]);
            Debug.Assert(m_ToolStripMenuItemHelpPTUHelp != null, "ControlPanel.InitializeControlPanel() - m_ToolStripMenuItemHelpPTUHelp != null");
            Debug.Assert(m_ToolStripSeparatorHelpPTUHelp != null, "ControlPanel.InitializeControlPanel() - m_ToolStripSeparatorHelpPTUHelp != null");
            #endregion - [Help] -
            #endregion - [Menu Items] -

            m_MdiPTU = this.Parent as MdiPTU;
            m_MdiPTU.MdiChildActivate += new EventHandler(MdiChildActivate);

            // Call the MdiChildActivate event handler to ensure that the Visible properties of this UserControl and the ToolStripFunctionKeys ToolStrip reflect the
            // current status.
            MdiChildActivate(this, new EventArgs());

            // Hide the menu options that have been replaced by Control Panel buttons whenever the menu is updated as a result of a security level or mode change.
            m_MdiPTU.MenuUpdated +=new EventHandler(MenuUpdated);

            // Call the MenuUpdated event handler to ensure that the menu options that have been replaced by Control Panel buttons are hidden.
            MenuUpdated(this, new EventArgs());
        }