Version 2 of Drag and Drop Notebook Tabs

Updated 2010-07-26 23:27:07 by CJB

CJB: An example of how to make drag and drop tabs with a ttk::notebook.


#Create notebook
set n [ttk::notebook .nb]
pack $n -fill both -expand 1

#Create tabs
foreach tab [list First Second Third] {
    set w [frame $n.[string tolower $tab]]
    label $w.src_lab -text "Clicked Tab Index:"
    label $w.src_idx -textvariable src_index
    label $w.dst_lab -text "Released Tab Index:"
    label $w.dst_idx -textvariable dst_index
    grid $w.src_lab $w.src_idx -in $w -sticky news
    grid $w.dst_lab $w.dst_idx -in $w -sticky news
    $n add $w -text $tab
    bindtags $w [linsert [bindtags $w] 1 DropTarget]
}

#Bindings
bind all <KeyPress-question> {console show}
bind $n <ButtonPress>   [list click   %W %x %y]
bind $n <ButtonRelease> [list release %W %x %y]
bind $n <Motion>        [list motion  %W %X %Y]

#Sets index of tab clicked.
proc click   {W x y} {
    variable src_index [$W index @$x,$y]
    puts stderr "click $src_index"
}

#Moves the tab to the position where it was dropped.
proc release {W x y} {
    variable src_index
    variable dst_index
    puts stderr "Release $src_index"
    #Check for a valid source
    if {[string is int -strict $src_index]} {
        set dst_index [$W index @$x,$y]
        #Check for a valid destination
        if {[string is int -strict $dst_index]} {
            set tab [lindex [$W tabs] $src_index]
            $W insert $dst_index $tab
            puts stderr "insert $dst_index $tab"
        }
    }
}

#Passes mouse motion events to underlying widgets while dragging.
#Allows the notebook tabs to highlight on mouse-over.
proc motion  {W X Y} {
    set w [winfo containing $X $Y]
    if {$w ne $W && $w ne ""} {
        set x [expr {$X - [winfo rootx $w]}]
        set y [expr {$Y - [winfo rooty $w]}]
        event generate $w <Motion> -x $x -y $y
    }
}