Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

[module] TVX - Tree View eXtension


  • Please log in to reply
29 replies to this topic
majkinetor
  • Moderators
  • 4512 posts
  • Last active: May 20 2019 07:41 AM
  • Joined: 24 May 2006
TVX is extension for TreeView control to support moving, inserting and deleting. Once you call TVX function your tree view will become extended.


Key Bindings :
INSERT        - add new item
   SHIFT INSERT        - add new group
         DELETE        - delete item or group
   SHIFT   UP          - move item up    
   SHIFT  DOWN         - move item down

Current API is as follows (documentation currently in the source):

TVX  - Initialisation function. Mandatory to call before you show the TreeView.

Walk - Walk the menu and rise events. Check out Save button in Example
Move - Moves tree view item up or down

Copy - Copies menu item or group to another location. Exists in the code as TVX_CopyItem, but still not documented and properly interfaced. 

Download (with example)

Posted Image
Basic Example:
Gui, Add, TreeView, h400 w300 [color=brown]vMyTree[/color]

	root  := TV_Add("Root", "" , "Expand")
	loop, 10 
		P     := TV_Add(A_Index, root)

[color=red]	TVX("MyTree", "Handler", "HasRoot CollapseOnMove ")[/color]
	Gui, Show,  autosize
return


Handler:
return

[color=brown]#include TVX.ahk[/color]	

Check out Walk example here

Documentation
;----------------------------------------------------------------------------------------
; Function:     TVX
;               Initialisation function. Mandatory to call before you show the TreeView.
; 
; Parameters:
;               pTree       - AHK name of the TreeView control
;               pSub        - Subroutine for TreeViewX, the same rules as in g.
;               pOptions    - String containing space delimited options for setting up TreeViewX
;               pUserData   - Base name of the array holding user data. 
;                             This array is indexed using tree view item handles.
;           
; Options: 
;               HasRoot     - TreeViewX has root item - the one containing all other items. 
;                             Root item can't be moved, edited or delited, and items can not
;                             be moved or created outside of it. This option need to be set 
;                             after root is already added to the menu, as TreeViewX need to
;                             know the root menu handle.
;                         
;           CollapseOnMove  - When moving item out of of its container, this option makes container collapse
;           EditOnInsert    - Automaticaly enters edit mode upon insertion of new item
;
; Example:
;>
;>          TVX("MyTree", "Handler", "HasRoot CollapseOnMove")
;>
;----------------------------------------------------------------------------------------
; Function:     Walk
;               Walk the menu and rise events
; 
; Parameters:
;               root        - menu to iterate, can be simple item also
;               label       - event handler
;               event_type  - event argument 1 - Event type
;               event_param - event argument 2 - Item upon which event is rised
;           
;
;                  Type                       Param
;
;           +  - Iteration start,           root handle
;           M  - Menu item,                 menu handle 
;           I  - Item,                      item handle
;           E  - End of menu                menu handle         (pseudo item)
;           -  - Iteration end              root handle         (pseudo item)
;
;----------------------------------------------------------------------------------------------
; Function:     Move
;               Moves tree view item up or down
;
; Parameters:
;               item        -   Handle of the item to move
;               direction   -   "u" or "d" (Up & Down)
;
; Returns:
;               Handle of the item
;
; Remarks:
;               Item to be moved is copied to the new place then source item is deleted. This
;               creates new handle for the moved item. New handle will be returned by the function.
;

Posted Image

Rabiator
  • Members
  • 292 posts
  • Last active: Aug 29 2016 09:29 PM
  • Joined: 17 Apr 2005
majkinetor, nice work!! 8)
Now I'll retry a script that I discarded exactly because these modifying possibilities were missing.

Thanks for this facility!

majkinetor
  • Moderators
  • 4512 posts
  • Last active: May 20 2019 07:41 AM
  • Joined: 24 May 2006
This is Walk example. It will save entire tree in the text file on button click.
Walk handler is called for every item in the treeview and few more times for pseudo items (end of menu, end of iteration). Events specify some points of general interest. You can use Walk for whatever kind of processing you need upon treeview enteries, while being informed about hierarchy details.


OnBtnClick:
	TVX_Walk(root, "[color=blue]SaveHandler[/color]", [color=red]Event[/color], [color=green]Item[/color])
return

[color=blue]SaveHandler[/color]:
    TV_GetText(txt, [color=green]Item[/color])                   
    if [color=red]Event[/color] = +                                ;start of iteration, called only for root
    {
        FileDelete, _out.txt 
        FileAppend %txt%`n, _out.txt
        line := "|-"
    }

    if [color=red]Event[/color] = E
        StringTrimRight, line, line, 2          ;end of group
    
    if [color=red]Event[/color] in I,M                             ;I=simple item, M=group item  
        FileAppend %line%%txt%, _out.txt


    if [color=red]Event[/color] = M                                ;start of group
        line .= "--"
    
    if [color=red]Event[/color] = -                                ;end of iteration
        Msgbox, TVX saved in _out.txt
return


Posted Image

Rajat
  • Members
  • 1904 posts
  • Last active: Jul 17 2015 07:45 AM
  • Joined: 28 Mar 2004
cool additions to TView control... I did similar additions from scratch in a couple of my scripts but never coaxed myself into writing a function. thanks for doing it! :)

MIA

CleanNews.in : Bite sized latest news headlines from India with zero bloat


Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004
Great extension and presentation. I've linked to this topic from the remarks section of the TreeView page.

Rajat
  • Members
  • 1904 posts
  • Last active: Jul 17 2015 07:45 AM
  • Joined: 28 Mar 2004
what do you use to make these demo gifs?
thanks

MIA

CleanNews.in : Bite sized latest news headlines from India with zero bloat


majkinetor
  • Moderators
  • 4512 posts
  • Last active: May 20 2019 07:41 AM
  • Joined: 24 May 2006
Different stuff.

- Camstudio (freeware, portable)
Makes a video of what you do in region you specify. You have hotkeys to pause recording so you can pause when you want to add anotations. You also have hotkey "next anotation" so if you order then chronologicaly you can just record and press this hotkey when you want. This will generaly give you about 60MB avi.

- GIF Movie Gear (shareware, can be portable)
Then, you load this video here. It will show frames, so you can remove frames you don't like. After that you optimise gif with this tool so it becomes very small (optimisation means that only picture differences will be kept, so if you have several static frames, only 1 will be saved, if dot moved on 4th frame, only that dot will saved..). Then you save it as gif animation which gives you 300KB for longer gifs.

- Bannershop GIF Animator (shareware, can be portable)
You can create here banners , like the one in your signature. You can save short bunners and insert them at frame location using GIF Movie Gear. This allows you more proffesional presentation, with transitions etc..
For instance, take first frame of your movie and save it as a picture. Load this picture in Banner Animator and create fade in. Save this gif and load it at the start of your movie in GIF Movie Gear. This joines transitional gif and large gif into single one.


Don't create gifs larger then 300KB. Although they work nice standalone, they usualy crash all browsers or make local CPU burn. 300KB is generaly enough for 2 minutes of presentation. This depends on contenst of your presentation. If frames are "too moving" optimisation will be less effective and you will have larger gif.
Posted Image

Rajat
  • Members
  • 1904 posts
  • Last active: Jul 17 2015 07:45 AM
  • Joined: 28 Mar 2004
that's really useful explanation... thanks for the info.
i'll copy this to my notes program, i'm sure this'll come in handy. :)

MIA

CleanNews.in : Bite sized latest news headlines from India with zero bloat


T800
  • Members
  • 107 posts
  • Last active: Feb 01 2014 11:14 PM
  • Joined: 15 Oct 2006
This really should be integrated into ahk runtime.

animeaime
  • Members
  • 1045 posts
  • Last active: Jun 18 2011 04:44 AM
  • Joined: 04 Nov 2008
I just wanted to say great job - a much needed function.

Also, I wanted to mention, in case you didn't know, the code enters an infinite loop when trying to copy an item to one of its children. The included TVX_isAncestor can be used as a check to prevent this. You can modify this function as needed.

Gui, Add, TreeView, vMyTreeView

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)
P2C2C1 := TV_Add("Child 2's grandchild", P2C2C1)

;infinite loop when coping an item to its child
;e.g. cannot copy P2 to the first child of P2C2C1

;if P2 is an ancestor of P2C2C1 (which it is), then the Copy cannot be done
;commenting out this check results in an infinite loop
if !TVX_isAncestor(P2, P2C2C1)
    TVX_CopyItem("First", P2C2C1, P2)
    
;however, since P1 is not an Ancestor of P2C2, this copy can be done
if !TVX_isAncestor(P1, P2C2)
    TVX_CopyItem("First", P2C2, P1)

Gui, Show

return

TVX_isAncestor(Ancestor, TestItem)
{
    ;returns true if Ancestor is an ancestor of the TestItem
    
    Loop
    {
        if (Ancestor = TestItem)
            return true
            
        if (!TestItem := TV_getParent(TestItem))
        {
            ;TestItem has no parent
            return false
        }
    }
}

I know that an infinite loop is the result of doing an impossible task. Thus, this should be done to verify that the source is not a parent of the destination.
As always, if you have any further questions, don't hesitate to ask.

Add OOP to your scripts via the Class Library. Check out my scripts.

majkinetor
  • Moderators
  • 4512 posts
  • Last active: May 20 2019 07:41 AM
  • Joined: 24 May 2006
Thx. Ill see to explicitelly forbid that.
Posted Image

-Dexter-
  • Guests
  • Last active:
  • Joined: --
Hi majkinetor. :)
Sorry for the offtopic. I looked through your code and some parts look very confusing to me, though I'm very interested in learning more about the syntax. For example:

TVX_sel := TVX_Move( TVX_prevSel, TVX_lastKey=40 ? "d" : "u")

and this ("return true" is particularly interesting)
if (TVX_bSelfSelect)	{	
	TVX_bSelfSelect := false
	return true
}

Can you please point me in a direction where I can find more information about it? Thanks!

Joy2DWorld
  • Members
  • 562 posts
  • Last active: Jun 30 2014 07:48 PM
  • Joined: 04 Dec 2006
see AHK help file under "Variables and Expressions".


also in same place, "?" is Ternary operator, explained there.



hope helpful.
Joyce Jamce

-Dexter-
  • Guests
  • Last active:
  • Joined: --
Thanks Joy2DWorld! :)

This is one of the fundamental sections that I read with one eye closed. I'll need to dig deeper into that.

rexx
  • Members
  • 73 posts
  • Last active: Sep 25 2009 03:23 AM
  • Joined: 28 Feb 2006
hi
i've used this in my script, and i found that if i hold shift, and press up down many times, sometimes it will go wrong.

and i modified the insert code, first is clear the user data, because i found that after i destory a gui and create it again, the ItemID may be the same as a previously used one. so i clear the associated data on creating an item to avoid using the old data.

the other little modification is inserting on an expanded item. i make the new item be the selected item's first child, where i expect it to be added.

;insert
	if pKey = 45
	{
		tp := TV_GetParent(TVX_sel)
		if (TVX_sel = TVX_root)
			tp := TVX_root

		if TV_Get(TVX_sel, "E")
			tp := TV_Add("New Item", TVX_sel, "Select Bold First")
		else
			tp := TV_Add("New Item", tp, "Select Bold " . TVX_sel)
		%TVX_UserData%%tp% = ; clear data
		if GetKeyState("Shift")
		{
			tttt := TV_Add("New Item", tp, "Bold First ")
			%TVX_UserData%%tttt% = ; clear data
			TV_Modify(tp,"Expand", "New Menu")
		}

		if (TVX_EditOnInsert)
		{
			TVX_bSelfPress := TVX_bSelfSelect := true
			TV_Modify(tp, "Select")
			Send, {F2}
		}

		return true
	}

and the last, when moving up an item in to an expanded group, the item becomes the first item of that group. but i expect it to be the last item in that group.

; if submenu is expanded, go into it
			t := TV_Get(p, "E")
			if (t = p)
			{
				newc := TV_GetChild(p)
				Loop
				{
					c := TV_GetNext(newc)
					if c = 0
						break
					newc := c
				}
;				newc := "First"
				newp := t
			}