// Created with MonoDevelop
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2021 Torsten Schache, Hiperscan GmbH Dresden, Germany
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

using System;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
using Gdk;
using Glade;
using Gtk;
using Hiperscan.Common.I18n;
using Hiperscan.Extensions.ApoIdent.Widgets;
using Hiperscan.GtkExtensions.Widgets;
using Hiperscan.Spectroscopy.IdentModule;
using Hiperscan.Unix;

namespace Hiperscan.Extensions.ApoIdent
{
    public partial class ApoIdentApplication
    {
        public const string FONT_FAMILIY = "Arial";
        public const double WIN_SCALE = 1.2;

        private const string ICON_KEY = "ICON_KEY";

        [Widget] Gtk.Window main_window = null;

        [Widget] Gtk.EventBox menu_eventbox = null;
        [Widget] Gtk.EventBox form_eventbox = null;

        [Widget] Gtk.Table main_table = null;
        [Widget] Gtk.Table form_table = null;

        [Widget] Gtk.EventBox line1_eventbox = null;
        [Widget] Gtk.EventBox line2_eventbox = null;
        [Widget] Gtk.EventBox line3_eventbox = null;
        [Widget] Gtk.EventBox line4_eventbox = null;
        [Widget] Gtk.EventBox line5_eventbox = null;
        [Widget] Gtk.EventBox line6_eventbox = null;

        [Widget] Gtk.ScrolledWindow main_scrolledwindow = null;
        [Widget] Gtk.Alignment main_alignment = null;

        [Widget] Gtk.Alignment substance_data_exchange_alignment = null;
        [Widget] Gtk.Alignment substance_classifier_change_alignment = null;
        [Widget] Gtk.Alignment substance_info_alignment = null;


        private void DrawGui()
        {
            Guid guid = Guid.NewGuid();
            this.Control.EnterGui(guid.ToString());

            Glade.XML gui = new Glade.XML(null, "Hiperscan.Extensions.ApoIdent.ApoIdentApplication.apo_ident_window.glade", "main_window", "Hiperscan");
            gui.Autoconnect(this);

            this.InitEvents();

            this.InitComboboxes(this.MainWindow);

            this.InitMainWindow();
            this.InitMenuSection();
            this.InitTestSection();
            this.InitSubstanceSection();
            this.InitSpecimenSection();
            this.InitMeasuringSection();
            this.InitResultSection();
            this.InitProtocolSection();
            this.InitAnimation();
            CellRendererInfo.Init();

            this.InitFontSizes();
            GtkExtensions.Widgets.Font.SetFont(this.MainWindow, ApoIdentApplication.FONT_FAMILIY);
            this.InitColorSchema();
            this.InitHelpMenue();

            this.InitWindowsStyle(this.MainWindow, ApoIdentApplication.WIN_SCALE);
            this.MainWindow.ShowAll();
            this.FineTuning();

            this.DesiredWindowWidth = this.main_table.Requisition.Width;
            this.DesiredWindowHeight = this.main_table.Requisition.Height;

            this.DesiredFormWidth = this.form_table.Requisition.Width;
            this.DesiredFormHeight = this.form_table.Requisition.Height;

            this.Control.LeaveGui(guid.ToString());
            this.Control.WaitForGuiUpdateFinished(guid.ToString());

            this.Control.Busy = true;
            this.Update(ApoIdentApplicationState.ProgramStart);

            this.MainWindow.QueueDraw();
            this.Control.Host.ProcessEvents();
        }

        private void InitMainWindow()
        {
            this.MainWindow.IconList = ApoIdentStock.FinderIcons;
            this.MainWindow.Title = "QuickStep " + Plugin.name + " " + this.Control.Host.MainWindowTitelExtension;

            this.MainWindow.SetWmclass(Plugin.name.ToLower(),
                                          Plugin.name.ToLower());
        }

        private void InitEvents()
        {
            this.MainWindow.Shown += (sender, e) => Console.WriteLine(main_window.Allocation.Width + "x" + this.main_window.Allocation.Height);
            this.MainWindow.ExposeEvent += this.OnDrawBackgroundImage;
            this.MainWindow.DeleteEvent += this.OnDeleteEvent;
            this.MainWindow.Realized += (sender, e) => this.BringWindowToFront(false);

            this.main_window.Realized += (sender, e) => this.MainWindow.QueueDraw();
            this.MainWindow.SizeRequested += (sender, e) => this.MainWindow.QueueDraw();
            this.form_table.SizeAllocated += this.OnFormTableSizeAllocated;

            this.MainWindow.FocusInEvent += this.OnMainWindowScanFocusedIn;
            this.MainWindow.FocusOutEvent += this.OnMainWindowScanFocusedOut;
        }

        private void InitMenuSection()
        {
            this.SetToolButtonIcon(this.menu_quickstep_toolbutton, ApoIdentIcon.QuickStep);
            this.SetToolButtonIcon(this.menu_exit_toolbutton, ApoIdentIcon.Exit);
            this.SetToolButtonIcon(this.menu_archive_toolbutton, ApoIdentIcon.Archive);
            this.SetToolButtonIcon(this.menu_query_toolbutton, ApoIdentIcon.Query);
            this.SetToolButtonIcon(this.menu_reset_toolbutton, ApoIdentIcon.Referencing);
            this.SetToolButtonIcon(this.menu_connect_toolbutton, ApoIdentIcon.Connect);
            this.SetToolButtonIcon(this.menu_settings_toolbutton, ApoIdentIcon.Settings);
            this.SetToolButtonIcon(this.menu_substance_toolbutton, ApoIdentIcon.Substance);
            this.SetToolButtonIcon(this.menu_help_toolbutton, ApoIdentIcon.Help);
            this.SetToolButtonIcon(this.menu_info_toolbutton, ApoIdentIcon.Info);
        }

        private void InitTestSection()
        {
            this.TestUserEntry = new OutLinedRegexEntry(this.test_user_entry);
            this.TestUserEntry.Regex = this.Control.ProtocolState.UserRegex;
            this.TestUserEntry.GtkEntry.MaxLength = 75;
            this.TestUserEntry.ErrorMessage = ValidatedWidget.DEFAULT_ERROR_MESSAGE;
            this.TestUserEntry.ValueChanged += this.OnTestUserEntryChanged;
            this.InitTestUserCompletion();
            this.GuiDesignerData.SetValidatedEntryColor(this.TestUserEntry);
        }

        private void InitSubstanceSection()
        {
            this.SubstanceValidationLinklabel = new LinkLabel(this.substance_validation_label);
            this.SubstanceValidationLinklabel.BgColor = ApoIdentColors.WHITE;
            this.SubstanceValidationLinklabel.Clicked += this.OnValidationReportButtonClicked;

            this.SubstanceSearchEntry = new OutLinedRegexEntry(this.substance_search_entry);
            this.SubstanceSearchEntry.IgnoreValidation = false;
            this.SubstanceSearchEntry.Regex = new Regex(@"\w{1}");
            this.SubstanceSearchEntry.ErrorMessage = ValidatedWidget.DEFAULT_ERROR_MESSAGE;
            this.GuiDesignerData.SetValidatedEntryColor(this.SubstanceSearchEntry);

            this.SubstanceBAKMarking = new BAKMarking(this.substance_bak_marking_hbox);
            this.SubstanceBAKMarking.SetState(BAKMarkingState.Yellow | BAKMarkingState.Orange | BAKMarkingState.Blue | BAKMarkingState.Red); //TODO delete

            this.SetButtonIcon(this.substance_classifier_change_button, ApoIdentIcon.ClassifierChange);
            this.SetButtonIcon(this.substance_data_exchange_button, ApoIdentIcon.DataExchangeLennartz);
            this.SetButtonIcon(this.substance_info_button, ApoIdentIcon.SubstanceWarning);

            this.InitSubstanceSearchEntry();

        }

        private void InitSpecimenSection()
        {
            this.SpecimenExpiryDateinklabel = new LinkLabel(this.specimen_expiry_date_label);
            this.SpecimenExpiryDateinklabel.BgColor = ApoIdentColors.WHITE;
            this.SpecimenExpiryDateinklabel.Clicked += this.OnBatchDeadLineClicked;

            this.SpecimenPpnEntry = new OutLinedRegexEntry(this.specimen_ppn_entry);
            this.SpecimenPpnEntry.IgnoreValidation = true;
            this.SpecimenPpnEntry.GtkEntry.MaxLength = 8;
            this.SpecimenPpnEntry.ValueChanged += this.OnPpnEntryChanged;
            this.GuiDesignerData.SetValidatedEntryColor(this.SpecimenPpnEntry);

            this.SpecimenBatchEntry = new OutLinedRegexEntry(this.specimen_batch_entry);
            this.SpecimenBatchEntry.Regex = this.Control.ProtocolState.BatchRegex;
            this.SpecimenBatchEntry.GtkEntry.MaxLength = 30;
            this.SpecimenBatchEntry.ErrorMessage = ValidatedWidget.DEFAULT_ERROR_MESSAGE;
            this.SpecimenBatchEntry.ValueChanged += this.OnBatchEntryChanged;
            this.GuiDesignerData.SetValidatedEntryColor(this.SpecimenBatchEntry);

            this.SpecimenSupplierEntry = new OutLinedRegexEntry(this.specimen_supplier_entry);
            this.SpecimenSupplierEntry.Regex = this.Control.ProtocolState.SupplierRegex;
            this.SpecimenSupplierEntry.GtkEntry.MaxLength = 75;
            this.SpecimenSupplierEntry.ErrorMessage = ValidatedWidget.DEFAULT_ERROR_MESSAGE;
            this.SpecimenSupplierEntry.ValueChanged += this.OnSupplierEntryChanged;
            this.GuiDesignerData.SetValidatedEntryColor(this.SpecimenSupplierEntry);

            this.SpecimenWeighingCorrEntry = new OutLinedRegexEntry(this.specimen_weighing_corr_entry);
            this.SpecimenWeighingCorrEntry.GtkEntry.MaxLength = 20;
            this.SpecimenWeighingCorrEntry.IgnoreValidation = true;
            this.SpecimenWeighingCorrEntry.ValueChanged += this.OnWeighingFactorEntryChanged;
            this.GuiDesignerData.SetValidatedEntryColor(this.SpecimenWeighingCorrEntry);

            this.SpecimenExpiryDateBox = new OutLinedValidatedMonthYearBox(
                this.specimen_year_combobox,
                DateTime.Now.Year,
                10,
                this.specimen_month_combobox,
                Locale.CurrentCulture);

            this.GuiDesignerData.SetValidatedWidgetColor(this.SpecimenExpiryDateBox.MonthBox);
            this.GuiDesignerData.SetValidatedWidgetColor(this.SpecimenExpiryDateBox.YearBox);
            this.SpecimenExpiryDateBox.MonthBox.ValueChanged += this.OnExpiryDateChanged;
            this.SpecimenExpiryDateBox.YearBox.ValueChanged += this.OnExpiryDateChanged;

            this.InitSpecimenSupplierCompletion();
        }

        private void InitMeasuringSection()
        {
            this.MeasuringButton = new MeasuringButton(this.measuring_start_button,
                                                       this.measuring_abort_button,
                                                       this.measuring_advice_label);
        }

        private void InitResultSection()
        {
            this.ResultNirLinklabel = new LinkLabel(this.result_nir_label);
            this.ResultNirLinklabel.BgColor = ApoIdentColors.WHITE;
            this.ResultNirLinklabel.Clicked += this.OnResultNirButtonClicked;

            this.ResultValuationLinklabel = new LinkLabel(this.result_valuation_label);
            this.ResultValuationLinklabel.BgColor = ApoIdentColors.WHITE;
            this.ResultValuationLinklabel.Clicked += this.OnResultValuationButtonClicked;

            this.ResultAdditionTestLinklabel = new LinkLabel(this.result_additional_test_label);
            this.ResultAdditionTestLinklabel.BgColor = ApoIdentColors.WHITE;
            this.ResultAdditionTestLinklabel.Clicked += this.OnResultAdditionalTestsClicked;

            this.ResultSuggestionLinklabel = new LinkLabel(this.result_suggestion_label);
            this.ResultSuggestionLinklabel.BgColor = ApoIdentColors.WHITE;
            this.ResultSuggestionLinklabel.Clicked += this.OnResultSuggestionButtonClicked;

            this.ResultCommentEntry = new OutLinedRegexEntry(this.result_comment_entry);
            this.ResultCommentEntry.GtkEntry.MaxLength = 150;
            this.ResultCommentEntry.ValueChanged += this.OnResultCommentEntryChanged;
            this.GuiDesignerData.SetValidatedEntryColor(this.ResultCommentEntry);

            this.ResultClassificationOutputLabel = new OutLinedRegexLabel(this.result_classification_output_label);
            this.ResultClassificationOutputLabel.IgnoreValidation = true;
            this.ResultClassificationOutputLabel.BgColor = ApoIdentColors.WHITE;
            this.ResultClassificationOutputLabel.OkColor = ApoIdentColors.WHITE;

            this.ResultAdditionlTestOutputLabel = new OutLinedRegexLabel(this.result_additional_test_output_label);
            this.ResultAdditionlTestOutputLabel.PlaceHolderText = Catalog.GetString("(empty)");
            this.ResultAdditionlTestOutputLabel.Text = this.ResultAdditionlTestOutputLabel.PlaceHolderText;
            this.ResultAdditionlTestOutputLabel.Regex = this.Control.ProtocolState.AdditionalTestRegex;
            this.ResultAdditionlTestOutputLabel.BgColor = ApoIdentColors.WHITE;
            this.GuiDesignerData.SetValidatedWidgetColor(this.ResultAdditionlTestOutputLabel);

            Gdk.Pixbuf pix_buf = new Pixbuf(null, "Hiperscan.Extensions.ApoIdent.ApoIdentApplication.Icons.ResultNegative.png", 50, 50);
            this.result_fail_image.Pixbuf = pix_buf;

            pix_buf = new Pixbuf(null, "Hiperscan.Extensions.ApoIdent.ApoIdentApplication.Icons.ResultPositive.png", 50, 50);
            this.result_ok_image.Pixbuf = pix_buf;
        }

        private void InitProtocolSection()
        {
            this.SetToolButtonIcon(this.protocol_save_toolbutton, ApoIdentIcon.Save);
            this.SetToolButtonIcon(this.protocol_pdf_toolbutton, ApoIdentIcon.Pdf);
            this.SetToolButtonIcon(this.protocol_print_toolbutton, ApoIdentIcon.Print);
            this.SetToolButtonIcon(this.protocol_label_print_toolbutton, ApoIdentIcon.LabelPrint);
        }

        private void InitAnimation()
        {
            this.Animation = new Animation(this.animation_state_image, 
                                             this.animation_state_label,
                                             this.animation_info_image, 
                                             this.animation_frame_eventbox,
                                             this.animation_menuline_alignment,
                                             this.GuiDesignerData.Logo,
                                             this.Control.Transaction);
        }


        private void SetToolButtonIcon(Gtk.ToolButton tb, ApoIdentIcon icon)
        {
            tb.Data.Clear();
            tb.Data.Add(ApoIdentApplication.ICON_KEY, icon);

            if (tb.IconWidget == null)
                tb.IconWidget = new Gtk.Image();

            ((Gtk.Image)tb.IconWidget).Pixbuf = this.GuiDesignerData.GetIconImage(icon);
            tb.IconWidget.ShowAll();
            tb.LabelWidget = new Gtk.Label(tb.Label);
            tb.LabelWidget.ShowAll();
        }

        private void SetToolButtonActiveState(ToolButton tb)
        {
            ApoIdentIcon icon = (ApoIdentIcon)tb.Data[ApoIdentApplication.ICON_KEY];

            if (tb.Sensitive)
                ((Gtk.Image)tb.IconWidget).Pixbuf = this.GuiDesignerData.GetIconImage(icon);
            else
                ((Gtk.Image)tb.IconWidget).Pixbuf = this.GuiDesignerData.GetIconInactiveImage(icon);
        }

        private void SetButtonIcon(Gtk.Button button, ApoIdentIcon icon)
        {
            button.Data.Clear();
            button.Data.Add(ApoIdentApplication.ICON_KEY, icon);

            if (button.Image == null)
                button.Image = new Gtk.Image();

            ((Gtk.Image)button.Image).Pixbuf = this.GuiDesignerData.GetIconImage(icon);
            button.Image.ShowAll();
        }

        private void SetButtonActiveState(Button button)
        {
            ApoIdentIcon icon = (ApoIdentIcon)button.Data[ApoIdentApplication.ICON_KEY];

            if (button.Sensitive)
                ((Gtk.Image)button.Image).Pixbuf = this.GuiDesignerData.GetIconImage(icon);
            else
                ((Gtk.Image)button.Image).Pixbuf = this.GuiDesignerData.GetIconInactiveImage(icon);
        }

        private void InitFontSizes()
        {
            Pango.FontDescription fd = null;
            double scale = 1.6;

            fd = this.big_test_label.Style.FontDesc.Copy();
            fd.Size = (int) (fd.Size * scale);
            this.big_test_label.ModifyFont(fd);

            fd = this.big_substance_label.Style.FontDesc.Copy();
            fd.Size = (int)(fd.Size * scale);
            this.big_substance_label.ModifyFont(fd);

            fd = this.big_specimen_label.Style.FontDesc.Copy();
            fd.Size = (int)(fd.Size * scale);
            this.big_specimen_label.ModifyFont(fd);

            fd = this.big_measuring_label.Style.FontDesc.Copy();
            fd.Size = (int)(fd.Size * scale);
            this.big_measuring_label.ModifyFont(fd);

            fd = this.big_result_label.Style.FontDesc.Copy();
            fd.Size = (int)(fd.Size * scale);
            this.big_result_label.ModifyFont(fd);

            fd = this.big_protocol_label.Style.FontDesc.Copy();
            fd.Size = (int)(fd.Size * scale);
            this.big_protocol_label.ModifyFont(fd);

            fd = this.ResultClassificationOutputLabel.GtkLabel.Style.FontDesc.Copy();
            fd.Size = (int)(fd.Size * scale * 0.8);
            this.ResultClassificationOutputLabel.GtkLabel.ModifyFont(fd);

            fd = this.state_device_label.Style.FontDesc.Copy();
            fd.Size = (int)(fd.Size * scale * 0.6);
            this.state_device_label.ModifyFont(fd);

            fd = this.state_devicetype_label.Style.FontDesc.Copy();
            fd.Size = (int)(fd.Size * scale * 0.6);
            this.state_devicetype_label.ModifyFont(fd);

            fd = this.measuring_time_label.Style.FontDesc.Copy();
            fd.Size = (int)(fd.Size * scale * 0.6);
            this.measuring_time_label.ModifyFont(fd);

            fd = this.measuring_time_output_label.Style.FontDesc.Copy();
            fd.Size = (int)(fd.Size * scale * 0.6);
            this.measuring_time_output_label.ModifyFont(fd);

        }

        private void InitSubstanceSearchEntry()
        {
            Console.WriteLine("Init auto completion substance search entry ...");
            CellRendererSubstanceCategory.Init();

            Gtk.EntryCompletion completion = new EntryCompletion();
            completion.InlineSelection = false;

            CellRendererSubstanceCategory substance_cell = new CellRendererSubstanceCategory();
            substance_cell.Xpad = 5;
            ///TODO scale windows
            Gtk.CellRendererText text_cell = new Gtk.CellRendererText();

            text_cell.Xpad = 5;

            completion.PackStart(substance_cell, false);
            completion.AddAttribute(substance_cell, CellRendererSubstanceCategory.GLIB_PROPERTY, 0);

            completion.PackStart(text_cell, false);
            completion.TextColumn = 1;

            completion.MatchFunc = this.MatchSubstance;
            completion.MatchSelected += this.OnSubstanceMatchSelected;

            ListStore store = new ListStore(typeof(SubstanceCategory), typeof(string), typeof(SubstanceListAutoCompletionEntry));
            completion.Model = store;
            this.substance_search_entry.Completion = completion;
        }

        private void InitTestUserCompletion()
        {
            ListStore store = new ListStore(typeof(String));
            foreach (string user in this.Config.GuiSettings.UserCompletion)
            {
                store.AppendValues(user);
            }
            this.test_user_entry.Completion = new EntryCompletion();
            this.test_user_entry.Completion.InlineSelection = false;
            this.test_user_entry.Completion.Model = store;
            this.test_user_entry.Completion.TextColumn = 0;
        }

        private void InitSpecimenSupplierCompletion()
        {
            ListStore store = new ListStore(typeof(String));
            this.Config.GuiSettings.UpdateSupplierCompletion(Hiperscan.Common.I18n.Locale.Language);
            foreach (string supplier in this.Config.GuiSettings.SupplierCompletion)
            {
                store.AppendValues(supplier);
            }
            this.SpecimenSupplierEntry.GtkEntry.Completion = new EntryCompletion();
            this.SpecimenSupplierEntry.GtkEntry.Completion.InlineSelection = false;
            this.SpecimenSupplierEntry.GtkEntry.Completion.Model = store;
            this.SpecimenSupplierEntry.GtkEntry.Completion.TextColumn = 0;
        }



        private void InitColorSchema()
        {
            this.SetMainColor();
            this.SetGrayColor();
        }

        private void SetGrayColor()
        {
            Gdk.Color color = ApoIdentColors.GRAY;

            WidgetColor.SetFontColor(this.measuring_time_label, color);
            WidgetColor.SetFontColor(this.measuring_time_output_label, color);

            color = ApoIdentColors.lIGHT_GRAY;

            this.line1_eventbox.ModifyBg(StateType.Normal, color);
            this.line2_eventbox.ModifyBg(StateType.Normal, color);
            this.line3_eventbox.ModifyBg(StateType.Normal, color);
            this.line4_eventbox.ModifyBg(StateType.Normal, color);
            this.line5_eventbox.ModifyBg(StateType.Normal, color);
            this.line6_eventbox.ModifyBg(StateType.Normal, color);


        }

        private void SetMainColor()
        {
            Gdk.Color color = ApoIdentColors.WHITE;

            this.form_eventbox.ModifyBg(StateType.Normal, color);
            this.protocol_toolbar.ModifyBg(StateType.Normal, color);
            this.state_eventbox.ModifyBg(StateType.Normal, color);

            this.menu_eventbox.ModifyBg(StateType.Normal, color);
            this.menu_toolbar.ModifyBg(StateType.Normal, color);
        }

        private void OnDrawBackgroundImage(object sender, EventArgs e)
        {
            Gdk.Window win = this.MainWindow.GdkWindow;

            if (win == null)
                return;

            if (this.MainWindow.Allocation.Width <= 1 || this.MainWindow.Allocation.Height <= 1)
                return;

            double scal_x = (double)this.MainWindow.Allocation.Width / 
                                        this.GuiDesignerData.BackGround.Width;
            double scal_y = (double)this.MainWindow.Allocation.Height / 
                                        this.GuiDesignerData.BackGround.Height;

            Cairo.Context ctx = Gdk.CairoHelper.Create(win);

            ctx.Rectangle(0, 0, this.MainWindow.Allocation.Width, this.MainWindow.Allocation.Height);
            ctx.SetSourceColor(new Cairo.Color(1, 1, 1));
            ctx.Fill();

            double y_pos = this.GuiDesignerData.BgYPosition / 100 / scal_y * this.MainWindow.Allocation.Height;

            ctx.Scale(scal_x, scal_y);
            this.GuiDesignerData.BackGround.Show(ctx, 0, y_pos);


            ((IDisposable)ctx.GetTarget()).Dispose();
            ((IDisposable)ctx).Dispose();
        }


        private void FineTuning()
        {
            this.ResultAdditionlTestOutputLabel.GtkLabel.HeightRequest = this.test_user_entry.Allocation.Height;
            ResultAdditionlTestOutputLabel.GtkLabel.Xpad = 5;

            this.substance_info_alignment.HeightRequest = this.substance_classifier_change_button.Allocation.Height;
            this.substance_data_exchange_alignment.HeightRequest = this.substance_classifier_change_button.Allocation.Height;
            this.substance_classifier_change_alignment.HeightRequest = this.substance_classifier_change_button.Allocation.Height;

            this.substance_classifier_change_button.Visible = false;

            this.test_user_entry.HasFocus = true;
        }

        private void OnFormTableSizeAllocated(object sender, EventArgs e)
        {
            int x_diff = this.form_table.Requisition.Width - this.DesiredFormWidth;
            if (x_diff > 0 && this.DesiredFormWidth > 0)
            {
                this.DesiredFormWidth += x_diff;
                this.DesiredWindowWidth += x_diff;
                this.main_table.WidthRequest = this.DesiredWindowWidth;
            }

            int y_diff = this.form_table.Requisition.Height - this.DesiredFormHeight;
            if (y_diff > 0 && this.DesiredFormHeight > 0)
            {
                this.DesiredFormHeight += y_diff;
                this.DesiredWindowHeight += y_diff;
                this.main_table.HeightRequest = this.DesiredWindowHeight;
            }
            
            this.SetScrolledWindow();
        }

        private void SetScrolledWindow()
        {
            Requisition desired_size = this.MainWindow.SizeRequest();
            int width = (int)((this.MainWindow.Screen.Width / this.MainWindow.Screen.NMonitors) * 0.9);
            int height = (int)((this.MainWindow.Screen.Height) * 0.9);

            bool can_maximize = this.main_scrolledwindow.HscrollbarPolicy == PolicyType.Never &&
                                   this.main_scrolledwindow.VscrollbarPolicy == PolicyType.Never;

            if (this.main_scrolledwindow.HscrollbarPolicy == PolicyType.Never)
            {
                if (desired_size.Width > width)
                {
                    this.DesiredFormWidth = -1;
                    this.main_table.WidthRequest = width / 2;
                    if (can_maximize)
                        this.main_window.Maximize();
                    this.main_scrolledwindow.HscrollbarPolicy = PolicyType.Automatic;
                    this.main_alignment.Xscale = 1;
                }
            }

            if (this.main_scrolledwindow.VscrollbarPolicy == PolicyType.Never)
            {
                if (desired_size.Height > height)
                {
                    this.DesiredFormHeight = -1;
                    this.main_table.HeightRequest = height / 2;
                    if (can_maximize)
                        this.main_window.Maximize();
                    this.main_scrolledwindow.VscrollbarPolicy = PolicyType.Automatic;
                }
            }
        }

        private void InitComboboxes(Gtk.Widget widget)
        {
            Gtk.ComboBox combobox = widget as Gtk.ComboBox;
            if (combobox != null)
            {
                ListStore store = new ListStore(typeof(string));
                CellRendererText cell__text = new CellRendererText();
                cell__text.Scale = Pango.Scale.Large;
                combobox.PackStart(cell__text, false);
                combobox.SetAttributes(cell__text, "text", 0);
                combobox.Model = store;
                combobox.AppendText(" ");
                combobox.Active = 0;
            }

            Gtk.Container container = widget as Gtk.Container;
            if (container == null)
                return;

            foreach (Widget child in container.Children)
                this.InitComboboxes(child);
        }




        public void InitWindowsStyle(Gtk.Widget widget, double scale)
        {
            if (Environment.OSVersion.Platform.ToString().ToLower().StartsWith("win", StringComparison.InvariantCulture) == false)
                return;
                
            Pango.FontDescription fd = null;

            /*
            Gtk.Label label = widget as Gtk.Label;
            if (label != null)
            {
                fd = label.Style.FontDesc.Copy();
                fd.Size = (int)(fd.Size * scale);
                label.ModifyFont(fd);
            }*/

            Gtk.Entry entry = widget as Gtk.Entry;
            if (entry != null)
            {
                fd = entry.Style.FontDesc.Copy();
                fd.Size = (int)(fd.Size * scale);
                entry.ModifyFont(fd);
            }

            Gtk.ComboBox combobox = widget as Gtk.ComboBox;
            if (combobox != null)
            {
                CellRendererText ct = combobox.Cells[0] as CellRendererText;
                ct.Scale = scale * 1.1;
            }

            Gtk.Container container = widget as Gtk.Container;
            if (container != null)
            {


                foreach (Widget child in container.Children)
                {
                    double factor = 1;
                    if (child == this.menu_toolbar)
                        factor = 0.75;

                    if (child == this.protocol_toolbar)
                        factor = 0.75;

                    if (child == this.state_alignment)
                        factor = 0.7;

                    this.InitWindowsStyle(child, scale * factor);
                }
            }
        }

        private void OnBgYPositionChanged(object sender, EventArgs e)
        {
            this.MainWindow.QueueDraw();
        }

        private void OnMeasuringButtonSizeChanged(object sender, EventArgs e)
        {
            if (this.MeasuringButton != null)
                this.MeasuringButton.ButtonSize = this.GuiDesignerData.MeasuringButtonSize;
        }

        private void OnMeasuringAlignemtChanged(object sender, EventArgs e)
        {
            if (this.MeasuringButton != null)
                this.MeasuringButton.ButtonAlignment = this.GuiDesignerData.MeasuringAlignment;
        }

        private void OnOuterLineWidthChanged(object sender, EventArgs e)
        {
            if (this.Animation != null)
                this.Animation.OuterLineWidth = this.GuiDesignerData.OuterLineWidth;
        }

        private void OnMenuLineWidthChanged(object sender, EventArgs e)
        {
            if (this.Animation != null)
                this.Animation.MenuLineWidth = this.GuiDesignerData.MenuLineeWidth;
        }

        private void OnStatebarTopWidthChanged(object sender, EventArgs e)
        {
            if (this.Animation != null)
                this.Animation.StatusbarTopLineWidth = this.GuiDesignerData.StateBarTopLineWidth;
        }

        private void OnStatebarLeftWidthChanged(object sender, EventArgs e)
        {
            if (this.Animation != null)
                this.Animation.StatusbarLeftLineWidth = this.GuiDesignerData.StateBarLeftLineWidth;
        }

        private void OnStatebarRightWidthChanged(object sender, EventArgs e)
        {
            if (this.Animation != null)
                this.Animation.StatusbarRightLineWidth = this.GuiDesignerData.StateBarRightLineWidth;
        }

        private Gtk.Window GetTmpWinodow()
        {
            Gtk.Window window = new Gtk.Window("Invisible");
            window.Visible = false;
            window.Decorated = false;
            window.Opacity = 0;
            window.NoShowAll = true;
            window.ShowAll();
            window.KeepAbove = true;
            window.Present();

            return window;
        }

        public Gtk.Window MainWindow
        {
            get
            {
                return this.main_window;
            }
        }



        private int DesiredWindowWidth { get; set; } = -1;
        private int DesiredWindowHeight { get; set; } = -1;
        private int DesiredFormWidth { get; set; } = -1;
        private int DesiredFormHeight { get; set; } = -1;

        public GuiDesigner GuiDesignerData { get; private set; }
        public SplashScreen SplashScreen { get; private set; }
    }

}
