File: repackanim.tcl

package info (click to toggle)
coccinella 0.96.20-7
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 13,108 kB
  • ctags: 5,908
  • sloc: tcl: 124,744; xml: 206; makefile: 66; sh: 62
file content (152 lines) | stat: -rw-r--r-- 3,320 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# repackanim.tcl ---
#
#       An utility to achive sliding toplevel height while swapping two
#       notebook pages.
#       
#  Usage: 
#       ::repackanim::swap frame1 frame2 ?-command tclProc -text str -widget key?
#       -widget typically "ttk::label %s -text Wait..."
#       
#  Copyright (c) 2007 Mats Bengtsson
#  
#  This source file is distributed under the BSD license.
#  
#  $Id: repackanim.tcl,v 1.3 2007-12-22 14:52:22 matben Exp $

package provide repackanim 0.1

namespace eval ::repackanim {
   
    variable options
    array set options {
	step   4
	millis 40
    }
}

proc ::repackanim::configure {args} {
    variable options
    
    array set options $args
}

proc ::repackanim::swap {wfrom wto args} {
    variable options
    
    set w [winfo toplevel $wfrom]
    if {$w ne [winfo toplevel $wto]} {
	puts stderr "Both widgets must belong to the same toplevel"
    }
    variable $w
    upvar 0 $w state

    array set opts {
	-command {}
	-text    "Loading page..."
	-widget  ""
    }
    array set opts $args
    set state(opts) [array get opts]
    set state(w)     $w
    set state(wfrom) $wfrom
    set state(wto)   $wto

    # Do this in order to get correct sizes.
    update idletasks
    set h1 [winfo reqheight $wfrom]
    set h2 [winfo reqheight $wto]
    set delta [expr {$h2 - $h1}]
    puts "::repackanim::repack h1=$h1, h2=$h2"

    wm positionfrom $w user

    set tmp ${wfrom}_tmp
    ttk::frame $tmp
    if {[string length $opts(-widget)]} {
	eval [format $opts(-widget) $tmp.label]
    } else {
	ttk::label $tmp.label -text $opts(-text)
    }
    place $tmp.label -x [expr {[winfo width $wfrom]/2}] -y [expr {$h1/2}] -anchor c
    
    pack forget $wfrom
    pack $tmp -fill both -expand 1
    
    set state(height) [expr {[winfo height $w] + $delta}]
    Animate $w
}

proc ::repackanim::Animate {w} {
    variable options
    variable $w
    upvar 0 $w state

    if {![winfo exists $w]} {
	unset -nocomplain state
    }
    set height $state(height)
    set geom [split [wm geometry $w] x+-]
    set h [lindex $geom 1]
    set sign [expr {$h < $height ? "+" : "-"}]
    if {$h == $height} {
	Final $w
	return
    }
    set step $options(step)
    #pack propagate $w 0
    if {$sign eq "+"} {
	set new [expr {$h + $step}]
	if {$new > $height} {
	    set h $height
	} else {
	    incr h $sign$step
	}
    } else {
	set new [expr {$h - $step}]
	if {$new < $height} {
	    set h $height
	} else {
	    incr h $sign$step
	}
    }
    wm geometry $w [lindex $geom 0]x$h
    after $options(millis) [namespace code [list Animate $w]]
}

proc ::repackanim::Final {w} {
    variable $w
    upvar 0 $w state

    puts "::repack::Final"
    if {![winfo exists $w]} {
	unset -nocomplain state
    }
    #pack propagate $w 1
    destroy $state(wfrom)_tmp
    pack $state(wto)
    array set opts $state(opts)
    if {[llength $opts(-command)]} {
	uplevel #0 $opts(-command)
    }
    unset -nocomplain state    
}

# Test code.
if {0} {    
    proc content {w n} {
	ttk::frame $w -padding 20
	for {set i 0} {$i < $n} {incr i} {
	    ttk::label $w.$i -text "Some junk number $i"
	    grid $w.$i -sticky w
	}
	return $w
    }

    set w .top
    toplevel $w
    set f1 [content $w.f1 10]
    set f2 [content $w.f2 20]
    pack $f1
    after 4000 [list ::repackanim::swap $f1 $f2]
}