AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

TreeView: Drag and Drop items

 
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
freakkk as guest
Guest





PostPosted: Sat Jul 15, 2006 3:29 am    Post subject: TreeView: Drag and Drop items Reply with quote

Quote:
The user has attempted to start dragging an item (there is currently no built-in support for this).
Using v1.0.44 there isn't currently any built in support for this-- so here is an attempt I made. As it currently stands- it only keeps 1 level deep worth of child items.. and since it uses a timer to detect how far your dragging the item-- it seems to act a little buggy at times. I would love to see feedback on improving (I'm sure theres probably a much better more efficeint way of doing this!!)
Anyways- here it is:

--Corey

Code:
#singleinstance force

SetTimer, TREEVIEWdragTIMER, 10
SetTimer, TREEVIEWdragTIMER, Off

Gui, Add, TreeView, gMySubroutine h195 0x200 AltSubmit 0x400
Gui, Add, Button, gMOVEdown, MOVEdown
Gui, Add, Button, gMOVEup, MOVEup

P1 := TV_Add("First parent")
P1C1 := TV_Add("Parent 1's first child", P1)  ; Specify P1 to be this item's parent.
P2 := TV_Add("Second parent")
P2C1 := TV_Add("Parent 2's first child", P2)
P2C2 := TV_Add("Parent 2's second child", P2)
P2C2C1 := TV_Add("Child 2's first child", P2C2)
P3 := TV_Add("3rd parent")
P4 := TV_Add("4th parent")
Gui, Show, ,Drag and drop experiment..  ; Show the window and its TreeView.
return

GuiEscape:
GuiClose:  ; Exit the script when the user closes the TreeView's GUI window.
ExitApp
;------------------------------------------------------------------------------
MOVEup:
TREEVIEWmoveup()
return
;------------------------------------------------------------------------------
MOVEdown:
TREEVIEWmovedown()
return
;------------------------------------------------------------------------------
MySubroutine:
If A_GuiEvent=D
{
   MouseGetPos, , OutputVarY
   SetTimer, TREEVIEWdragTIMER, On
}
return
;------------------------------------------------------------------------------
TREEVIEWdragTIMER:
OLDvalue=
;TV_Modify(A_EventInfo , "Select")
GetKeyState, state, LButton, P
If state=U
{
   ;TV_Modify(A_EventInfo , "Select")
   SetTimer, TREEVIEWdragTIMER, Off
   OutputVarY=
   OLDvalue=
   NEWOutputVarY=
   return
}
MouseGetPos, , NEWOutputVarY
If NEWOutputVarY=%OutputVarY%
   return

OLDvalue:=Sub(OutputVarY, 11)
If NEWOutputVarY<%OLDvalue%
{
   MouseGetPos, , OutputVarY
   TREEVIEWmoveup()
   return
}

OLDvalue:=Add(OutputVarY, 11)
If NEWOutputVarY>%OLDvalue%
{
   MouseGetPos, , OutputVarY
   TREEVIEWmovedown()
   return
}
return

;////////////////////////// FUNCTIONS //////////////////////////
TREEVIEWmoveup()
{
TV_GetText(PREVitem, TV_GetPrev(TV_GetSelection()))
TV_GetText(THISitem, TV_GetSelection())
If PREVitem=
   return

; LOOPS THROUGH ITEM.. STORING THE TEXT OF CHILD ITEMS IN A STRING.. (there's gotta be a better way!!)

Loop
{
   If TV_GetChild(TV_GetSelection())=0   ; CURRENT ITEM HAS CHILD ITEMS..
      break
   TV_GetText(CHILDitem, TV_GetChild(TV_GetSelection()))
   TV_Delete(TV_GetChild(TV_GetSelection()))
   If THISitemARRAY=
      THISitemARRAY=%CHILDitem%
   Else
      THISitemARRAY=%THISitemARRAY%|%CHILDitem%
}
Loop
{
   If TV_GetChild(TV_GetPrev(TV_GetSelection()))=0 ; CURRENT ITEM HAS CHILD ITEMS..
      break
   TV_GetText(CHILDitem, TV_GetChild(TV_GetPrev(TV_GetSelection())))
   TV_Delete(TV_GetChild(TV_GetPrev(TV_GetSelection())))
   If PREVitemARRAY=
      PREVitemARRAY=%CHILDitem%
   Else
      PREVitemARRAY=%PREVitemARRAY%|%CHILDitem%
}
If THISitemARRAY<>
{
   Loop, Parse, THISitemARRAY, |
      TV_Add(A_LoopField, TV_GetPrev(TV_GetSelection()))

}
If PREVitemARRAY<>
{
   Loop, Parse, PREVitemARRAY, |
      TV_Add(A_LoopField, TV_GetSelection())
}
TV_Modify(TV_GetSelection() , "", PREVitem)
TV_Modify(TV_GetPrev(TV_GetSelection()) , "Select", THISitem)
PREVitemARRAY=
THISitemARRAY=
return
}
;------------------------------------------------------------------------------
TREEVIEWmovedown()
{
TV_GetText(NEXTitem, TV_GetNext(TV_GetSelection()))
TV_GetText(THISitem, TV_GetSelection())
If NEXTitem=
   return

Loop
{
   If TV_GetChild(TV_GetSelection())=0
      break
   TV_GetText(CHILDitem, TV_GetChild(TV_GetSelection()))
   TV_Delete(TV_GetChild(TV_GetSelection()))
   If THISitemARRAY=
      THISitemARRAY=%CHILDitem%
   Else
      THISitemARRAY=%THISitemARRAY%|%CHILDitem%
}
Loop
{
   If TV_GetChild(TV_GetNext(TV_GetSelection()))=0
      break
   TV_GetText(CHILDitem, TV_GetChild(TV_GetNext(TV_GetSelection())))
   TV_Delete(TV_GetChild(TV_GetNext(TV_GetSelection())))
   If NEXTitemARRAY=
      NEXTitemARRAY=%CHILDitem%
   Else
      NEXTitemARRAY=%NEXTitemARRAY%|%CHILDitem%
}
If THISitemARRAY<>
{
   Loop, Parse, THISitemARRAY, |
      TV_Add(A_LoopField, TV_GetNext(TV_GetSelection()))

}
If NEXTitemARRAY<>
{
   Loop, Parse, NEXTitemARRAY, |
      TV_Add(A_LoopField, TV_GetSelection())
}
TV_Modify(TV_GetSelection() , "", NEXTitem)
TV_Modify(TV_GetNext(TV_GetSelection()) , "Select", THISitem)
NEXTitemARRAY=
THISitemARRAY=
return
}
;------------------------------------------------------------------------------
Add(x, y)
{
 return x + y   ; "Return" expects an expression.
}
;------------------------------------------------------------------------------
Sub(x, y)
{
 return x - y   ; "Return" expects an expression.
}
Back to top
Chris
Site Admin


Joined: 02 Mar 2004
Posts: 10716

PostPosted: Sat Jul 15, 2006 12:57 pm    Post subject: Reply with quote

Nice-looking script (maybe a similar approach can be applied to ListViews). I'm glad you've created a means of drag-and-drop because it might be a while before built-in support is added.
Back to top
View user's profile Send private message Send e-mail
Terrapin



Joined: 15 Aug 2005
Posts: 107
Location: North Carolina

PostPosted: Mon Jul 17, 2006 8:36 am    Post subject: Reply with quote

Corey, it works very well as far as I can see. I had thought to try to do something similar with ListView, but it seems like it would take a great deal of brain-power I don't have. Smile I join Chris in asking whether this is possible with ListView? It seems it would be simpler than doing TreeView?

Thanks,

Bob
Back to top
View user's profile Send private message
MisterW



Joined: 20 Jul 2005
Posts: 65

PostPosted: Mon Jul 17, 2006 2:01 pm    Post subject: Tree Functions Reply with quote

Here are some functions I wrote to convert trees to strings and back. They can be used to handle cutting/copying/pasting/moving of brances or loading or saving trees to a file. They could be more robust in their handling of delimiters but they seem to work ok.

Below the functions is some sample code that uses them. The listview does nothing at the moment.

Code:
Tree2Str(id,byref str)
{
   TV_GetText(name,id)
   str=%str%%name%
   first_child := TV_GetChild(id)
   if first_child
   {
      str=%str%(
      Tree2Str(first_child,str)
      this_child := first_child
      Loop {
         next_child := TV_GetNext(this_child)
         if next_child {
            str=%str%,
            Tree2str(next_child,str)
            this_child := next_child
         } else
            break
      }
      str=%str%)
   }
   return
}

; This function will destroy the string passed to it.
; If you need it make a copy
Str2Tree(byref str, parent_id=0 , relative=0)
{
   Loop {
      name=
      maybe=
      size := StrLen(str)
      at_start=1
      count = 0
      Loop, parse, str
      {
         count := a_index
         c := a_loopfield

         if c = ,
         {
            r=0
            break
         } else if c = (
         {
            r=1
            break
         } else if c = )
         {
            r = -1
            break
         } else {
            a := Asc(c)
            if (a = 32) {
               if !at_start
                  maybe=%maybe%%c%
               ; else skip
            } else if (a > 8 and a < 14) { ; tabs, newlines, linefeeds and anything in between
               ; skip
            } else {
               at_start = 0
               if maybe {
                  name=%name%%maybe%%c%
                  maybe=
               } else
                  name=%name%%c%
            }
         }
      }
      if (count = size) ; string end
         r = -1
      StringTrimLeft,str,str,%count%

      if r < 0 ; Found ) or end of string
      {
         if name
            TV_add(name,parent_id)
         break
      } else if name {
         if relative
            new_id := TV_Add(name,parent_id,relative)
         else
            new_id := TV_Add(name,parent_id)
         if r > 0 ; Found (
            Str2Tree(str,new_id)
      }
   }
   return
}



Sample Code

Right Click on a node to get a context menu.

Code:

#SingleInstance Force

ThingString=
(
Things{
 Animals{
  Farm{Sheep,Goat,Cow,Horse,Chicken},
  Home{Dog,Cat,Hamster,Budgie,Goldfish}
 },
 Colors{
  Primary{Red,Green,Blue},
  Others{Yellow,Magenta,Cyan},
  Shades{Black,White}
 },
 Vehicles{
  Land{
   Motor{
    Car{Holden,Ford,Subaru,Mitsubishi,Toyota},
   Truck,Motorbike,Train},
   Other{Bike,Skateboard}
  },
  Sea{Boat,Submarine,Hydrofoil,Hovercraft},
  Air{Plane,Helicopter,Glider}
 }
}
)

StringReplace,ThingString,ThingString,{,(,A
StringReplace,ThingString,ThingString,},),A

Menu,ContextMenu,Add,Add,CMHandler
Menu,ContextMenu,Add,Add,CMHandler
Menu,ContextMenu,Add,Delete,CMHandler
Menu,ContextMenu,Add,
Menu,ContextMenu,Add,Cut,CMHandler
Menu,ContextMenu,Add,Copy,CMHandler
Menu,ContextMenu,Add,Paste,CMHandler
Menu,ContextMenu,Add,Insert Above,CMHandler
Menu,ContextMenu,Add,Insert Below,CMHandler

Gui,Font,s10 w1000,Arial
Gui,Add,TreeView, +Buttons cGreen vTVC AltSubmit gTVEvent,
Gui,Add,ListView, vLVC
copy=%ThingString%
Str2Tree(copy)
copy=%ThingString%
Str2Tree(copy)
Gui,+Resize
Gui,Show,w600 h450,Hello There
Gui,Add,StatusBar,,
return

GuiClose:
ExitApp

GuiSize:
tw := A_GuiWidth / 3
SB_SetParts(tw,tw)
th := A_GuiHeight - 35
GuiControl,Move,TVC,x5 y5 w%tw% h%th%
lw := 2 * (A_GuiWidth / 3) - 15
lh := th
lx := tw +10
GuiControl,Move,LVC,x%lx% y5 w%lw% h%lh%
return

TVEvent:
MouseGetPos,x,y
SB_SetText(A_GuiEvent,1)
SB_SetText(A_EventInfo,2)
SB_SetText(x . " , " . y,3)
if A_GuiEvent = RightClick
{
   TVSelected := A_EventInfo
   Menu,ContextMenu,Show,%x%,%y%
}
return

CMHandler:
op := A_ThisMenuItem
SB_SetText(op,1)

if op = Add
{
   InputBox,NewNode
   TV_Add(NewNode,TVSelected)
}
else if op = Delete
{
   TV_Delete(TVSelected)
}
else if op = Cut
{
   TreeBuffer=
   Tree2Str(TVSelected,TreeBuffer)
   TV_Delete(TVSelected)
}
else if op = Copy
{
   TreeBuffer=
   Tree2Str(TVSelected,TreeBuffer)
}
else if op = Paste
{
   Branch=%TreeBuffer%
   Str2Tree(Branch,TVSelected)
}
else if op = Insert Above
{
   Branch=%TreeBuffer%
   Sibling := TV_GetPrev(TVSelected)
   NewParent := TV_GetParent(TVSelected)
   if !Sibling
      Sibling=First
   Str2Tree(Branch,NewParent,Sibling)
}
else if op = Insert Below
{
   Branch=%TreeBuffer%
   NewParent := TV_GetParent(TVSelected)
   Str2Tree(Branch,NewParent,TVSelected)
}
return
Back to top
View user's profile Send private message
PhiLho



Joined: 27 Dec 2005
Posts: 6836
Location: France (near Paris)

PostPosted: Mon Jul 17, 2006 2:33 pm    Post subject: Re: Tree Functions Reply with quote

MisterW wrote:
Here are some functions I wrote to convert trees to strings and back.
Interesting. Perhaps using a more "standard" syntax like JSON, YAML or the like could be useful. Or not...
http://www.autohotkey.com/forum/viewtopic.php?t=10898&p=67614#67614
_________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group