TreeView Class [1.1]
Posted: 25 Mar 2019, 09:36
I really like using XML to create and manipulate the data within a TreeView but I know that XML isn't everyone's favorite so I decided to write this Class.
Basic Use:
1. Create Instance
2. Create An Item
3. Create A Sub-Item
4. Delete Either Checked Or Selected Item(s)
5. Move Items Below
6. Move Items After
7. Flatten Items After
Class With Example:
Hope someone finds this useful
Basic Use:
1. Create Instance
Code: Select all
TV:=New TreeViewClass(1,"w400 h400")
;First parameter is the name of your window, Second parameter is the position data
;TV.HWND will be the HWND of the created TreeView in case you need it later
;TV.Default() selects the TreeView and any TV_* will effect that TreeView
Code: Select all
ID:=TV.AddItem({Name:"Your Items Name"})
;You can add whatever you like to this object but Select, Expand, Under, ID and Parent will be over-written
;ID will be the ID of the created TreeView Item
Code: Select all
TV.AddSub({Name:"Your Sub-Item Name,Under:TV.Get().ID})
;Same as above just puts it below the Under value
;ID will be the ID of the created TreeView Item
Code: Select all
TV.Delete([<ID>,<ID>,...])
;Nothing is required to Delete all Checked OR Selected Items
;Pass an Array of IDs to Delete them
Code: Select all
TV.Move(0)
;This will move all Checked Items below the currently Selected item
TV.Move(0,<Target ID>)
;This will move all Checked Items below the Target ID
TV.Move(0,<Target ID>,[<Source ID>,<Source ID>,...],1)
;This will move all Source ID Items Below The Target ID and display any Errors
Code: Select all
TV.Move(1)
;Same structure as above just changing the first parameter to a 1
Code: Select all
TV.Move(2)
;Same structure as above just changing the first parameter to a 2
Code: Select all
#SingleInstance,Force
global TVIndex:=0
Gui,+HWNDMain
ID:="ahk_id" Main
Gui,Color,0,0
Gui,Font,s10 c0xAAAAAA
TV:=New TVClass(1)
Hotkey,IfWinActive,%ID%
for a,b in {Enter:"AddItem","^Enter":"AddSub","!u":"Under","!a":"After","!f":"Flatten","!Up":"MV","!Down":"MV","!Left":"MV","!Right":"MV",Delete:"Delete"}
Hotkey,%a%,%b%,On
Instructions=
(
Enter To Add An Item
Ctrl+Enter To Add A Sub-Item
Alt+U To Put Checked Items Under The Selected Item
Alt+A To Put Checked Items After The Selected Item
Alt+F To Flatten Checked Items After The Selected Item
Alt+Up/Down To Move The Selected Item Up Or Down
Alt+Left To Move The Selected Item Into The Parent Level
Alt+Right To Move The Selected Item Under Its Next Sibling
F1 To Insert An Item With A Saved Object
Delete To Delete Either Checked Or Selected Item(s)
Escape To Exit
)
Gui,Add,Text,,%Instructions%
Gui,Show
return
AddItem:
TV.AddItem({Name:++TVIndex,Select:1})
return
AddSub:
TV.AddItem({Name:++TVIndex,Select:1,Under:TV.Get().ID})
return
Delete::
if(!TV.Get().Name)
return
if(m("Can NOT Be Undone, Continue","btn:yn","def:2","ico:!")!="YES")
return
TV.Delete()
return
F1::
TV.AddItem({Name:"Special Press F2 With This Selected: " ++TVIndex,Woah:{Nice:{Things:1}}})
return
F2::
m(TV.Get())
return
Under:
TV.Move(0,,,1)
return
After:
TV.Move(1,,,1)
return
Flatten:
TV.Move(2,,,1)
return
MoveItem:
return
GuiClose:
Escape::
ExitApp
return
Class TVClass{
__New(Win:=1,Pos:="w400 h400"){
Gui,%Win%:Add,TreeView,%Pos% Checked HWNDHWND
this.Win:=Win,this.HWND:=HWND,this.Keep:=[]
}AddItem(Info){
this.Default(),Parent:=TV_GetParent(Sel:=Info.TV?Info.TV:TV_GetSelection()),Info.ID:=TV:=TV_Add(Info.Name,(Info.Under?Info.Under:Parent),Sel),this.Keep["|" TV]:=Info,Info.Select?TV_Modify(TV,"Select Vis Focus"):""
return TV
}AddSub(Info){
this.Default()
PID:=TV_GetParent(Sel:=Info.TV?Info.TV:TV_GetSelection())
TV:=TV_Add(Info.Name,Sel,"Select Vis Focus " Sel)
this.Keep["|" TV]:=Info
}After(TV,Tree:=""){
if(!TV)
return
this.Redraw(TV,this.Items(Tree),1)
}Clean(After:=0){
this.Default(),TV:=TV_GetSelection(),Checked:=[]
if(TV_Get((Parent:=TV),"Check"))
Error:="`nCan Not Move An Item Under Itself`n",TV_Modify(TV,"-Check")
while(Parent:=TV_GetParent(Parent))
if(TV_Get(Parent,"Check"))
POD:="`t" this.Keep["|" Parent].Name " Above " this.Keep["|" TV].Name "`n" POD,TV_Modify(Parent,"-Check")
Error.=POD?"Parent Of Destination:`n" POD:""
if(!After){
Next:=TV
while(Next:=TV_GetChild(Next))
TV_Modify(Next,"-Check")
}while(Check:=TV_GetNext(Check,"Checked Full")){
Next:=Check
while(Next:=TV_GetChild(Next)){
TV_Modify(Next,"-Check")
}}Next:=0
while(Next:=TV_GetNext(Next,"Checked Full")){
Look:=Next
while(Look:=TV_GetParent(Look)){
if(TV_Get(Look,"Check")){
TV_Modify(Next,"-Check")
Break
}}}return Error
}Default(){
Gui,% this.Win ":Default"
Gui,% this.Win ":TreeView",% this.HWND
}Delete(TV:=""){
this.Default(),Delete:=IsObject(TV)?TV:[]
while(Next:=TV_GetNext(Next,"Checked Full"))
for a,b in this.Items(Next)
Delete.Push(b)
if(!Delete.1)
for a,b in this.Items(TV_GetSelection())
Delete.Push(b)
while(Obj:=Delete.Pop())
for a,b in Obj
this.Keep.Delete("|" b.ID),TV_Delete(b.ID)
}Get(){
this.Default()
return this.Keep["|" TV_GetSelection()]
}GetItems(){
this.Default()
return this.Items(TV_GetSelection())
}Items(TV:=0){
this.Default(),TV:=TV?TV:TV_GetSelection(),Node:=this.Keep[TV],Items:=[],Find:=TV,Start:=TV
while(!TV_GetNext(Find)){
if(!Find:=TV_GetParent(Find))
Break
}Stop:=TV_GetNext(Find)
while(Start!=Stop&&Start)
Items.Push(Start),Start:=TV_GetNext(Start,"Full")
Tree:=[],Added:=[]
for a,b in Again:=Items{
Parent:=TV_GetParent(b)
if(!Obj:=Added[Parent])
Tree.Push(Obj:=Added[Parent]:=[])
}for a,b in Again{
Parent:=TV_GetParent(b)
if(Obj:=Added[Parent]){
Obj.Push({Parent:Parent,ID:b,Obj:this.Keep["|" b],Expand:TV_Get(b,"Expand")})
}}return Tree
}Move(UAF:=0,Target:="",Items:="",ShowError:=0){ ;UAF:="Under = 0 After = 1 Flatten = 2"
Error:=this.Clean(UAF),TV:=Target?Target:TV_GetSelection()
GuiControl,% this.Win ":-Redraw",% this.HWND
if(Items.1){
for a,b in Items
this.Redraw(TV,this.Items(b),UAF)
}else{
while(Next:=TV_GetNext(0,"Checked Full"))
this.Redraw(TV,this.Items(Next),UAF)
}
GuiControl,% this.Win ":+Redraw",% this.HWND
if(Error&&ShowError)
m("Can Not Move Item(s):",Error)
return
}Redraw(TV,Tree,UAF){
GuiControl,% this.Win ":-Redraw",% this.HWND
Under:=[]
for a,b in Tree{
for c,d in b{
Under[d.ID]:=TV_Add(d.Obj.Name,(UAF="First"?TV:UAF=2?TV_GetParent(TV):Under[d.Parent]?Under[d.Parent]:(UAF?TV_GetParent(TV):TV)),(UAF="First"?"First":UAF=2?TV:Under[d.Parent]?"":(UAF?TV:""))),TV:=UAF?Under[d.ID]:TV,this.Keep["|" Under[d.ID]]:=this.Keep["|" d.ID],this.Keep.Delete("|" d.ID)
if(a=1&&c=1)
OTV:=Under[d.ID]
}}for a,b in Tree
for c,d in b
TV_Delete(d.ID),(d.Expand?TV_Modify(Under[d.ID],"Expand"))
TV_Modify(OTV,"Select Vis Focus")
GuiControl,% this.Win ":+Redraw",% this.HWND
}
}
m(x*){
static List:={BTN:{OC:1,ARI:2,YNC:3,YN:4,RC:5,CTC:6},ico:{X:16,"?":32,"!":48,I:64}},Msg:=[],xx,y,w,h,XPos:=Round(A_ScreenWidth*.7825),Center:=0,TT
static Title
List.Title:="TreeView Class Example",List.Def:=0,List.Time:=0,Value:=0,TXT:="",Bottom:=0
WinGetTitle,Title,A
for a,b in x
Obj:=StrSplit(b,":"),(Obj.1="Bottom"?(Bottom:=1):""),(VV:=List[Obj.1,Obj.2])?(Value+=VV):(List[Obj.1]!="")?(List[Obj.1]:=Obj.2):TXT.=(IsObject(b)?Obj2String(b,,Bottom):b) "`n"
Msg:={option:Value+262144+(List.Def?(List.Def-1)*256:0),Title:List.Title,Time:List.Time,TXT:TXT}
Sleep,120
MsgBox,% Msg.option,% Msg.Title,% Msg.TXT,% Msg.Time
for a,b in {OK:Value?"OK":"",Yes:"YES",No:"NO",Cancel:"CANCEL",Retry:"RETRY"}
IfMsgBox,%a%
return b
return
}
MV(){
global TV
Direction:=SubStr(A_ThisHotkey,2)
TV.Default(),II:=TV_GetSelection()
if(Direction="Up"){
TV.After((Prev:=TV_GetPrev(TV_GetPrev(II)))?Prev:TV_GetPrev(II)?"First":"",II)
}else if(Direction="Down"){
TV.After((TV_GetNext(II)?TV_GetNext(II):""),II)
}else if(Direction="Left"){
if(!Before:=TV_GetParent(II))
return
After:=TV_GetPrev(Before),TV.Redraw((After?After:TV_GetParent(Before)),TV.GetItems(),(After?1:"First"))
}else if(Direction="Right"){
}
}
Obj2String(Obj,FullPath:=1,BottomBlank:=0){
static String,Blank
if(FullPath=1)
String:=FullPath:=Blank:=""
if(IsObject(Obj)){
for a,b in Obj{
if(IsObject(b))
Obj2String(b,FullPath "." a,BottomBlank)
else{
if(BottomBlank=0)
String.=FullPath "." a " = " b "`n"
else if(b!="")
String.=FullPath "." a " = " b "`n"
else
Blank.=FullPath "." a " =`n"
}
}}
return String Blank
}