Imports System.ComponentModel

Imports DevExpress.XtraGrid
Imports DevExpress.XtraGrid.Columns
Imports DevExpress.XtraGrid.Views.Grid
Imports DevExpress.XtraGrid.Views.Grid.ViewInfo
Imports DigitalData.Controls.LookupGrid
Imports System.Drawing
Imports DigitalData.GUIs.Common
Imports DevExpress.Utils.Filtering.Internal
Imports DevExpress.XtraEditors

Public Class frmFormDesigner
    Public ProfileId As Integer
    Public ProfileName As String
    Public ProfileObjectType As String
    Public Designer_Locked As Boolean = True
    Public NewControlSelected As String = ""

    ' Control Variables
    Private CurrentControl As Control = Nothing

    Private _Logger = LOGCONFIG.GetLogger()
    Private ControlCreator As ClassControlCreator

    ' Movement Variables
    Private Mouse_IsPressed As Boolean
    Private Mouse_IsMoving As Boolean
    Private Mouse_BeginLocation As Point
    Private Mouse_EndLocation As Point

    ' Windream List Data
    Private Windream_ChoiceLists As List(Of String)
    Private Source_AllIndicies As List(Of String)
    Private Source_VectorIndicies As List(Of String)
    Private Source_SimpleIndicies As List(Of String)
    Private Source_LookupIndicies As List(Of String)

    Private CurrentColumnId As Integer = 0
    Private pgControls_Focused As Boolean = False

    Public Sub Reload_ControlNameList()
        _Logger.debug("Reloading control name list")
        Dim oControlNameList = DatabaseFallback.GetDatatableECM($"
            SELECT NAME 
            FROM TBPM_PROFILE_CONTROLS
            WHERE 
            PROFIL_ID = {CURRENT_ProfilGUID} AND
            CTRL_TYPE <> 'LBL'
            ORDER BY NAME"
        )
        CURRENT_CONTROL_NAME_LIST = oControlNameList.AsEnumerable().
            Select(Function(row) ClassAllgemeineFunktionen.NotNullString(row.Item("NAME"), String.Empty)).
            ToList()
        _Logger.debug("Reloading control name list done!")
    End Sub

    Private Sub frmFormDesigner_Load(sender As Object, e As EventArgs) Handles Me.Load
        Try
            ControlCreator = New ClassControlCreator(LOGCONFIG)
            BarButtonItem3.Caption = "Designer locked"
            BarButtonItem3.ItemAppearance.Normal.BackColor = Color.Red
            Designer_Locked = True
            Mouse_IsPressed = False
            RibPGCtrlheight.Enabled = False
            RibPGCtrlWidth.Enabled = False
            RibbonGroupControls.Enabled = False
            RibbonGroupControlFunctions.Enabled = False

            ' Setzt den typ des SQL-Befehls für frmSQL_DESIGNER
            CURRENT_DESIGN_TYPE = "INPUT_INDEX"
            CHANGES_FORM_DESIGN = False

            ' Profil Name in Fenstertitel setzen
            Text = $"Validation Designer - Profil: {ProfileName}"
            bsitmProfilID.Caption = $"ProfilID: {ProfileId}"
            '  Try
            ' Windream initialisieren
            If IDB_ACTIVE = False Then
                'clsWindream.Create_Session()
                bbtnitButton.Visibility = DevExpress.XtraBars.BarItemVisibility.Never
            Else
                bbtnitButton.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
            End If


            'Windream Abfragen, sollten einmal beim Start des Formulars geladen werden
            Dim unsortedIndicies
            Dim sortedIndicies As List(Of String)
            If IDB_ACTIVE = False Then
                unsortedIndicies = WINDREAM_MOD.GetIndiciesByObjecttype(CURRENT_OBJECTTYPE).ToList()
                sortedIndicies = unsortedIndicies '.OrderBy(Function(index As String) index).ToList()
                sortedIndicies = sortedIndicies.OrderBy(Function(index As String) index).ToList
            Else
                sortedIndicies = IDBData.GetIndicesByBE(CURRENT_OBJECTTYPE).ToList()
            End If

            sortedIndicies.Add("@@DISPLAY_ONLY")
            Source_AllIndicies = sortedIndicies
            Source_VectorIndicies = Source_AllIndicies.FindAll(AddressOf IsVectorIndex)
            Source_SimpleIndicies = Source_AllIndicies.Except(Source_VectorIndicies).ToList()
            Source_LookupIndicies = Source_AllIndicies.
                        Where(AddressOf IsNotVectorBooleanIndex).
                        Where(AddressOf IsNotVectorDateIndex).
                        Where(AddressOf IsNotVectorDatetimeIndex).
                        Where(AddressOf IsNotBooleanIndex).
                        Where(AddressOf IsNotDateIndex).
                        ToList()

            If IDB_ACTIVE = False Then
                Windream_ChoiceLists = New List(Of String)
                Windream_ChoiceLists.Add(String.Empty)
                Windream_ChoiceLists.AddRange(WINDREAM_MOD.GetChoiceLists())
            End If

            'Catch ex As Exception
            '    _Logger.Error(ex)
            '    MsgBox("Fehler bei Initialisieren von windream: " & vbNewLine & ex.Message, MsgBoxStyle.Critical, "Achtung:")
            'End Try

            Try
                TBPM_PROFILE_CONTROLSTableAdapter.Connection.ConnectionString = CONNECTION_STRING_ECM
                TBDD_CONNECTIONTableAdapter.Connection.ConnectionString = CONNECTION_STRING_ECM
                TBWH_CHECK_PROFILE_CONTROLSTableAdapter.Connection.ConnectionString = CONNECTION_STRING_ECM
                TBPM_CONTROL_TABLETableAdapter.Connection.ConnectionString = CONNECTION_STRING_ECM
                TBDD_CONNECTIONTableAdapter.Fill(DD_DMSLiteDataSet.TBDD_CONNECTION)
            Catch ex As Exception
                _Logger.Error(ex)
                MsgBox("Fehler bei Laden der Connection-Strings und Grunddaten: " & vbNewLine & ex.Message, MsgBoxStyle.Critical, "Achtung:")
            End Try

            LoadControls()
        Catch ex As Exception
            _Logger.Error(ex)
            MsgBox(ex.Message, MsgBoxStyle.Critical, "error loading form:")
        End Try
    End Sub

    Private Sub frmFormDesigner_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
        If ProfileId > 0 Then
            Dim sql As String = $"SELECT NAME, INDEX_NAME FROM TBPM_PROFILE_CONTROLS WHERE PROFIL_ID = {ProfileId} AND CTRL_TYPE NOT IN ('BUTTON','LBL','LINE')"
            Dim dt As DataTable = DatabaseFallback.GetDatatableECM(sql) ', "frmFormDesigner_FormClosing")

            Dim missingIndexControls As New List(Of String)

            For Each row As DataRow In dt.Rows
                If ClassAllgemeineFunktionen.NotNullString(row.Item("INDEX_NAME"), String.Empty) = String.Empty Then
                    missingIndexControls.Add(row.Item("NAME"))
                End If
            Next

            If missingIndexControls.Count > 0 Then
                e.Cancel = True
                Dim missingControls As String = String.Join(vbCrLf, missingIndexControls.ToArray())
                MsgBox($"Für die folgenden Controls wurden noch keine Indexdefinitionen hinterlegt: {vbCrLf}{vbCrLf}{missingControls}")
            End If
        End If

        If Application.OpenForms().OfType(Of frmColumn_Detail).Any Then
            frmColumn_Detail.Close()
        End If

        ' Setzt den typ des SQL-Befehls für frmSQL_DESIGNER
        CURRENT_DESIGN_TYPE = "FINAL_INDEX"

        ' Beim Schließen das PropertyGrid leeren
        'pgControls.SelectedObject = Nothing
        pgControlsNew.SelectedObject = Nothing
    End Sub

    ''' <summary>
    ''' Filtert aus der Liste von Indexen die Vektor Indexe heraus
    ''' </summary>
    Private Function IsVectorIndex(IndexName As String) As Boolean
        Dim oType As Integer
        If IndexName = "@@DISPLAY_ONLY" Then
            Return 0
        End If
        If IDB_ACTIVE = False Then
            oType = WINDREAM_MOD.GetIndexType(IndexName)
        Else
            oType = IDBData.GetTypeOfIndex(IndexName)
        End If

        Return FINALINDICES.IsVectorIndex(oType)
    End Function

    Private Function IsNotBooleanIndex(IndexName As String) As Boolean
        Dim oType As Integer '= WINDREAM_MOD.GetIndexType(IndexName)
        If IDB_ACTIVE = False Then
            oType = WINDREAM_MOD.GetIndexType(IndexName)
        Else
            oType = IDBData.GetTypeOfIndex(IndexName)
        End If
        Return oType <> FINALINDICES.INDEX_TYPE_BOOLEAN
    End Function

    Private Function IsNotDateIndex(IndexName As String) As Boolean
        Dim oType As Integer '= WINDREAM_MOD.GetIndexType(IndexName)
        If IDB_ACTIVE = False Then
            oType = WINDREAM_MOD.GetIndexType(IndexName)
        Else
            oType = IDBData.GetTypeOfIndex(IndexName)
        End If
        Return oType <> FINALINDICES.INDEX_TYPE_DATE
    End Function

    Private Function IsNotVectorBooleanIndex(IndexName As String) As Boolean
        Dim oType As Integer '= WINDREAM_MOD.GetIndexType(IndexName)
        If IDB_ACTIVE = False Then
            oType = WINDREAM_MOD.GetIndexType(IndexName)
        Else
            oType = IDBData.GetTypeOfIndex(IndexName)
        End If
        Return oType <> FINALINDICES.INDEX_TYPE_VECTOR_BOOLEAN
    End Function

    Private Function IsNotVectorDateIndex(IndexName As String) As Boolean
        Dim oType As Integer '= WINDREAM_MOD.GetIndexType(IndexName)
        If IDB_ACTIVE = False Then
            oType = WINDREAM_MOD.GetIndexType(IndexName)
        Else
            oType = IDBData.GetTypeOfIndex(IndexName)
        End If
        Return oType <> FINALINDICES.INDEX_TYPE_VECTOR_DATE
    End Function

    Private Function IsNotVectorDatetimeIndex(IndexName As String) As Boolean
        Dim oType As Integer '= WINDREAM_MOD.GetIndexType(IndexName)
        If IDB_ACTIVE = False Then
            oType = WINDREAM_MOD.GetIndexType(IndexName)
        Else
            oType = IDBData.GetTypeOfIndex(IndexName)
        End If
        Return oType <> FINALINDICES.INDEX_TYPE_VECTOR_DATETIME
    End Function
    Sub LoadControls()
        Try
            TBPM_PROFILE_CONTROLSTableAdapter.FillByProfil(DD_DMSLiteDataSet.TBPM_PROFILE_CONTROLS, USER_LANGUAGE, ProfileId)
            TBPM_CONTROL_TABLETableAdapter.FillAll(DD_DMSLiteDataSet.TBPM_CONTROL_TABLE)

            ' löscht alle Controls
            pnldesigner.Controls.Clear()

            Dim dt As DataTable = DD_DMSLiteDataSet.TBPM_PROFILE_CONTROLS
            For Each row As DataRow In dt.Rows
                ' Ein Base Control erstellen
                Dim guid As Integer = row.Item("GUID")
                Dim name As String = row.Item("NAME")
                Dim x As Integer = row.Item("X_LOC")
                Dim y As Integer = row.Item("Y_LOC")
                Dim style As FontStyle = ClassAllgemeineFunktionen.NotNullString(row.Item("FONT_STYLE"), FontStyle.Regular)
                Dim size As Single = ClassAllgemeineFunktionen.NotNullString(row.Item("FONT_SIZE"), 10)
                Dim familyString As String = ClassAllgemeineFunktionen.NotNullString(row.Item("FONT_FAMILY"), "Arial")
                Dim family As FontFamily = New FontFamily(familyString)
                Dim font As New Font(family, size, style, GraphicsUnit.Point)
                Dim color As Color = IntToColor(ClassAllgemeineFunktionen.NotNullString(row.Item("FONT_COLOR"), 0))


                ' Jetzt die Control spezifischen Eigenschaften zuweisen
                Select Case row.Item("CTRL_TYPE")
                    Case ClassControlCreator.PREFIX_TEXTBOX
                        Dim txt = ControlCreator.CreateExistingTextbox(row, True)
                        pnldesigner.Controls.Add(txt)
                        SetMovementHandlers(txt)

                    Case ClassControlCreator.PREFIX_LABEL
                        Dim lbl = ControlCreator.CreateExistingLabel(row, True)
                        pnldesigner.Controls.Add(lbl)
                        SetMovementHandlers(lbl)


                    Case "CMB"
                        Dim cmb = ControlCreator.CreateExistingCombobox(row, True)
                        pnldesigner.Controls.Add(cmb)
                        SetMovementHandlers(cmb)

                    Case "DTP"
                        Dim dtp = ControlCreator.CreateExistingDatepicker(row, True)
                        pnldesigner.Controls.Add(dtp)
                        SetMovementHandlers(dtp)

                    Case "CHK"
                        Dim chk = ControlCreator.CreateExisingCheckbox(row, True)
                        pnldesigner.Controls.Add(chk)
                        SetMovementHandlers(chk)

                    Case "DGV"
                        Dim dgv = ControlCreator.CreateExistingDataGridView(row, True)
                        pnldesigner.Controls.Add(dgv)
                        SetMovementHandlers(dgv)

                    Case "TABLE"
                        Try
                            Dim oSQL = $"Select IIF(LANG.CAPTION Is NULL,T.SPALTEN_HEADER,LANG.CAPTION) SPALTEN_HEADER_LANG, T.* FROM TBPM_CONTROL_TABLE T
                            INNER JOIN TBPM_PROFILE_CONTROLS T1 ON T.CONTROL_ID = T1.GUID LEFT JOIN (SELECT * FROM TBPM_CONTOL_TABLE_LANG WHERE LANG_CODE = '{USER_LANGUAGE}') LANG ON T.GUID = LANG.COL_ID  
                            WHERE T1.CONTROL_ACTIVE = 1  AND  T.CONTROL_ID = T1.GUID AND T.CONTROL_ID = {guid} ORDER BY T.SEQUENCE"
                            Dim oDTColumnsPerDevExGrid As DataTable = DatabaseFallback.GetDatatableECM(oSQL) ', "FDesignLaodControls")


                            Dim table = ControlCreator.CreateExistingGridControl(row, oDTColumnsPerDevExGrid, True, "EUR")

                            AddHandler table.MouseClick, AddressOf gridControl_MouseClick
                            ' AddHandler table.ColumnHeaderMouseClick, AddressOf table_ColumnHeaderMouseClick

                            pnldesigner.Controls.Add(table)
                            SetMovementHandlers(table)
                        Catch ex As Exception
                            _Logger.Error(ex)
                            MsgBox("Error while loading Table Control with Id " & guid & vbNewLine & ex.Message, MsgBoxStyle.Critical, "Achtung:")
                        End Try


                    Case "LOOKUP"
                        Dim lookup = ControlCreator.CreateExistingLookupControl(row, True)
                        pnldesigner.Controls.Add(lookup)
                        SetMovementHandlers(lookup)

                    Case "LINE"
                        Dim line = ControlCreator.CreateExistingLine(row, True)
                        pnldesigner.Controls.Add(line)
                        SetMovementHandlers(line)
                    Case "BUTTON"
                        Dim oButton = ControlCreator.CreateExistingButton(row, True)
                        pnldesigner.Controls.Add(oButton)
                        SetMovementHandlers(oButton)
                End Select
            Next
        Catch ex As Exception
            _Logger.Error(ex)
            MsgBox("Unexpected error in LoadControls " & vbNewLine & ex.Message, MsgBoxStyle.Critical, "Achtung:")
        End Try

    End Sub

    Private Function GetLastID()
        Dim sql = String.Format("SELECT MAX(GUID) FROM TBPM_PROFILE_CONTROLS WHERE PROFIL_ID = {0}", ProfileId)
        Return DatabaseFallback.GetScalarValueECM(sql)
    End Function

    Sub SetActiveControlColor()
        If DirectCast(CurrentControl.Tag, ClassControlCreator.ControlMetadata).ReadOnly = False Then
            CurrentControl.BackColor = Color.DarkOrange
        End If

        ' Reset Color of all other controls
        For Each oControl As Control In Me.pnldesigner.Controls
            If oControl.Name <> CurrentControl.Name Then
                Dim oMetadata = DirectCast(oControl.Tag, ClassControlCreator.ControlMetadata)

                If oMetadata.ReadOnly = False Then

                    Select Case oControl.GetType()
                        Case GetType(TextEdit)
                            oControl.BackColor = Color.White
                        Case GetType(System.Windows.Forms.ComboBox)
                            oControl.BackColor = Color.White
                        Case GetType(System.Windows.Forms.Label)
                            oControl.BackColor = Color.Transparent
                        Case GetType(System.Windows.Forms.CheckBox)
                            oControl.BackColor = Color.Transparent
                        Case GetType(taskFLOW.ClassControlCreator.LineLabel)
                            oControl.BackColor = oControl.ForeColor
                        Case GetType(DigitalData.Controls.LookupGrid.LookupControl3)
                            oControl.BackColor = Color.White
                        Case GetType(System.Windows.Forms.Button)
                            oControl.BackColor = SystemColors.Control
                    End Select
                End If
            End If
        Next
    End Sub

    Public Sub gridControl_MouseClick(sender As GridControl, e As MouseEventArgs)
        Try
            If Designer_Locked = True Then
                Exit Sub
            End If
            Dim oView As GridView = sender.DefaultView
            Dim oHitinfo As GridHitInfo = oView.CalcHitInfo(sender.PointToClient(Cursor.Position))

            CurrentControl = sender
            CURRENT_CONTROL_ID = DirectCast(sender.Tag, ClassControlCreator.ControlMetadata).Guid

            If oHitinfo.IsValid And oHitinfo.InColumn Then
                Dim oColumn As GridColumn = oHitinfo.Column

                If oColumn Is Nothing Then
                    Exit Sub
                End If

                Dim oColumnCaption As String = oColumn.Caption
                Dim oColumnName As String = oColumn.FieldName
                Dim oColumnId = TBPM_CONTROL_TABLETableAdapter.getColumnID(CURRENT_CONTROL_ID, oColumnName)

                CurrentColumnId = oColumnId

                Dim frmTableColumn = New frmColumn_Detail()
                frmTableColumn.FillData(CurrentColumnId)
                frmTableColumn.Text = "Konfiguration von Spalte: " & oColumnCaption
                Dim oResult = frmTableColumn.ShowDialog()

                LoadControls()

            ElseIf oHitinfo.IsValid And e.Button = MouseButtons.Right Then
                GridControlContextMenu.Show(Cursor.Position.X, Cursor.Position.Y)
            End If
        Catch ex As Exception
            _Logger.Error(ex)
            MsgBox("Error while loading Column Configuration: " & vbCrLf & ex.Message, MsgBoxStyle.Critical)
        End Try
    End Sub
    Sub Control_Delete()
        If CurrentControl Is Nothing = False Then
            Dim result As MsgBoxResult = MsgBox("Wollen Sie das Control: " & CurrentControl.Name & " wirklich löschen?", MsgBoxStyle.YesNo, "Bestätigung:")
            ' wenn Speichern ja
            If result = MsgBoxResult.Yes Then
                DeleteControl(CurrentControl.Name)
                'pgControls.Enabled = False
                pgControlsNew.Enabled = False
                tslblAenderungen.Caption = $"Control {CurrentControl.Name} deleted - " + Now.ToString
                CurrentControl = Nothing
                RibPGCtrlheight.Enabled = False
                RibPGCtrlWidth.Enabled = False

                Reload_ControlNameList()

            End If

        End If
    End Sub
    Sub DeleteControl(controlName As String)
        Try
            Dim controlId As Integer = TBPM_PROFILE_CONTROLSTableAdapter.cmdGetGUID(ProfileId, controlName)
            If controlId > 0 Then
                TBPM_CONTROL_TABLETableAdapter.DeleteColumnsByControlId(controlId)
                TBPM_PROFILE_CONTROLSTableAdapter.Delete(controlId)
                LoadControls()
            End If
        Catch ex As Exception
            _Logger.Error(ex)
            MsgBox(ex.Message, MsgBoxStyle.Critical, "DeleteControl:")
        End Try
    End Sub


    ' +++ Public Helper Methods +++
    Public Function GetCursorPosition() As Point
        Return pnldesigner.PointToClient(Cursor.Position)
    End Function

    ''' <summary>
    ''' Setzt die Eventhandler für ein Control, die für die Bewegung via Drag & Drop und das Laden der Eigentschaften verantwortlich sind
    ''' </summary>
    ''' <param name="control">Das Control, für das die Eventhandler gesetzt werden sollen</param>
    Private Sub SetMovementHandlers(control As Control)
        AddHandler control.MouseDown, AddressOf OnControl_MouseDown
        AddHandler control.MouseUp, AddressOf OnControl_MouseUp
        AddHandler control.MouseMove, AddressOf OnControl_MouseMove
    End Sub

    Private Sub OnControl_MouseDown(sender As Control, e As MouseEventArgs)
        If e.Button = MouseButtons.Left Then
            If Designer_Locked Then
                Exit Sub
            End If
            CurrentControl = sender
            Mouse_BeginLocation = e.Location
            sender.BringToFront()
            RibbonGroupControlFunctions.Enabled = True
            Mouse_IsPressed = True
            RibPGCtrlheight.Enabled = True
            RibPGCtrlWidth.Enabled = True
            Console.WriteLine("CURRENT_CONTROL:" & CurrentControl.Name)
        End If
    End Sub

    Private Sub OnControl_MouseUp(sender As Control, e As MouseEventArgs)
        Try
            If Designer_Locked Then
                Exit Sub
            End If
            Mouse_IsPressed = False
            If (TypeOf sender Is LookupControl3 Or TypeOf sender Is Windows.Forms.ComboBox) Then
                RibPGCtrlheight.Enabled = False
            Else
                RibPGCtrlheight.Enabled = True
            End If
            ' Control Eigenschaften laden
            LoadControlProperties(sender)

            If Mouse_IsMoving = False Then
                MyBase.Cursor = Cursors.Default
                Exit Sub
            End If

            Mouse_IsMoving = False

            Dim CurrentPosition = CurrentControl.Location

            'Dim OldPosition As Point = DirectCast(pgControls.SelectedObject, BaseProperties).Location
            Dim OldPosition As Point = DirectCast(pgControlsNew.SelectedObject, BaseProperties).Location

            If CurrentPosition.X = OldPosition.X + 2 And CurrentPosition.Y = OldPosition.Y + 2 Then
                CurrentControl.Location = New Point(CurrentPosition.X - 2, CurrentPosition.Y - 2)
                MyBase.Cursor = Cursors.Default
                Exit Sub
            End If

            If Not Point.op_Inequality(CurrentPosition, OldPosition) Then
                MyBase.Cursor = Cursors.Default
                Exit Sub
            End If

            ' Das Control sollte nicht außerhalb des Panels geschoben werden (Koordinaten kleiner 0)
            If CurrentPosition.X < 0 Then
                CurrentControl.Location = New Point(0, CurrentControl.Location.Y)
            End If

            If CurrentPosition.Y < 0 Then
                CurrentControl.Location = New Point(CurrentControl.Location.X, 0)
            End If

            ' Ebenso nicht über die Größe des Panels (X-Achse)
            If CurrentPosition.X > pnldesigner.Width Then
                CurrentControl.Location = New Point(pnldesigner.Width - CurrentControl.Width, CurrentControl.Location.Y)
            End If

            ' Ebenso nicht über die Größe des Panels (Y-Achse)
            If CurrentPosition.Y > pnldesigner.Height Then
                CurrentControl.Location = New Point(CurrentControl.Location.X, pnldesigner.Height - CurrentControl.Height)
            End If

            'DirectCast(pgControls.SelectedObject, BaseProperties).Location = CurrentControl.Location
            DirectCast(pgControlsNew.SelectedObject, BaseProperties).Location = CurrentControl.Location
            pgControlsNew.UpdateData()

            UpdateSingleValue("X_LOC", CurrentControl.Location.X)
            UpdateSingleValue("Y_LOC", CurrentControl.Location.Y)

            MyBase.Cursor = Cursors.Default
        Catch ex As Exception
            MsgBox(ex.Message, MsgBoxStyle.Critical)
            _Logger.Error(ex)
            Mouse_IsMoving = False
            Mouse_IsPressed = False
        End Try

    End Sub

    Private Sub OnControl_MouseMove(sender As Control, e As MouseEventArgs)
        Try
            If Designer_Locked Then
                Exit Sub
            End If
            If CurrentControl Is Nothing Then
                Exit Sub
            End If

            Mouse_IsMoving = True

            If Mouse_IsPressed Then
                Cursor = Cursors.Hand
                Refresh()

                Dim CurrentPosition As Point = GetCursorPosition()

                If Point.op_Inequality(CurrentPosition, Mouse_BeginLocation) Then
                    CurrentControl.Location = New Point(CurrentPosition.X - Mouse_BeginLocation.X, CurrentPosition.Y - Mouse_BeginLocation.Y)
                End If
            End If
        Catch ex As Exception
            _Logger.Error(ex)
            Mouse_IsMoving = False
        End Try
    End Sub

    ''' <summary>
    ''' Weist die grundlegenden Eigenschaften zu einem Properties Objekt zu
    ''' Die Properties werden an das Property Grid weitergegeben
    ''' </summary>
    ''' <param name="obj">Das grundlegende Properties Objekt</param>
    ''' <param name="row">Die DataRow, die die Eigenschaften des Controls enthält</param>
    ''' <returns>Das gefüllt Properties Objekt</returns>
    Private Function CreatePropsObject(obj As BaseProperties, row As DataRow, Optional indicies As List(Of String) = Nothing)
        obj.ID = row.Item("GUID")
        obj.Location = New Point(row.Item("X_LOC"), row.Item("Y_LOC"))
        obj.Name = row.Item("NAME")
        obj.Size = New Size(row.Item("WIDTH"), row.Item("HEIGHT"))
        obj.ChangedAt = ClassAllgemeineFunktionen.NotNullDate(row.Item("CHANGED_WHEN"), Nothing)
        obj.ChangedWho = ClassAllgemeineFunktionen.NotNullString(row.Item("CHANGED_WHO"), "")

        Dim oStyle As FontStyle = ClassAllgemeineFunktionen.NotNullString(row.Item("FONT_STYLE"), FontStyle.Regular)
        Dim oSize As Single = ClassAllgemeineFunktionen.NotNullString(row.Item("FONT_SIZE"), 10)
        Dim oFamilyString As String = ClassAllgemeineFunktionen.NotNullString(row.Item("FONT_FAMILY"), "Arial")
        Dim oFamily As FontFamily = New FontFamily(oFamilyString)

        obj.Font = New Font(oFamily, oSize, oStyle)

        Dim oColor As Integer = ClassAllgemeineFunktionen.NotNullString(row.Item("FONT_COLOR"), 0)

        obj.TextColor = IntToColor(oColor)
        obj.TextAlignment = ClassAllgemeineFunktionen.NotNullString(row.Item("TEXT_ALIGNMENT"), "Near")

        Return obj
    End Function

    ''' <summary>
    ''' Funktioniert wie CreatePropsObject mit dem Unterschied, dass zusätzlich noch eine Liste von Indicies übergeben wird
    ''' Diese können dann im PropertyGrid angezeigt und ausgewählt werden.
    ''' Außerdem werden noch einige Eigenschaften gesetzt, die alle Controls (außer reine Anzeige-Controls) haben
    ''' </summary>
    ''' <param name="obj">Das grundlegende Properties Objekt</param>
    ''' <param name="row">Die DataRow, die die Eigenschaften des Controls enthält</param>
    ''' <param name="indicies">Eine Liste von Indicies</param>
    ''' <returns>Das gefüllt Properties Objekt</returns>
    Private Function CreatePropsObjectWithIndicies(obj As InputProperties, row As DataRow, indicies As List(Of String))
        obj = CreatePropsObject(obj, row)
        obj.Indicies = indicies
        obj.ReadOnly = StrToBool(row.Item("READ_ONLY"))
        obj.SaveChangeOnReadOnly = StrToBool(row.Item("SAVE_CHANGE_ON_ENABLED"))
        obj.Required = StrToBool(row.Item("VALIDATION"))
        obj.Active = StrToBool(row.Item("CONTROL_ACTIVE"))
        obj.Index = ClassAllgemeineFunktionen.NotNullString(row.Item("INDEX_NAME"), "")
        obj.DefaultValue = ClassAllgemeineFunktionen.NotNullString(row.Item("DEFAULT_VALUE"), Nothing)
        obj.TextAlignment = ClassAllgemeineFunktionen.NotNullString(row.Item("TEXT_ALIGNMENT"), "Near")
        ' Default value for ConnectionID
        Dim oConnectionId = ClassAllgemeineFunktionen.NotNullString(row.Item("CONNECTION_ID"), 0)
        obj.SQLCommand = New SQLValue(row.Item("SQL_UEBERPRUEFUNG"))
        Return obj
    End Function

    Private Sub LoadControlProperties(sender As Control)
        Try
            Dim props
            Dim oDatatable As DataTable = DD_DMSLiteDataSet.TBPM_PROFILE_CONTROLS
            Dim oRow As DataRow

            'pgControls.Enabled = True
            pgControlsNew.Enabled = True

            ' Beim Laden der Eigenschaften eines Controls muss die ganze Datatable neu geladen werden
            ' Nicht wirklich, aber gibt gerade keine bessere Möglichkeit, ohne alle SQL Abfragen selbst auszuführen
            Try
                TBPM_PROFILE_CONTROLSTableAdapter.FillByProfil(DD_DMSLiteDataSet.TBPM_PROFILE_CONTROLS, USER_LANGUAGE, ProfileId)
            Catch ex As Exception
                _Logger.Error(ex)
                _Logger.Info("Error while executing TBPM_PROFILE_CONTROLSTableAdapter.FillByProfil in LoadControlProperties:")
                _Logger.Info(ex)
            End Try

            Dim oControlId = DirectCast(sender.Tag, ClassControlCreator.ControlMetadata).Guid

            oRow = oDatatable.AsEnumerable().Where(Function(r As DataRow)
                                                       Return r.Item("GUID") = oControlId
                                                   End Function).SingleOrDefault()

            ' Control-Id wurde nicht in DataRow gefunden
            If IsNothing(oRow) Then
                _Logger.Info($"Error while filtering Controls by Guid '{oControlId}' in LoadControlProperties:")
                MsgBox($"Control mit der Id {oControlId} wurde nicht gefunden!", MsgBoxStyle.Critical, "Fehler beim Laden der Control Eigenschaften")

                Exit Sub
            End If

            ' Globale Variablen setzen
            CurrentControl = sender
            CURRENT_CONTROL_ID = oControlId

            SetActiveControlColor()

            ' Mithilfe von CreatePropsObject(WithIndicies) wird ein Basis Objekt mit grundlegenden
            ' Eigenschaften angelegt. Danach können für jeden Control Typ spezifische Eigenschaften festgelegt werden.
            If TypeOf sender Is ClassControlCreator.LineLabel Then
                Dim line As ClassControlCreator.LineLabel = sender
                Dim lineProps As LineLabelProperties = CreatePropsObject(New LineLabelProperties, oRow)

                props = lineProps
            ElseIf TypeOf sender Is Label Then
                Dim label As Label = sender
                Dim labelProps As LabelProperties = CreatePropsObject(New LabelProperties, oRow)
                labelProps.Text = label.Text

                props = labelProps
            ElseIf TypeOf sender Is CheckBox Then
                Dim check As CheckBox = sender
                Dim checkProps As CheckboxProperties = CreatePropsObjectWithIndicies(New CheckboxProperties, oRow, Source_AllIndicies)
                checkProps.Text = check.Text
                checkProps.Enable_SQL = New SQLValue(ClassAllgemeineFunktionen.NotNullString(oRow.Item("SQL_ENABLE"), ""))
                checkProps.Enable_SQL_OnLoad = New SQLValue(ClassAllgemeineFunktionen.NotNullString(oRow.Item("SQL_ENABLE_ON_LOAD"), ""))
                checkProps.SetControlData = New SQLValue(ClassAllgemeineFunktionen.NotNullString(oRow.Item("SET_CONTROL_DATA"), ""))
                props = checkProps
            ElseIf TypeOf sender Is LookupControl3 Then
                Dim oLookup As LookupControl3 = sender
                Dim lookupProps As LookupControlProperties = CreatePropsObjectWithIndicies(New LookupControlProperties, oRow, Source_AllIndicies)
                lookupProps.MultiSelect = StrToBool(oRow.Item("MULTISELECT"))
                lookupProps.PreventDuplicates = StrToBool(oRow.Item("VKT_PREVENT_MULTIPLE_VALUES"))
                lookupProps.AllowAddNewValues = StrToBool(oRow.Item("VKT_ADD_ITEM"))
                lookupProps.DisplayAsComboBox = False
                lookupProps.Enable_SQL = New SQLValue(ClassAllgemeineFunktionen.NotNullString(oRow.Item("SQL_ENABLE"), ""))
                lookupProps.Enable_SQL_OnLoad = New SQLValue(ClassAllgemeineFunktionen.NotNullString(oRow.Item("SQL_ENABLE_ON_LOAD"), ""))
                lookupProps.SetControlData = New SQLValue(ClassAllgemeineFunktionen.NotNullString(oRow.Item("SET_CONTROL_DATA"), ""))

                props = lookupProps
            ElseIf TypeOf sender Is TextEdit Then
                'Dim txt As TextEdit = sender
                Dim txtProps As TextboxProperties = CreatePropsObjectWithIndicies(New TextboxProperties, oRow, Source_AllIndicies)
                txtProps.Regex = ClassAllgemeineFunktionen.NotNullString(oRow.Item("REGEX_MATCH"), String.Empty)
                txtProps.RegexMessage = ClassAllgemeineFunktionen.NotNullString(oRow.Item("REGEX_MESSAGE_DE"), String.Empty)
                txtProps.Enable_SQL = New SQLValue(ClassAllgemeineFunktionen.NotNullString(oRow.Item("SQL_ENABLE"), ""))
                txtProps.Enable_SQL_OnLoad = New SQLValue(ClassAllgemeineFunktionen.NotNullString(oRow.Item("SQL_ENABLE_ON_LOAD"), ""))
                txtProps.SetControlData = New SQLValue(ClassAllgemeineFunktionen.NotNullString(oRow.Item("SET_CONTROL_DATA"), ""))
                txtProps.DisplayFormat = ClassAllgemeineFunktionen.NotNullString(oRow.Item("FORMAT_STRING"), ClassControlCreator.CONTROL_TYPE_TEXT)

                props = txtProps

            ElseIf TypeOf sender Is Windows.Forms.ComboBox Then
                Dim cmb As Windows.Forms.ComboBox = sender
                Dim cmbProps As ComboboxProperties = CreatePropsObjectWithIndicies(New ComboboxProperties, oRow, Source_AllIndicies)
                cmbProps.ChoiceLists = Windream_ChoiceLists
                cmbProps.ChoiceList = ClassAllgemeineFunktionen.NotNullString(oRow.Item("CHOICE_LIST"), String.Empty)
                cmbProps.Enable_SQL = New SQLValue(ClassAllgemeineFunktionen.NotNullString(oRow.Item("SQL_ENABLE"), ""))
                cmbProps.Enable_SQL_OnLoad = New SQLValue(ClassAllgemeineFunktionen.NotNullString(oRow.Item("SQL_ENABLE_ON_LOAD"), ""))
                cmbProps.SetControlData = New SQLValue(ClassAllgemeineFunktionen.NotNullString(oRow.Item("SET_CONTROL_DATA"), ""))
                props = cmbProps
                cmbProps.DisplayAsLookUpControl = False

            ElseIf TypeOf sender Is DateTimePicker Then
                Dim dtp As DateTimePicker = sender
                Dim dtpProps As DatepickerProperties = CreatePropsObjectWithIndicies(New DatepickerProperties, oRow, Source_AllIndicies)
                dtpProps.Enable_SQL = New SQLValue(ClassAllgemeineFunktionen.NotNullString(oRow.Item("SQL_ENABLE"), ""))
                dtpProps.Enable_SQL_OnLoad = New SQLValue(ClassAllgemeineFunktionen.NotNullString(oRow.Item("SQL_ENABLE_ON_LOAD"), ""))
                props = dtpProps

            ElseIf TypeOf sender Is DataGridView Then
                Dim grid As DataGridView = sender
                Dim gridProps As GridViewProperties = CreatePropsObjectWithIndicies(New GridViewProperties, oRow, Source_VectorIndicies)

                props = gridProps



            ElseIf TypeOf sender Is GridControl Then
                Dim oGridControl As GridControl = sender
                Dim oGridProps As GridControlProperties = CreatePropsObjectWithIndicies(New GridControlProperties, oRow, Source_VectorIndicies)
                oGridProps.AllowAddNewValues = StrToBool(oRow.Item("VKT_ADD_ITEM"))
                oGridProps.Enable_SQL = New SQLValue(ClassAllgemeineFunktionen.NotNullString(oRow.Item("SQL_ENABLE"), ""))
                oGridProps.Enable_SQL_OnLoad = New SQLValue(ClassAllgemeineFunktionen.NotNullString(oRow.Item("SQL_ENABLE_ON_LOAD"), ""))
                props = oGridProps
            ElseIf TypeOf sender Is Button Then
                Dim oButton As Button = sender
                Dim oButtonProps As ButtonProperties = CreatePropsObject(New ButtonProperties, oRow, Source_VectorIndicies)
                oButtonProps.Text = oButton.Text
                oButtonProps.SQLCommand = New SQLValue(oRow.Item("SQL_UEBERPRUEFUNG"))
                oButtonProps.Override_SQL = New SQLValue(ClassAllgemeineFunktionen.NotNullString(oRow.Item("SQL2"), ""))
                oButtonProps.Enable_SQL = New SQLValue(ClassAllgemeineFunktionen.NotNullString(oRow.Item("SQL_ENABLE"), ""))
                oButtonProps.Enable_SQL_OnLoad = New SQLValue(ClassAllgemeineFunktionen.NotNullString(oRow.Item("SQL_ENABLE_ON_LOAD"), ""))
                If Not IsDBNull(oRow.Item("IMAGE_CONTROL")) Then
                    Dim obimg() As Byte = oRow.Item("IMAGE_CONTROL")
                    Dim oBitmap As Bitmap = ByteArrayToBitmap(obimg)
                    oButtonProps.CtrlImage = New ImageValue("IMAGE")
                    oButton.Image = oBitmap
                End If

                props = oButtonProps
            Else
                MsgBox("This is not a supported control type!")
                Exit Sub
            End If

            ' Zum Schluss wird das Eigenschaften-Objekt ins PropertyGrid geladen
            'pgControls.SelectedObject = props
            pgControlsNew.SelectedObject = props
        Catch ex As Exception
            MsgBox(ex.Message, MsgBoxStyle.Critical)
        End Try

    End Sub

    Private Sub pgControlsNew_RowChanged(sender As Object, e As DevExpress.XtraVerticalGrid.Events.RowChangedEventArgs) Handles pgControlsNew.RowChanged
        If e.ChangeType <> DevExpress.XtraVerticalGrid.RowChangeTypeEnum.Value Then
            Exit Sub
        End If
        pgControls_Focused = True
        Dim prop = e.Properties.FieldName
        Dim newValue = e.Properties.Value

        Select Case prop
            Case "DisplayAsLookUpControl"
                If UpdateSingleValue("CTRL_TYPE", "LOOKUP") = True Then
                    MsgBox("Type has been changed. Controls will be reloaded!", MsgBoxStyle.Information, "")
                    LoadControls()
                End If
            Case "DisplayAsComboBox"
                If UpdateSingleValue("CTRL_TYPE", "CMB") = True Then
                    MsgBox("Type has been changed. Controls will be reloaded!", MsgBoxStyle.Information, "")
                    LoadControls()
                End If
            Case "Location"
                UpdateSingleValue("X_LOC", DirectCast(newValue, Point).X)
                UpdateSingleValue("Y_LOC", DirectCast(newValue, Point).Y)

                CurrentControl.Location = newValue

            Case "X"
                UpdateSingleValue("X_LOC", CInt(newValue))

                CurrentControl.Location = New Point(newValue, CurrentControl.Location.Y)

            Case "Y"
                UpdateSingleValue("Y_LOC", CInt(newValue))

                CurrentControl.Location = New Point(CurrentControl.Location.X, newValue)

            Case "Size"
                UpdateSingleValue("WIDTH", DirectCast(newValue, Size).Width)
                UpdateSingleValue("HEIGHT", DirectCast(newValue, Size).Height)

                CurrentControl.Size = newValue

            Case "Width"
                UpdateSingleValue("WIDTH", CInt(newValue))

                CurrentControl.Size = New Size(newValue, CurrentControl.Size.Height)

            Case "Height"
                UpdateSingleValue("HEIGHT", CInt(newValue))

                CurrentControl.Size = New Size(CurrentControl.Size.Width, newValue)

            Case "Name"
                UpdateSingleValue("NAME", newValue)

                Reload_ControlNameList()

                CurrentControl.Name = newValue

            Case "Index"
                UpdateSingleValue("INDEX_NAME", newValue)

            Case "Text"
                UpdateSingleValue("CTRL_TEXT", newValue)

                CurrentControl.Text = newValue

            Case "Required"
                UpdateSingleValue("VALIDATION", IIf(newValue = True, 1, 0))

            Case "ReadOnly"
                UpdateSingleValue("READ_ONLY", IIf(newValue = True, 1, 0))
            Case "SaveChangeOnReadOnly"
                UpdateSingleValue("SAVE_CHANGE_ON_ENABLED", IIf(newValue = True, 1, 0))
            Case "Font"
                Dim font As Font = newValue
                Dim fontSize As Integer = Math.Truncate(font.SizeInPoints)
                UpdateSingleValue("FONT_SIZE", fontSize)
                UpdateSingleValue("FONT_FAMILY", font.FontFamily.Name)
                UpdateSingleValue("FONT_STYLE", CInt(font.Style))

                CurrentControl.Font = font
            Case "TextColor"
                Dim color As Color = newValue
                UpdateSingleValue("FONT_COLOR", ColorTranslator.ToWin32(color))

                CurrentControl.ForeColor = color
            Case "SQLCommand"
                UpdateSingleValue("SQL_UEBERPRUEFUNG", newValue)
                UpdateSingleValue("CHOICE_LIST", "")

            Case "Enable_SQL"
                UpdateSingleValue("SQL_ENABLE", newValue)
                UpdateSingleValue("CHOICE_LIST", "")

            Case "Enable_SQL_OnLoad"
                UpdateSingleValue("SQL_ENABLE_ON_LOAD", newValue)
                UpdateSingleValue("CHOICE_LIST", "")

            Case "Override_SQL"
                UpdateSingleValue("SQL2", newValue)
                UpdateSingleValue("CHOICE_LIST", "")

            Case "SetControlData"
                UpdateSingleValue("SET_CONTROL_DATA", newValue)
                UpdateSingleValue("CHOICE_LIST", "")

            Case "ChoiceList"
                UpdateSingleValue("CHOICE_LIST", newValue)
                UpdateSingleValue("SQL_UEBERPRUEFUNG", "")

            Case "MultiSelect"
                UpdateSingleValue("MULTISELECT", IIf(newValue = True, 1, 0))

            Case "AllowAddNewValues"
                UpdateSingleValue("VKT_ADD_ITEM", IIf(newValue = True, 1, 0))

            Case "PreventDuplicates"
                UpdateSingleValue("VKT_PREVENT_MULTIPLE_VALUES", IIf(newValue = True, 1, 0))

            Case "DefaultValue"
                UpdateSingleValue("DEFAULT_VALUE", newValue)

            Case "Regex"
                UpdateSingleValue("REGEX_MATCH", newValue)

            Case "RegexMessage"
                UpdateSingleValue("REGEX_MESSAGE_DE", newValue)

            Case "Active"
                Dim oActive As Boolean = IIf(newValue = True, 1, 0)
                UpdateSingleValue("CONTROL_ACTIVE", oActive)

            Case "CtrlImage"
                Dim myPath As ImageValue = newValue
                UpdateImage(myPath.Value)

            Case "DisplayFormat"
                UpdateSingleValue("FORMAT_STRING", newValue)
            Case "TextAlignment"
                UpdateSingleValue("TEXT_ALIGNMENT", newValue)
                Select Case CurrentControl.GetType()
                    Case GetType(TextEdit)
                        If TypeOf CurrentControl Is DevExpress.XtraEditors.TextEdit Then
                            Dim txt = DirectCast(CurrentControl, DevExpress.XtraEditors.TextEdit)
                            Select Case newValue
                                Case "Near" : txt.Properties.Appearance.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Near
                                Case "Center" : txt.Properties.Appearance.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center
                                Case "Far" : txt.Properties.Appearance.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Far
                            End Select
                        End If
                End Select
        End Select
    End Sub

    Private Function UpdateImage(ImageLocation As String)
        Try
            Dim image As Bitmap = CType(System.Drawing.Image.FromFile(ImageLocation, True), Bitmap)
            Dim bimage() As Byte = BitmapToByteArray(image)
            'UPDATE TBPMO_FORM_CONSTRUCTOR SET MENU_IMG = @MENU_IMG, WHERE GUID = @GUID"
            Dim SQL As String = "UPDATE TBPM_PROFILE_CONTROLS SET IMAGE_CONTROL = @MENU_IMG WHERE GUID = @GUID"
            Dim conn As SqlClient.SqlConnection = New SqlClient.SqlConnection(CONNECTION_STRING_ECM)
            Dim cmd As SqlClient.SqlCommand = New SqlClient.SqlCommand(SQL, conn)

            cmd.Parameters.Add("@MENU_IMG", SqlDbType.VarBinary).Value = bimage
            cmd.Parameters.Add("@GUID", SqlDbType.Int).Value = CURRENT_CONTROL_ID

            conn.Open()
            cmd.ExecuteNonQuery()
            conn.Close()

            tslblAenderungen.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
            tslblAenderungen.Caption = "Änderungen gespeichert - " & Now

            CHANGES_FORM_DESIGN = True
            Return True

        Catch ex As Exception
            _Logger.Error(ex)
            Dim oMsg = $"UpdateImage - Error while saving Control (Id: {CURRENT_CONTROL_ID}): {vbCrLf}{ex.Message}"
            MsgBox(oMsg)
            _Logger.Info(oMsg)
            Return False
        End Try
    End Function
    Private Function UpdateSingleValue(columnName As String, value As Object)
        Dim guid As Integer = CURRENT_CONTROL_ID
        Dim escapedValue = value

        ' Strings und SQL-Commands müssen vor dem Speichern escaped und mit Anführungszeichen versehen werden
        If TypeOf value Is String Then
            escapedValue = $"'{value}'"
        ElseIf TypeOf value Is SQLValue Then
            Dim v As SQLValue = value
            escapedValue = $"'{v.Value.Replace("'", "''")}'"

            'UpdateSingleValue("CONNECTION_ID", v.ConnectionId)
        ElseIf TypeOf value Is Boolean Then
            If escapedValue = False Then
                escapedValue = 0
            Else
                escapedValue = 1
            End If
        End If

        Try
            Dim upd = $"UPDATE TBPM_PROFILE_CONTROLS SET {columnName} = {escapedValue}, CHANGED_WHO = '{USER_USERNAME}' WHERE GUID = {guid}"
            If DatabaseFallback.ExecuteNonQueryECM(upd) = True Then
                tslblAenderungen.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
                tslblAenderungen.Caption = "Änderungen gespeichert - " & Now
                If columnName.ToUpper = "CTRL_TEXT" Then
                    Dim oSQL = $"EXEC PRPM_CHANGE_CONTROL_CAPTION {guid},{escapedValue},'{USER_USERNAME}','{USER_LANGUAGE}'"
                    DatabaseFallback.ExecuteNonQueryECM(oSQL)
                End If
                CHANGES_FORM_DESIGN = True
                Return True
            Else
                LOGGER.Info($"UpdateSingleValue - Fehler beim Speichern von Control (Id: {guid}, column: {columnName}): {vbCrLf}{upd}")
            End If

            Return False

        Catch ex As Exception
            _Logger.Error(ex)
            Dim oMsg = $"UpdateSingleValue - Fehler beim Speichern von Control (Id: {guid}, column: {columnName}): {vbCrLf}{ex.Message}"
            MsgBox(oMsg)
            _Logger.Info(oMsg)
            Return False
        End Try
    End Function

    Private Sub MenuItemAddColumn_Click(sender As Object, e As EventArgs) Handles MenuItemAddColumn.Click
        Try
            Dim oGuid = ClassAllgemeineFunktionen.NewShortGuid()
            Dim oColumnName As String = "colNew" & oGuid
            Dim oColumnCaption As String = "New Column " & oGuid
            If DatabaseFallback.ExecuteNonQueryECM($"INSERT INTO TBPM_CONTROL_TABLE (CONTROL_ID, SPALTENNAME, SPALTEN_HEADER, SPALTENBREITE) VALUES({CURRENT_CONTROL_ID}, '{oColumnName}', '{oColumnCaption}', 95)") = True Then
                tslblAenderungen.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
                tslblAenderungen.Caption = "Änderungen gespeichert - " & Now

                LoadControls()
            End If
        Catch ex As Exception
            Dim oMsg = $"MenuItemAddColumn_Click - Fehler beim Hinzufügen von einer neuen Spalte: {vbCrLf}{ex.Message}"
            MsgBox(oMsg)
            _Logger.Error(ex)
        End Try
    End Sub

    Private Sub bbtnItemFinishSQL_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles bbtnItemFinishSQL.ItemClick
        Try
            CURRENT_DESIGN_TYPE = "SQL_BTNFINISH"
            Dim oSQL = $"SELECT SQL_BTN_FINISH FROM TBPM_PROFILE WHERE GUID = {ProfileId}"
            Dim oldSQL = DatabaseFallback.GetScalarValueECM(oSQL)
            Dim oForm As New frmSQLEditor(LOGCONFIG, DatabaseECM) With {
                .SQLCommand = oldSQL,
                .SQLConnection = 1,
                .PlaceholdersManualPrefix = "CTRL",
                .PlaceholdersManualTitle = "Controls",
                .PlaceholdersManual = CURRENT_CONTROL_NAME_LIST.ToDictionary(Function(name) name, Function(name) name)
            }
            If IDB_ACTIVE = False Then
                oForm.ATTRIBUTE_STORE = "WM"
                oForm.PlaceholdersWindream = MVSource_AllIndicies
            Else
                oForm.ATTRIBUTE_STORE = "IDB"
            End If

            oForm.ShowDialog()

            If oForm.DialogResult = DialogResult.OK Then
                If oldSQL <> oForm.SQLCommand Then
                    Dim oUpdate As String = $"Update TBPM_PROFILE SET CHANGED_WHO = '{USER_USERNAME}', SQL_BTN_FINISH = '{oForm.SQLCommand.Replace("'", "''")}' WHERE GUID = {CURRENT_ProfilGUID}"
                    If DatabaseFallback.ExecuteNonQueryECM(oUpdate) = True Then
                        tslblAenderungen.Caption = $"Profile SQLFinish saved - {Now.ToLongTimeString}"
                        tslblAenderungen.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
                        CHANGES_FORM_DESIGN = True
                    Else
                        tslblAenderungen.Visibility = DevExpress.XtraBars.BarItemVisibility.Never
                    End If

                End If
            End If
        Catch ex As Exception
            MsgBox("Error in Saving Profile SQLFinish: " & vbNewLine & vbNewLine & ex.Message)
            _Logger.Error(ex)
        End Try
    End Sub

    Private Sub BarButtonItem1_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarButtonItem1.ItemClick
        If CurrentControl Is Nothing = False Then
            DeleteControl(CurrentControl.Name)
            'pgControls.Enabled = False
            pgControlsNew.Enabled = False
            CurrentControl = Nothing
            RibPGCtrlheight.Enabled = False
            RibPGCtrlWidth.Enabled = False

            Reload_ControlNameList()
        End If
    End Sub

    Private Sub BarButtonItem2_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarButtonItem2.ItemClick
        LoadControls()
    End Sub

    Private Sub BarButtonItem3_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarButtonItem3.ItemClick
        If BarButtonItem3.Caption = "Designer locked" Then
            BarButtonItem3.Caption = "Designer active"
            BarButtonItem3.ItemAppearance.Normal.BackColor = Color.LightSteelBlue
            RibbonGroupControls.Enabled = True
            RibbonGroupControlFunctions.Enabled = True
            Designer_Locked = False
        Else
            BarButtonItem3.Caption = "Designer locked"
            BarButtonItem3.ItemAppearance.Normal.BackColor = Color.Red
            Designer_Locked = True

            RibbonGroupControls.Enabled = False
            RibbonGroupControlFunctions.Enabled = False

            If Me.Cursor = Cursors.Cross Then
                Mouse_IsPressed = False
                Me.Cursor = Cursors.Default
            End If
        End If
    End Sub
    Private Sub ControlBarItem_Clicked(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles bbtnitLabel.ItemClick, bbtnitLine.ItemClick, bbtnitButton.ItemClick,
        bbtnitCheckBox.ItemClick, bbtnitDatePicker.ItemClick, bbtnitLU.ItemClick, bbtnitTable.ItemClick, bbtnitTextBox.ItemClick
        If Designer_Locked Then
            Exit Sub
        End If

        Me.Cursor = Cursors.Cross
        Mouse_IsPressed = True
        CurrentControl = Nothing

        Select Case e.Item.Name
            Case "bbtnitLabel"
                NewControlSelected = ClassControlCreator.PREFIX_LABEL
            Case "bbtnitTextBox"
                NewControlSelected = ClassControlCreator.PREFIX_TEXTBOX
            Case "btncmb"
                NewControlSelected = ClassControlCreator.PREFIX_COMBOBOX
            Case "bbtnitDatePicker"
                NewControlSelected = ClassControlCreator.PREFIX_DATETIMEPICKER
            Case "btnVektor"
                NewControlSelected = ClassControlCreator.PREFIX_DATAGRIDVIEW
            Case "bbtnitTable"
                NewControlSelected = ClassControlCreator.PREFIX_TABLE
            Case "bbtnitCheckBox"
                NewControlSelected = ClassControlCreator.PREFIX_CHECKBOX
            Case "bbtnitLine"
                NewControlSelected = ClassControlCreator.PREFIX_LINE
            Case "bbtnitButton"
                NewControlSelected = ClassControlCreator.PREFIX_BUTTON
            Case "bbtnitLU"
                NewControlSelected = ClassControlCreator.PREFIX_LOOKUP
        End Select


    End Sub

    Private Sub frmFormDesigner_KeyUp(sender As Object, e As KeyEventArgs) Handles MyBase.KeyUp
        If e.KeyCode = Keys.Escape Then
            If Me.Cursor = Cursors.Cross Then
                Mouse_IsPressed = False
                Me.Cursor = Cursors.Default
            End If

        End If
    End Sub

    Private Sub pnldesigner_MouseDown(sender As Object, e As MouseEventArgs) Handles pnldesigner.MouseDown
        If Designer_Locked Then
            Exit Sub
        End If

        If Cursor = Cursors.Cross And Mouse_IsPressed = True Then
            Dim cursorPosition As Point = pnldesigner.PointToClient(Cursor.Position)
            Mouse_IsPressed = False
            Try
                Select Case NewControlSelected
                    Case ClassControlCreator.PREFIX_LABEL
                        Dim label = ControlCreator.CreateNewLabel(cursorPosition)
                        SetMovementHandlers(label)

                        Dim oInsert = $"INSERT INTO TBPM_PROFILE_CONTROLS
                        (PROFIL_ID, NAME, CTRL_TYPE, CTRL_TEXT, X_LOC, Y_LOC, ADDED_WHO, HEIGHT, WIDTH, TEXT_ALIGNMENT, DISPLAY_IN_SEPERATE_FORM)
                        VALUES ({ProfileId},'{label.Name}','LBL','{label.Text}','{label.Location.X}','{label.Location.Y}','{USER_USERNAME}',{label.Size.Height},{label.Size.Width},'{label.TextAlign}','')"
                        If DatabaseFallback.ExecuteNonQueryECM(oInsert) Then
                            'TBPM_PROFILE_CONTROLSTableAdapter.cmdInsertAnlage(ProfileId, label.Name, "LBL", label.Text, label.Location.X, label.Location.Y, USER_USERNAME, label.Size.Height, label.Size.Width, label.TextAlign, "")
                            CHANGES_FORM_DESIGN = True
                            CurrentControl = label
                            CurrentControl.Tag = New ClassControlCreator.ControlMetadata() With {
                                .Guid = GetLastID(),
                                .ReadOnly = False
                            }
                            pnldesigner.Controls.Add(label)
                        Else
                            _Logger.Info($"Error while inserting new Label Control into TBPM_PROFILE_CONTROLS: {oInsert}")
                            MsgBox("Fehler beim Erstellen des Labels. Bitte überprüfen Sie die Log-Datei für weitere Informationen.", MsgBoxStyle.Critical, "Fehler beim Erstellen des Labels")
                        End If

                    Case ClassControlCreator.PREFIX_TEXTBOX
                        Dim txt = ControlCreator.CreateNewTextBox(cursorPosition)
                        SetMovementHandlers(txt)

                        TBPM_PROFILE_CONTROLSTableAdapter.cmdInsertAnlage(ProfileId, txt.Name, "TXT", txt.Name, txt.Location.X, txt.Location.Y, USER_USERNAME, txt.Size.Height, txt.Size.Width, txt.Properties.Appearance.TextOptions.HAlignment)
                        CHANGES_FORM_DESIGN = True
                        CurrentControl = txt
                        CurrentControl.Tag = New ClassControlCreator.ControlMetadata() With {
                            .Guid = GetLastID(),
                            .ReadOnly = False
                        }

                        pnldesigner.Controls.Add(txt)

                    Case ClassControlCreator.PREFIX_COMBOBOX
                        Dim cmb = ControlCreator.CreateNewCombobox(cursorPosition)
                        SetMovementHandlers(cmb)

                        TBPM_PROFILE_CONTROLSTableAdapter.cmdInsertAnlage(ProfileId, cmb.Name, "CMB", cmb.Name, cmb.Location.X, cmb.Location.Y, USER_USERNAME, cmb.Size.Height, cmb.Size.Width, "NONE")
                        CHANGES_FORM_DESIGN = True
                        CurrentControl = cmb
                        CurrentControl.Tag = New ClassControlCreator.ControlMetadata() With {
                            .Guid = GetLastID(),
                            .ReadOnly = False
                        }

                        pnldesigner.Controls.Add(cmb)

                    Case ClassControlCreator.PREFIX_DATETIMEPICKER
                        Dim dtp = ControlCreator.CreateNewDatetimepicker(cursorPosition)
                        SetMovementHandlers(dtp)

                        TBPM_PROFILE_CONTROLSTableAdapter.cmdInsertAnlage(ProfileId, dtp.Name, "DTP", dtp.Name, dtp.Location.X, dtp.Location.Y, USER_USERNAME, dtp.Size.Height, dtp.Size.Width, "NONE")
                        CHANGES_FORM_DESIGN = True
                        CurrentControl = dtp
                        CurrentControl.Tag = New ClassControlCreator.ControlMetadata() With {
                            .Guid = GetLastID(),
                            .ReadOnly = False
                        }

                        pnldesigner.Controls.Add(dtp)

                    Case ClassControlCreator.PREFIX_CHECKBOX
                        Dim chk = ControlCreator.CreateNewCheckbox(cursorPosition)
                        SetMovementHandlers(chk)

                        TBPM_PROFILE_CONTROLSTableAdapter.cmdInsertAnlage(ProfileId, chk.Name, "CHK", chk.Text, chk.Location.X, chk.Location.Y, USER_USERNAME, chk.Size.Height, chk.Size.Width, "NONE")
                        CHANGES_FORM_DESIGN = True
                        CurrentControl = chk
                        CurrentControl.Tag = New ClassControlCreator.ControlMetadata() With {
                            .Guid = GetLastID(),
                            .ReadOnly = False
                        }

                        pnldesigner.Controls.Add(chk)

                    Case ClassControlCreator.PREFIX_LOOKUP
                        Dim lc As LookupControl3 = ControlCreator.CreateNewLookupControl(cursorPosition)

                        SetMovementHandlers(lc)

                        TBPM_PROFILE_CONTROLSTableAdapter.cmdInsertAnlage(ProfileId, lc.Name, "LOOKUP", lc.Name, lc.Location.X, lc.Location.Y, USER_USERNAME, lc.Size.Height, lc.Size.Width, lc.Properties.Appearance.TextOptions.HAlignment)
                        CHANGES_FORM_DESIGN = True
                        CurrentControl = lc
                        CurrentControl.Tag = New ClassControlCreator.ControlMetadata() With {
                            .Guid = GetLastID(),
                            .ReadOnly = False
                        }

                        pnldesigner.Controls.Add(lc)

                    Case ClassControlCreator.PREFIX_TABLE
                        Dim tb = ControlCreator.CreateNewTable(cursorPosition)

                        SetMovementHandlers(tb)
                        AddHandler tb.MouseClick, AddressOf gridControl_MouseClick

                        TBPM_PROFILE_CONTROLSTableAdapter.cmdInsertAnlage(ProfileId, tb.Name, "TABLE", tb.Name, tb.Location.X, tb.Location.Y, USER_USERNAME, tb.Size.Height, tb.Size.Width, "NONE")
                        CHANGES_FORM_DESIGN = True
                        Dim oControlId = GetLastID()

                        CurrentControl = tb
                        CurrentControl.Tag = New ClassControlCreator.ControlMetadata() With {
                            .Guid = oControlId,
                            .ReadOnly = False
                        }

                        TBPM_CONTROL_TABLETableAdapter.Insert(oControlId, "column1", "Column1", 95, USER_USERNAME, "TEXT", 0)
                        TBPM_CONTROL_TABLETableAdapter.Insert(oControlId, "column2", "Column2", 95, USER_USERNAME, "TEXT", 0)

                        pnldesigner.Controls.Add(tb)
                    Case ClassControlCreator.PREFIX_LINE
                        Dim line = ControlCreator.CreateNewLine(cursorPosition)

                        SetMovementHandlers(line)

                        TBPM_PROFILE_CONTROLSTableAdapter.cmdInsertAnlage(ProfileId, line.Name, "LINE", line.Name, line.Location.X, line.Location.Y, USER_USERNAME, line.Size.Height, line.Size.Width, "NONE")
                        CHANGES_FORM_DESIGN = True
                        CurrentControl = line
                        CurrentControl.Tag = New ClassControlCreator.ControlMetadata() With {
                            .Guid = GetLastID(),
                            .ReadOnly = False
                        }


                        pnldesigner.Controls.Add(line)
                    Case ClassControlCreator.PREFIX_BUTTON
                        Dim oButton = ControlCreator.CreateNewButton(cursorPosition)

                        SetMovementHandlers(oButton)

                        TBPM_PROFILE_CONTROLSTableAdapter.cmdInsertAnlage(ProfileId, oButton.Name, "BUTTON", oButton.Name, oButton.Location.X, oButton.Location.Y, USER_USERNAME, oButton.Size.Height, oButton.Size.Width, "NONE")
                        CHANGES_FORM_DESIGN = True
                        CurrentControl = oButton
                        CurrentControl.Tag = New ClassControlCreator.ControlMetadata() With {
                            .Guid = GetLastID(),
                            .ReadOnly = False
                        }

                        pnldesigner.Controls.Add(oButton)
                End Select

                If IsNothing(NewControlSelected) = False Then
                    Reload_ControlNameList()
                End If

                If Not IsNothing(CurrentControl) Then
                    RibPGCtrlheight.Enabled = True
                    RibPGCtrlWidth.Enabled = True
                End If
            Catch ex As Exception
                _Logger.Info($"Error while Adding new control {NewControlSelected}:")
                _Logger.Info(ex)
                MsgBox($"Error while Adding new control {NewControlSelected}: {ex.Message}" & vbCrLf & "Check the log for further info", MsgBoxStyle.Critical)
            End Try
            Me.Cursor = Cursors.Default
            NewControlSelected = ""
        End If
    End Sub

    Private Sub bbtniwidth_plus_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles bbtniwidth_plus.ItemClick
        Width_Plus()
    End Sub

    Private Sub bbtniwidth_min_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles bbtniwidth_min.ItemClick
        Width_Min()
    End Sub

    Private Sub bbtniheight_min_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles bbtniheight_min.ItemClick
        Height_minus()
    End Sub

    Private Sub bbtniheight_plus_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles bbtniheight_plus.ItemClick
        Height_plus()
    End Sub


    Private Sub frmFormDesigner_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown

        If e.Control AndAlso (e.KeyCode = e.KeyCode.Add Or e.KeyCode = e.KeyCode.Oemplus) Then
            Height_plus()

        ElseIf e.Control AndAlso (e.KeyCode = e.KeyCode.Subtract Or e.KeyCode = e.KeyCode.Oemplus) Then
            Height_minus()
        Else
            Console.WriteLine("e.keycode: " + e.KeyCode.ToString)
            If e.KeyCode = e.KeyCode.Delete And pgControls_Focused = False Then

                Control_Delete()
            ElseIf e.KeyCode = e.KeyCode.F5 Then
                LoadControls()
                tslblAenderungen.Caption = "Controls loaded - " + Now.ToString
            ElseIf e.KeyCode = Keys.Escape Then
                If Me.Cursor = Cursors.Cross Then
                    Mouse_IsPressed = False
                    Me.Cursor = Cursors.Default
                End If
            ElseIf (e.KeyCode = e.KeyCode.Add Or e.KeyCode = e.KeyCode.Oemplus) Then
                Width_Plus()
            ElseIf (e.KeyCode = e.KeyCode.Subtract Or e.KeyCode = e.KeyCode.Oemplus) Then
                Width_Min()
            End If
        End If


    End Sub
    Sub Width_Plus()
        If CurrentControl Is Nothing = False Then
            CurrentControl.Size = New Size(CurrentControl.Width + 5, CurrentControl.Height)
            DirectCast(pgControlsNew.SelectedObject, BaseProperties).Size = CurrentControl.Size
            pgControlsNew.UpdateData()

            UpdateSingleValue("WIDTH", CurrentControl.Size.Width)
        End If
    End Sub
    Sub Width_Min()
        If CurrentControl Is Nothing = False Then
            Dim newWidth = CurrentControl.Width - 5
            ' Verhindert, dass das Control unsichtbar wird
            If newWidth < 1 Then
                Exit Sub
            End If
            CurrentControl.Size = New Size(newWidth, CurrentControl.Height)
            DirectCast(pgControlsNew.SelectedObject, BaseProperties).Size = CurrentControl.Size
            pgControlsNew.UpdateData()

            UpdateSingleValue("WIDTH", CurrentControl.Size.Width)
        End If
    End Sub

    Sub Height_minus()
        If CurrentControl Is Nothing = False Then
            Dim newHeight As Integer = CurrentControl.Height - 5
            Dim oReloadNeeded As Boolean = False
            If newHeight <= 22 And TypeOf CurrentControl Is DevExpress.XtraEditors.MemoEdit Then

                oReloadNeeded = True
                '    DirectCast(CurrentControl, TextBox).Multiline = True
            ElseIf newHeight <= 20 Then
                Exit Sub
            End If
            CurrentControl.Size = New Size(CurrentControl.Width, newHeight)
            DirectCast(pgControlsNew.SelectedObject, BaseProperties).Size = CurrentControl.Size
            pgControlsNew.UpdateData()

            If UpdateSingleValue("HEIGHT", newHeight) And oReloadNeeded Then
                LoadControls()
                LoadControlProperties(CurrentControl)
            End If
        End If
    End Sub

    Sub Height_plus()
        If CurrentControl Is Nothing = False Then
            Dim newHeight As Integer = CurrentControl.Height + 5
            Dim oReloadNeeded As Boolean = False
            ' TODO: Implement Multiline Textbox
            If newHeight > 21 And TypeOf CurrentControl Is DevExpress.XtraEditors.TextEdit Then
                Console.WriteLine("Multiline directcast")
                oReloadNeeded = True
                '    DirectCast(CurrentControl, TextBox).Multiline = True
            End If

            CurrentControl.Size = New Size(CurrentControl.Width, newHeight)
            DirectCast(pgControlsNew.SelectedObject, BaseProperties).Size = CurrentControl.Size
            pgControlsNew.UpdateData()

            If UpdateSingleValue("HEIGHT", newHeight) And oReloadNeeded Then
                LoadControls()
                CurrentControl.Select()
                CurrentControl.BackColor = Color.Orange
            End If
        End If
    End Sub

    Private Sub pgControlsNew_KeyPress(sender As Object, e As KeyPressEventArgs) Handles pgControlsNew.KeyPress
        pgControls_Focused = True
    End Sub

    Private Sub pgControlsNew_Leave(sender As Object, e As EventArgs) Handles pgControlsNew.Leave
        pgControls_Focused = False
    End Sub

    Private Sub pgControlsNew_KeyUp(sender As Object, e As KeyEventArgs) Handles pgControlsNew.KeyUp
        pgControls_Focused = True
    End Sub

    Private Sub pgControlsNew_Click(sender As Object, e As EventArgs) Handles pgControlsNew.Click
        pgControls_Focused = True
    End Sub

    Private Sub pgControlsNew_GotFocus(sender As Object, e As EventArgs) Handles pgControlsNew.GotFocus
        pgControls_Focused = True
    End Sub

    Private Sub pgControlsNew_Enter(sender As Object, e As EventArgs) Handles pgControlsNew.Enter
        pgControls_Focused = True
    End Sub
End Class