#include <GuiConstants.au3>
#include <GuiListView.au3>
#include-once
OnAutoItExitRegister("__ListViewEditInput_onExit")
; #INDEX# =======================================================================================================================
; Title .........: ListViewEditInput
; AutoIt Version : 3.3.12.0
; Language ......: English
; Description ...: This UDF make it possible to edit ListviewSubitems
; Author(s) .....: Kanashius
; ===============================================================================================================================

; #VARIABLES# ===================================================================================================================
Global $__ListViewEditInput_ListViews[0][7],$__ListViewEditInput_akt=-1,$__ListViewEditInput_Editing=false,$__ListViewEditInput_LastEdited[2]
Global $__ListViewEditInput_EnterDummy,$__ListViewEditInput_ESCDummy
Global $__ListViewEditInput_EditInput
global $__ListViewEditInput_hGui,$__ListViewEditInput_hHook

; #CURRENT# =====================================================================================================================
; __ListViewEditInput_StartUp
; __ListViewEditInput_AddListview
; __ListViewEditInput_DeleteListview
; __ListViewEditInput_ChangeListview
; __ListViewEditInput_InitializeKeys
; __ListViewEditInput_RegisterFunction
; ===============================================================================================================================

; #INTERNAL_USE_ONLY# ===========================================================================================================
; __ListViewEditInput_onExit
; __ListViewEditInput__WinProc
; __ListViewEditInput_saveLVChange
; __ListViewEditInput_cancelLVChange
; __ListViewEditInput_WM_COMMAND
; __ListViewEditInput_WM_NOTIFY
; ===============================================================================================================================

; #FUNCTION#==============================================================================
; Name...........: __ListViewEditInput_StartUp
; Description ...: Saves the Changes from Input to Listview and delete the Listview
; Syntax.........: __ListViewEditInput_StartUp($hGui)
; Parameters ....: $hGui - Handle of the Gui where to create the Input and set the Message hooks
; Author ........: Kanashius
; ===============================================================================================================================
Func __ListViewEditInput_StartUp($hGui)
	$__ListViewEditInput_EditInput=GUICtrlCreateInput("",10,10,10,10)
	GUICtrlSetState($__ListViewEditInput_EditInput,$GUI_HIDE)
	$__ListViewEditInput_hGui=$hGui
	$hProc = DllCallbackRegister('__ListViewEditInput__WinProc', 'ptr', 'hwnd;uint;wparam;lparam')
	$__ListViewEditInput_hHook = _WinAPI_SetWindowLong($hGui, -4, DllCallbackGetPtr($hProc))
EndFunc

; #FUNCTION#==============================================================================
; Name...........: __ListViewEditInput_AddListview
; Description ...: Adds a Listview to make it Editable
; Syntax.........: __ListViewEditInput_AddListview($hGui,$hListView,$arColumn="All",$arRow="All",$click="D")
; Parameters ....: $hGui		    - Handle of the Gui, where the Listview is placed
; ...............: $hListView		- CtrlID of the Listview
; ...............: $arColumn="All"	- "All" to Edit all Columns
; ...............:					  Numbers delimated by a "," starting with 0 e.g.: 1,2,5
; ...............: $arRow="All"		- "All" to Edit all Rows
; ...............:					  Numbers delimated by a "," starting with 0 e.g.: 1,2,5
; ...............: $click="D"		- D needs a doubleClick
; ...............:					  E needs a singleClick
; Author ........: Kanashius
; ===============================================================================================================================
Func __ListViewEditInput_AddListview($hGui,$hListView,$arColumn="All",$arRow="All",$click="D")
	ReDim $__ListViewEditInput_ListViews[UBound($__ListViewEditInput_ListViews)+1][7]
	local $__ListViewEditInput_akt=UBound($__ListViewEditInput_ListViews)-1
	$__ListViewEditInput_ListViews[$__ListViewEditInput_akt][0]=$hListView
	$__ListViewEditInput_ListViews[$__ListViewEditInput_akt][1]=$arColumn
	$__ListViewEditInput_ListViews[$__ListViewEditInput_akt][2]=$hGui
	$__ListViewEditInput_ListViews[$__ListViewEditInput_akt][3]=$arRow
	if $click="D" then
		$__ListViewEditInput_ListViews[$__ListViewEditInput_akt][6]=$NM_DBLCLK
	else
		$__ListViewEditInput_ListViews[$__ListViewEditInput_akt][6]=$NM_CLICK
	endif
EndFunc

; #FUNCTION#==============================================================================
; Name...........: __ListViewEditInput_DeleteListview
; Description ...: Deletes a Listview form the List of Editable Listviews
; Syntax.........: __ListViewEditInput_DeleteListview($hListView)
; Parameters ....: $hListView	- Listview CtrlID
; Author ........: Kanashius
; ===============================================================================================================================
Func __ListViewEditInput_DeleteListview($hListView)
	local $index=_ArraySearch($__ListViewEditInput_ListViews,$hListView)
	if $index<>-1 then
		_ArrayDelete($__ListViewEditInput_ListViews,$index)
	endif
EndFunc

; #FUNCTION#==============================================================================
; Name...........: __ListViewEditInput_ChangeListview
; Description ...: Changes the Colums and/or Rows of the given Listview
; Syntax.........: __ListViewEditInput_ChangeListview($hListView,$arColumn="All",$arRow="All")
; Parameters ....: $hListView
; ...............: $arColumn="All" - "All" to Edit all Columns
; ...............:					  Numbers delimated by a "," starting with 0 e.g.: 1,2,5
; ...............: $arRow="All"    - "All" to Edit all Rows
; ...............:					  Numbers delimated by a "," starting with 0 e.g.: 1,2,5
; Author ........: Kanashius
; ===============================================================================================================================
Func __ListViewEditInput_ChangeListview($hListView,$arColumn="All",$arRow="All")
	local $index=_ArraySearch($__ListViewEditInput_ListViews,$hListView)
	if $index<>-1 then
		$__ListViewEditInput_ListViews[$index][1]=$arColumn
		$__ListViewEditInput_ListViews[$index][3]=$arRow
	endif
EndFunc

; #FUNCTION#==============================================================================
; Name...........: __ListViewEditInput_GetEditedCell
; Description ...: Returns the index and Subindes of the last edited cell, or the actual editing cell
; Syntax.........: __ListViewEditInput_GetEditedCell()
; Return values .: Array: [0]=Listview Control
;                         [1]=Listview Index
;                         [2]=Listview SubItemIndex
; Author ........: Kanashius
; ===============================================================================================================================
Func __ListViewEditInput_GetEditedCell()
	local $__ListViewEditInput_Edited[3]
	$__ListViewEditInput_Edited[0]=$__ListViewEditInput_ListViews[$__ListViewEditInput_akt][0]
	$__ListViewEditInput_Edited[1]=$__ListViewEditInput_LastEdited[0]
	$__ListViewEditInput_Edited[2]=$__ListViewEditInput_LastEdited[1]
	return $__ListViewEditInput_Edited
EndFunc

; #FUNCTION#==============================================================================
; Name...........: __ListViewEditInput_InitializeKeys
; Description ...: Saves the Changes from Input to Listview and delete the Listview
; Syntax.........: __ListViewEditInput_InitializeKeys($hGui)
; Parameters ....: $hGui	- Guihandle, where the Accellerators should be used
; Error .........: Array has wrong Dimension (View GuiSetAccelerators in manual)
; Author ........: Kanashius
; ===============================================================================================================================
Func __ListViewEditInput_InitializeKeys($hGui,$arAccelerators=-1)
	if UBound($arAccelerators,2)<2 then
		SetError(1)
	endif
	$__ListViewEditInput_EnterDummy=GUICtrlCreateDummy()
	$__ListViewEditInput_ESCDummy=GUICtrlCreateDummy()
	Global $__ListViewEditInput_AccelKeys[2][2]=[["{ENTER}", $__ListViewEditInput_EnterDummy],["{ESC}", $__ListViewEditInput_ESCDummy]]
	if $arAccelerators<>-1 then
		$oldSize=UBound($__ListViewEditInput_AccelKeys)
		ReDim $__ListViewEditInput_AccelKeys[UBound($__ListViewEditInput_AccelKeys)+UBound($arAccelerators)][2]
		for $i=0 to UBound($arAccelerators)-1 step 1
			$__ListViewEditInput_AccelKeys[$i+$oldSize][0]=$arAccelerators[$i][0]
			$__ListViewEditInput_AccelKeys[$i+$oldSize][1]=$arAccelerators[$i][1]
		next
	endif
	GUISetAccelerators($__ListViewEditInput_AccelKeys,$hGui)
EndFunc

; #FUNCTION#==============================================================================
; Name...........: __ListViewEditInput_RegisterFunction
; Description ...: Saves the Changes from Input to Listview and delete the Listview
; Syntax.........: __ListViewEditInput_RegisterFunction($hListView,$sFunction,$sWhen="Changed")
; Parameters ....: $hListView		- ListView CtrlID
;				   $sFunction		- Name of the User Function
;				   $sWhen="Changed"	- When the Function should be called "Changed"->When the ListView was changed
;									   									 "Canceled"-> When the Change was canceled (ESC)
; Author ........: Kanashius
; ===============================================================================================================================
Func __ListViewEditInput_RegisterFunction($hListView,$sFunction,$sWhen="Changed")
	local $index=_ArraySearch($__ListViewEditInput_ListViews,$hListView)
	if $index<>-1 then
		if $sWhen="Changed" then
			$__ListViewEditInput_ListViews[$index][4]=$sFunction
		endif
		if $sWhen="Canceled" then
			$__ListViewEditInput_ListViews[$index][5]=$sFunction
		endif
	endif
EndFunc

; #INTERNAL_USE_ONLY#===========================================================================================================

; #INTERNAL_USE_ONLY#==============================================================================
; Name...........: __ListViewEditInput_onExit
; Description ...: Deletes the Hook at the Programm exit
; Syntax.........: __ListViewEditInput_onExit()
; Author ........: Kanashius
; Remarks .......: For Internal Use Only
; ===============================================================================================================================
Func __ListViewEditInput_onExit()
	_WinAPI_SetWindowLong($__ListViewEditInput_hGui, -4, $__ListViewEditInput_hHook) ; original WinProc wiederherstellen
EndFunc


; #INTERNAL_USE_ONLY#==============================================================================
; Name...........: __ListViewEditInput__WinProc
; Description ...: Takes the Messages and give them to the WM_COMMAND and WM_NOTIFY function
; Syntax.........: __ListViewEditInput__WinProc($hWnd, $iMsg, $iwParam, $ilParam)
; Parameters ....: $hWnd        - GuiHandle
;                  $iMsg        - MessageCode
;                  $iwParam     - wParam
;                  $ilParam     - lParam
; Return values .: WindowProc
; Author ........: Kanashius
; Remarks .......: For Internal Use Only
; ===============================================================================================================================
Func __ListViewEditInput__WinProc($hWnd, $iMsg, $iwParam, $ilParam)
    If $iMsg=$WM_NOTIFY Then
		__ListViewEditInput_WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
	ElseIf $iMsg=$WM_COMMAND Then
		__ListViewEditInput_WM_COMMAND($hWnd, $iMsg, $iwParam, $ilParam)
	endif
	Return _WinAPI_CallWindowProc($__ListViewEditInput_hHook, $hWnd, $iMsg, $iwParam, $ilParam)
EndFunc

; #INTERNAL_USE_ONLY#==============================================================================
; Name...........: __ListViewEditInput_saveLVChange
; Description ...: Saves the Changes from Input to Listview and hide the Input
; Syntax.........: __ListViewEditInput_saveLVChange()
; Author ........: Kanashius
; Remarks .......: For Internal Use Only
; ===============================================================================================================================
Func __ListViewEditInput_saveLVChange()
	if $__ListViewEditInput_Editing then
		$__ListViewEditInput_Editing=false
		$data=GUICtrlRead($__ListViewEditInput_EditInput)
		_GUICtrlListView_SetItemText($__ListViewEditInput_ListViews[$__ListViewEditInput_akt][0],$__ListViewEditInput_LastEdited[0],StringReplace($data,",","."),$__ListViewEditInput_LastEdited[1])
		GUICtrlSetState($__ListViewEditInput_EditInput,$GUI_HIDE)
		GUICtrlSetData($__ListViewEditInput_EditInput,"")
		if $__ListViewEditInput_ListViews[$__ListViewEditInput_akt][4]<>"" then
			Call($__ListViewEditInput_ListViews[$__ListViewEditInput_akt][4],$__ListViewEditInput_ListViews[$__ListViewEditInput_akt][0],$__ListViewEditInput_LastEdited[0],$__ListViewEditInput_LastEdited[1])
		endif
	endif
EndFunc

; #INTERNAL_USE_ONLY#==============================================================================
; Name...........: __ListViewEditInput_cancelLVChange
; Description ...: Hides the Input
; Syntax.........: __ListViewEditInput_cancelLVChange()
; Author ........: Kanashius
; Remarks .......: For Internal Use Only
; ===============================================================================================================================
Func __ListViewEditInput_cancelLVChange()
	if $__ListViewEditInput_Editing then
		$__ListViewEditInput_Editing=false
		GUICtrlSetState($__ListViewEditInput_EditInput,$GUI_HIDE)
		GUICtrlSetData($__ListViewEditInput_EditInput,"")
		if $__ListViewEditInput_ListViews[$__ListViewEditInput_akt][5]<>"" then
			Call($__ListViewEditInput_ListViews[$__ListViewEditInput_akt][5],$__ListViewEditInput_ListViews[$__ListViewEditInput_akt][0],$__ListViewEditInput_LastEdited[0],$__ListViewEditInput_LastEdited[1])
		endif
	endif
EndFunc

; #INTERNAL_USE_ONLY#==============================================================================
; Name...........: __ListViewEditInput_WM_COMMAND
; Description ...: Find out when the Input should be hidden (with or without saves)
; Syntax.........: __ListViewEditInput_WM_COMMAND($hWnd, $iMsg, $iwParam, $ilParam)
; Parameters ....: $hWnd        - GuiHandle
;                  $iMsg        - MessageCode
;                  $iwParam     - wParam
;                  $ilParam     - lParam
; Return values .: $GUI_RUNDEFMSG
; Author ........: Kanashius
; Remarks .......: For Internal Use Only
; ===============================================================================================================================
Func __ListViewEditInput_WM_COMMAND($hWnd, $iMsg, $iwParam, $ilParam)
	Local $hWndFrom, $iIDFrom, $iCode
	$hWndFrom = $ilParam
	$iIDFrom = BitAND($iwParam, 0xFFFF) ; Low Word
	$iCode = BitShift($iwParam, 16) ; Hi Word
	if $iIDFrom=$__ListViewEditInput_EnterDummy then
		__ListViewEditInput_saveLVChange()
	elseif $iIDFrom=$__ListViewEditInput_ESCDummy then
		__ListViewEditInput_cancelLVChange()
	endif
	Switch $hWndFrom
		Case GUICtrlGetHandle($__ListViewEditInput_EditInput)
			Switch $iCode
				Case 512
					__ListViewEditInput_saveLVChange()
			EndSwitch
	EndSwitch
	Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_COMMAND

; #INTERNAL_USE_ONLY#==============================================================================
; Name...........: __ListViewEditInput_WM_NOTIFY
; Description ...: Detect the click at a subitem to show the edit
; Syntax.........: __ListViewEditInput_WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
; Parameters ....: $hWnd        - GuiHandle
;                  $iMsg        - MessageCode
;                  $iwParam     - wParam
;                  $ilParam     - lParam
; Return values .: $GUI_RUNDEFMSG
; Author ........: Kanashius
; Remarks .......: For Internal Use Only
; ===============================================================================================================================
Func __ListViewEditInput_WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
	Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $tInfo
	$tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
	$hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
	$iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
	$iCode = DllStructGetData($tNMHDR, "Code")
	for $i=0 to UBound($__ListViewEditInput_ListViews)-1 step 1
		if $hWndFrom=GUICtrlGetHandle($__ListViewEditInput_ListViews[$i][0]) then
			if $iCode=$__ListViewEditInput_ListViews[$i][6] then
				local $tmp=AutoItSetOption("MouseCoordMode",2)
				local $pos=MouseGetPos()
				local $cPos=ControlGetPos($__ListViewEditInput_ListViews[$i][2],"",$__ListViewEditInput_ListViews[$i][0])
				$ar=_GUICtrlListView_SubItemHitTest($__ListViewEditInput_ListViews[$i][0],$pos[0]-$cPos[0],$pos[1]-$cPos[1])
				__ListViewEditInput__EditItem($i,$ar[0],$ar[1],true)
				AutoItSetOption("MouseCoordMode",$tmp)
			endif
		endif
	next
	Return $GUI_RUNDEFMSG
EndFunc

; #INTERNAL_USE_ONLY#==============================================================================
; Name...........: __ListViewEditInput__EditItem
; Description ...: Detect the click at a subitem to show the edit
; Syntax.........: __ListViewEditInput__EditItem($listview,$index,$subindex,$isIndex)
; Parameters ....: $listview        - Listview Ctrl or Index of Control
;                  $index           - Index to edit
;                  $subindex        - Subindex to edit
;                  $isIndex         - Set true if $listview is an index
; Error .........: 1=Listview not found in Editable Listview list
; Author ........: Kanashius
; ===============================================================================================================================
Func __ListViewEditInput__EditItem($listview,$index,$subindex,$isIndex=false)
	if NOT $isIndex then
		for $i=0 to UBound($__ListViewEditInput_ListViews)-1 step 1
			if $listview=$__ListViewEditInput_ListViews[$i][0] then
				$listview=$i
				ExitLoop
			endif
			if $i=UBound($__ListViewEditInput_ListViews)-1 then
				SetError(1)
			endif
		next
	endif
	local $subItem=false
	if $__ListViewEditInput_ListViews[$listview][1]="All" then
		$subItem=true
	else
		local $arTmp=StringSplit($__ListViewEditInput_ListViews[$listview][1],",",2)
		for $l=0 to UBound($arTmp)-1 step 1
			if $arTmp[$l]=$subindex then
				$subItem=true
				ExitLoop
			endif
		next
	endif
	local $Item=false
	if $__ListViewEditInput_ListViews[$listview][3]="All" then
		$Item=true
	else
		local $arTmp=StringSplit($__ListViewEditInput_ListViews[$listview][3],",",2)
		for $l=0 to UBound($arTmp)-1 step 1
			if $arTmp[$l]=$index then
				$Item=true
				ExitLoop
			endif
		next
	endif
	if $Item and $subItem and $index<>-1 and $subindex<>-1 then
		$__ListViewEditInput_akt=$listview
		$__ListViewEditInput_LastEdited[0]=$index
		$__ListViewEditInput_LastEdited[1]=$subindex
		$ar2=_GUICtrlListView_GetSubItemRect($__ListViewEditInput_ListViews[$__ListViewEditInput_akt][0],$index,$subindex)
		if $subindex=0 then
			local $ar3=_GUICtrlListView_GetSubItemRect($__ListViewEditInput_ListViews[$__ListViewEditInput_akt][0],$index,$subindex+1)
			$ar2[2]=$ar3[0]-$ar2[0]
		endif
		$pos=ControlGetPos($__ListViewEditInput_ListViews[$__ListViewEditInput_akt][2],"",$__ListViewEditInput_ListViews[$__ListViewEditInput_akt][0])
		GUICtrlSetPos($__ListViewEditInput_EditInput,$pos[0]+$ar2[0]+2,$pos[1]+$ar2[1]+2,$ar2[2]-$ar2[0],$ar2[3]-$ar2[1])
		GUICtrlSetData($__ListViewEditInput_EditInput,_GUICtrlListView_GetItemText($__ListViewEditInput_ListViews[$__ListViewEditInput_akt][0],$index,$subindex))
		GUICtrlSetState($__ListViewEditInput_EditInput,$GUI_SHOW)
		GUICtrlSetState($__ListViewEditInput_EditInput,$GUI_ONTOP)
		GUICtrlSetState($__ListViewEditInput_EditInput,$GUI_FOCUS)
		$__ListViewEditInput_Editing=true
	endif
EndFunc