summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xgit-gui.sh27
-rw-r--r--lib/blame.tcl24
-rw-r--r--lib/checkout_op.tcl15
-rw-r--r--lib/choose_repository.tcl120
-rw-r--r--lib/index.tcl31
-rw-r--r--lib/merge.tcl14
-rw-r--r--lib/status_bar.tcl231
7 files changed, 354 insertions, 108 deletions
diff --git a/git-gui.sh b/git-gui.sh
index 0d21f5688b..e317f528af 100755
--- a/git-gui.sh
+++ b/git-gui.sh
@@ -1797,10 +1797,10 @@ proc ui_status {msg} {
}
}
-proc ui_ready {{test {}}} {
+proc ui_ready {} {
global main_status
if {[info exists main_status]} {
- $main_status show [mc "Ready."] $test
+ $main_status show [mc "Ready."]
}
}
@@ -2150,8 +2150,6 @@ proc incr_font_size {font {amt 1}} {
##
## ui commands
-set starting_gitk_msg [mc "Starting gitk... please wait..."]
-
proc do_gitk {revs {is_submodule false}} {
global current_diff_path file_states current_diff_side ui_index
global _gitdir _gitworktree
@@ -2206,10 +2204,11 @@ proc do_gitk {revs {is_submodule false}} {
set env(GIT_WORK_TREE) $_gitworktree
cd $pwd
- ui_status $::starting_gitk_msg
- after 10000 {
- ui_ready $starting_gitk_msg
- }
+ set status_operation [$::main_status \
+ start \
+ [mc "Starting %s... please wait..." "gitk"]]
+
+ after 3500 [list $status_operation stop]
}
}
@@ -2240,10 +2239,11 @@ proc do_git_gui {} {
set env(GIT_WORK_TREE) $_gitworktree
cd $pwd
- ui_status $::starting_gitk_msg
- after 10000 {
- ui_ready $starting_gitk_msg
- }
+ set status_operation [$::main_status \
+ start \
+ [mc "Starting %s... please wait..." "git-gui"]]
+
+ after 3500 [list $status_operation stop]
}
}
@@ -4159,6 +4159,9 @@ if {$picked && [is_config_true gui.autoexplore]} {
do_explore
}
+# Clear "Initializing..." status
+after 500 {$main_status show ""}
+
# Local variables:
# mode: tcl
# indent-tabs-mode: t
diff --git a/lib/blame.tcl b/lib/blame.tcl
index a1aeb8b96e..62ec083667 100644
--- a/lib/blame.tcl
+++ b/lib/blame.tcl
@@ -24,6 +24,7 @@ field w_cviewer ; # pane showing commit message
field finder ; # find mini-dialog frame
field gotoline ; # line goto mini-dialog frame
field status ; # status mega-widget instance
+field status_operation ; # operation displayed by status mega-widget
field old_height ; # last known height of $w.file_pane
@@ -274,6 +275,7 @@ constructor new {i_commit i_path i_jump} {
pack $w_cviewer -expand 1 -fill both
set status [::status_bar::new $w.status]
+ set status_operation {}
menu $w.ctxm -tearoff 0
$w.ctxm add command \
@@ -602,16 +604,23 @@ method _exec_blame {cur_w cur_d options cur_s} {
} else {
lappend options $commit
}
+
+ # We may recurse in from another call to _exec_blame and already have
+ # a status operation.
+ if {$status_operation == {}} {
+ set status_operation [$status start \
+ $cur_s \
+ [mc "lines annotated"]]
+ } else {
+ $status_operation restart $cur_s
+ }
+
lappend options -- $path
set fd [eval git_read --nice blame $options]
fconfigure $fd -blocking 0 -translation lf -encoding utf-8
fileevent $fd readable [cb _read_blame $fd $cur_w $cur_d]
set current_fd $fd
set blame_lines 0
-
- $status start \
- $cur_s \
- [mc "lines annotated"]
}
method _read_blame {fd cur_w cur_d} {
@@ -806,10 +815,11 @@ method _read_blame {fd cur_w cur_d} {
[mc "Loading original location annotations..."]
} else {
set current_fd {}
- $status stop [mc "Annotation complete."]
+ $status_operation stop [mc "Annotation complete."]
+ set status_operation {}
}
} else {
- $status update $blame_lines $total_lines
+ $status_operation update $blame_lines $total_lines
}
} ifdeleted { catch {close $fd} }
@@ -1124,7 +1134,7 @@ method _blameparent {} {
set diffcmd [list diff-tree --unified=0 $cparent $cmit -- $new_path]
}
if {[catch {set fd [eval git_read $diffcmd]} err]} {
- $status stop [mc "Unable to display parent"]
+ $status_operation stop [mc "Unable to display parent"]
error_popup [strcat [mc "Error loading diff:"] "\n\n$err"]
return
}
diff --git a/lib/checkout_op.tcl b/lib/checkout_op.tcl
index a5228297db..21ea768d80 100644
--- a/lib/checkout_op.tcl
+++ b/lib/checkout_op.tcl
@@ -341,9 +341,9 @@ method _readtree {} {
global HEAD
set readtree_d {}
- $::main_status start \
+ set status_bar_operation [$::main_status start \
[mc "Updating working directory to '%s'..." [_name $this]] \
- [mc "files checked out"]
+ [mc "files checked out"]]
set fd [git_read --stderr read-tree \
-m \
@@ -354,26 +354,27 @@ method _readtree {} {
$new_hash \
]
fconfigure $fd -blocking 0 -translation binary
- fileevent $fd readable [cb _readtree_wait $fd]
+ fileevent $fd readable [cb _readtree_wait $fd $status_bar_operation]
}
-method _readtree_wait {fd} {
+method _readtree_wait {fd status_bar_operation} {
global current_branch
set buf [read $fd]
- $::main_status update_meter $buf
+ $status_bar_operation update_meter $buf
append readtree_d $buf
fconfigure $fd -blocking 1
if {![eof $fd]} {
fconfigure $fd -blocking 0
+ $status_bar_operation stop
return
}
if {[catch {close $fd}]} {
set err $readtree_d
regsub {^fatal: } $err {} err
- $::main_status stop [mc "Aborted checkout of '%s' (file level merging is required)." [_name $this]]
+ $status_bar_operation stop [mc "Aborted checkout of '%s' (file level merging is required)." [_name $this]]
warn_popup [strcat [mc "File level merge required."] "
$err
@@ -384,7 +385,7 @@ $err
return
}
- $::main_status stop
+ $status_bar_operation stop
_after_readtree $this
}
diff --git a/lib/choose_repository.tcl b/lib/choose_repository.tcl
index 80f5a59bbb..e54f3e66d8 100644
--- a/lib/choose_repository.tcl
+++ b/lib/choose_repository.tcl
@@ -9,6 +9,18 @@ field w_body ; # Widget holding the center content
field w_next ; # Next button
field w_quit ; # Quit button
field o_cons ; # Console object (if active)
+
+# Status mega-widget instance during _do_clone2 (used by _copy_files and
+# _link_files). Widget is destroyed before _do_clone2 calls
+# _do_clone_checkout
+field o_status
+
+# Operation displayed by status mega-widget during _do_clone_checkout =>
+# _readtree_wait => _postcheckout_wait => _do_clone_submodules =>
+# _do_validate_submodule_cloning. The status mega-widget is a different
+# instance than that stored in $o_status in earlier operations.
+field o_status_op
+
field w_types ; # List of type buttons in clone
field w_recentlist ; # Listbox containing recent repositories
field w_localpath ; # Entry widget bound to local_path
@@ -659,12 +671,12 @@ method _do_clone2 {} {
switch -exact -- $clone_type {
hardlink {
- set o_cons [status_bar::two_line $w_body]
+ set o_status [status_bar::two_line $w_body]
pack $w_body -fill x -padx 10 -pady 10
- $o_cons start \
+ set status_op [$o_status start \
[mc "Counting objects"] \
- [mc "buckets"]
+ [mc "buckets"]]
update
if {[file exists [file join $objdir info alternates]]} {
@@ -689,6 +701,7 @@ method _do_clone2 {} {
} err]} {
catch {cd $pwd}
_clone_failed $this [mc "Unable to copy objects/info/alternates: %s" $err]
+ $status_op stop
return
}
}
@@ -700,7 +713,7 @@ method _do_clone2 {} {
-directory [file join $objdir] ??]
set bcnt [expr {[llength $buckets] + 2}]
set bcur 1
- $o_cons update $bcur $bcnt
+ $status_op update $bcur $bcnt
update
file mkdir [file join .git objects pack]
@@ -708,7 +721,7 @@ method _do_clone2 {} {
-directory [file join $objdir pack] *] {
lappend tolink [file join pack $i]
}
- $o_cons update [incr bcur] $bcnt
+ $status_op update [incr bcur] $bcnt
update
foreach i $buckets {
@@ -717,10 +730,10 @@ method _do_clone2 {} {
-directory [file join $objdir $i] *] {
lappend tolink [file join $i $j]
}
- $o_cons update [incr bcur] $bcnt
+ $status_op update [incr bcur] $bcnt
update
}
- $o_cons stop
+ $status_op stop
if {$tolink eq {}} {
info_popup [strcat \
@@ -747,6 +760,8 @@ method _do_clone2 {} {
if {!$i} return
destroy $w_body
+
+ set o_status {}
}
full {
set o_cons [console::embed \
@@ -781,9 +796,9 @@ method _do_clone2 {} {
}
method _copy_files {objdir tocopy} {
- $o_cons start \
+ set status_op [$o_status start \
[mc "Copying objects"] \
- [mc "KiB"]
+ [mc "KiB"]]
set tot 0
set cmp 0
foreach p $tocopy {
@@ -798,7 +813,7 @@ method _copy_files {objdir tocopy} {
while {![eof $f_in]} {
incr cmp [fcopy $f_in $f_cp -size 16384]
- $o_cons update \
+ $status_op update \
[expr {$cmp / 1024}] \
[expr {$tot / 1024}]
update
@@ -808,17 +823,19 @@ method _copy_files {objdir tocopy} {
close $f_cp
} err]} {
_clone_failed $this [mc "Unable to copy object: %s" $err]
+ $status_op stop
return 0
}
}
+ $status_op stop
return 1
}
method _link_files {objdir tolink} {
set total [llength $tolink]
- $o_cons start \
+ set status_op [$o_status start \
[mc "Linking objects"] \
- [mc "objects"]
+ [mc "objects"]]
for {set i 0} {$i < $total} {} {
set p [lindex $tolink $i]
if {[catch {
@@ -827,15 +844,17 @@ method _link_files {objdir tolink} {
[file join $objdir $p]
} err]} {
_clone_failed $this [mc "Unable to hardlink object: %s" $err]
+ $status_op stop
return 0
}
incr i
if {$i % 5 == 0} {
- $o_cons update $i $total
+ $status_op update $i $total
update
}
}
+ $status_op stop
return 1
}
@@ -958,11 +977,26 @@ method _do_clone_checkout {HEAD} {
return
}
- set o_cons [status_bar::two_line $w_body]
+ set status [status_bar::two_line $w_body]
pack $w_body -fill x -padx 10 -pady 10
- $o_cons start \
+
+ # We start the status operation here.
+ #
+ # This function calls _readtree_wait as a callback.
+ #
+ # _readtree_wait in turn either calls _do_clone_submodules directly,
+ # or calls _postcheckout_wait as a callback which then calls
+ # _do_clone_submodules.
+ #
+ # _do_clone_submodules calls _do_validate_submodule_cloning.
+ #
+ # _do_validate_submodule_cloning stops the status operation.
+ #
+ # There are no other calls into this chain from other code.
+
+ set o_status_op [$status start \
[mc "Creating working directory"] \
- [mc "files"]
+ [mc "files"]]
set readtree_err {}
set fd [git_read --stderr read-tree \
@@ -976,33 +1010,9 @@ method _do_clone_checkout {HEAD} {
fileevent $fd readable [cb _readtree_wait $fd]
}
-method _do_validate_submodule_cloning {ok} {
- if {$ok} {
- $o_cons done $ok
- set done 1
- } else {
- _clone_failed $this [mc "Cannot clone submodules."]
- }
-}
-
-method _do_clone_submodules {} {
- if {$recursive eq {true}} {
- destroy $w_body
- set o_cons [console::embed \
- $w_body \
- [mc "Cloning submodules"]]
- pack $w_body -fill both -expand 1 -padx 10
- $o_cons exec \
- [list git submodule update --init --recursive] \
- [cb _do_validate_submodule_cloning]
- } else {
- set done 1
- }
-}
-
method _readtree_wait {fd} {
set buf [read $fd]
- $o_cons update_meter $buf
+ $o_status_op update_meter $buf
append readtree_err $buf
fconfigure $fd -blocking 1
@@ -1050,6 +1060,34 @@ method _postcheckout_wait {fd_ph} {
fconfigure $fd_ph -blocking 0
}
+method _do_clone_submodules {} {
+ if {$recursive eq {true}} {
+ $o_status_op stop
+ set o_status_op {}
+
+ destroy $w_body
+
+ set o_cons [console::embed \
+ $w_body \
+ [mc "Cloning submodules"]]
+ pack $w_body -fill both -expand 1 -padx 10
+ $o_cons exec \
+ [list git submodule update --init --recursive] \
+ [cb _do_validate_submodule_cloning]
+ } else {
+ set done 1
+ }
+}
+
+method _do_validate_submodule_cloning {ok} {
+ if {$ok} {
+ $o_cons done $ok
+ set done 1
+ } else {
+ _clone_failed $this [mc "Cannot clone submodules."]
+ }
+}
+
######################################################################
##
## Open Existing Repository
diff --git a/lib/index.tcl b/lib/index.tcl
index 28d4d2a54e..62f4773ef4 100644
--- a/lib/index.tcl
+++ b/lib/index.tcl
@@ -45,13 +45,13 @@ proc _close_updateindex {fd after} {
wm deiconify $w
tkwait window $w
- $::main_status stop
+ $::main_status stop_all
unlock_index
rescan $after 0
return
}
- $::main_status stop
+ $::main_status stop_all
unlock_index
uplevel #0 $after
}
@@ -67,7 +67,7 @@ proc update_indexinfo {msg path_list after} {
set batch [expr {int($total_cnt * .01) + 1}]
if {$batch > 25} {set batch 25}
- $::main_status start $msg [mc "files"]
+ set status_bar_operation [$::main_status start $msg [mc "files"]]
set fd [git_write update-index -z --index-info]
fconfigure $fd \
-blocking 0 \
@@ -81,15 +81,18 @@ proc update_indexinfo {msg path_list after} {
$path_list \
$total_cnt \
$batch \
+ $status_bar_operation \
$after \
]
}
-proc write_update_indexinfo {fd path_list total_cnt batch after} {
+proc write_update_indexinfo {fd path_list total_cnt batch status_bar_operation \
+ after} {
global update_index_cp
global file_states current_diff_path
if {$update_index_cp >= $total_cnt} {
+ $status_bar_operation stop
_close_updateindex $fd $after
return
}
@@ -119,7 +122,7 @@ proc write_update_indexinfo {fd path_list total_cnt batch after} {
display_file $path $new
}
- $::main_status update $update_index_cp $total_cnt
+ $status_bar_operation update $update_index_cp $total_cnt
}
proc update_index {msg path_list after} {
@@ -133,7 +136,7 @@ proc update_index {msg path_list after} {
set batch [expr {int($total_cnt * .01) + 1}]
if {$batch > 25} {set batch 25}
- $::main_status start $msg [mc "files"]
+ set status_bar_operation [$::main_status start $msg [mc "files"]]
set fd [git_write update-index --add --remove -z --stdin]
fconfigure $fd \
-blocking 0 \
@@ -147,15 +150,18 @@ proc update_index {msg path_list after} {
$path_list \
$total_cnt \
$batch \
+ $status_bar_operation \
$after \
]
}
-proc write_update_index {fd path_list total_cnt batch after} {
+proc write_update_index {fd path_list total_cnt batch status_bar_operation \
+ after} {
global update_index_cp
global file_states current_diff_path
if {$update_index_cp >= $total_cnt} {
+ $status_bar_operation stop
_close_updateindex $fd $after
return
}
@@ -190,7 +196,7 @@ proc write_update_index {fd path_list total_cnt batch after} {
display_file $path $new
}
- $::main_status update $update_index_cp $total_cnt
+ $status_bar_operation update $update_index_cp $total_cnt
}
proc checkout_index {msg path_list after} {
@@ -204,7 +210,7 @@ proc checkout_index {msg path_list after} {
set batch [expr {int($total_cnt * .01) + 1}]
if {$batch > 25} {set batch 25}
- $::main_status start $msg [mc "files"]
+ set status_bar_operation [$::main_status start $msg [mc "files"]]
set fd [git_write checkout-index \
--index \
--quiet \
@@ -224,15 +230,18 @@ proc checkout_index {msg path_list after} {
$path_list \
$total_cnt \
$batch \
+ $status_bar_operation \
$after \
]
}
-proc write_checkout_index {fd path_list total_cnt batch after} {
+proc write_checkout_index {fd path_list total_cnt batch status_bar_operation \
+ after} {
global update_index_cp
global file_states current_diff_path
if {$update_index_cp >= $total_cnt} {
+ $status_bar_operation stop
_close_updateindex $fd $after
return
}
@@ -253,7 +262,7 @@ proc write_checkout_index {fd path_list total_cnt batch after} {
}
}
- $::main_status update $update_index_cp $total_cnt
+ $status_bar_operation update $update_index_cp $total_cnt
}
proc unstage_helper {txt paths} {
diff --git a/lib/merge.tcl b/lib/merge.tcl
index 9f253db5b3..8df8ffae55 100644
--- a/lib/merge.tcl
+++ b/lib/merge.tcl
@@ -241,23 +241,27 @@ Continue with resetting the current changes?"]
if {[ask_popup $op_question] eq {yes}} {
set fd [git_read --stderr read-tree --reset -u -v HEAD]
fconfigure $fd -blocking 0 -translation binary
- fileevent $fd readable [namespace code [list _reset_wait $fd]]
- $::main_status start [mc "Aborting"] [mc "files reset"]
+ set status_bar_operation [$::main_status \
+ start \
+ [mc "Aborting"] \
+ [mc "files reset"]
+ fileevent $fd readable [namespace code [list \
+ _reset_wait $fd $status_bar_operation]]
} else {
unlock_index
}
}
-proc _reset_wait {fd} {
+proc _reset_wait {fd status_bar_operation} {
global ui_comm
- $::main_status update_meter [read $fd]
+ $status_bar_operation update_meter [read $fd]
fconfigure $fd -blocking 1
if {[eof $fd]} {
set fail [catch {close $fd} err]
- $::main_status stop
unlock_index
+ $status_bar_operation stop
$ui_comm delete 0.0 end
$ui_comm edit modified false
diff --git a/lib/status_bar.tcl b/lib/status_bar.tcl
index 02111a1742..d32b14142f 100644
--- a/lib/status_bar.tcl
+++ b/lib/status_bar.tcl
@@ -1,16 +1,42 @@
# git-gui status bar mega-widget
# Copyright (C) 2007 Shawn Pearce
+# The status_bar class manages the entire status bar. It is possible for
+# multiple overlapping asynchronous operations to want to display status
+# simultaneously. Each one receives a status_bar_operation when it calls the
+# start method, and the status bar combines all active operations into the
+# line of text it displays. Most of the time, there will be at most one
+# ongoing operation.
+#
+# Note that the entire status bar can be either in single-line or two-line
+# mode, depending on the constructor. Multiple active operations are only
+# supported for single-line status bars.
+
class status_bar {
+field allow_multiple ; # configured at construction
+
field w ; # our own window path
field w_l ; # text widget we draw messages into
field w_c ; # canvas we draw a progress bar into
field c_pack ; # script to pack the canvas with
-field status {}; # single line of text we show
-field prefix {}; # text we format into status
-field units {}; # unit of progress
-field meter {}; # current core git progress meter (if active)
+
+field baseline_text ; # text to show if there are no operations
+field status_bar_text ; # combined text for all operations
+
+field operations ; # list of current ongoing operations
+
+# The status bar can display a progress bar, updated when consumers call the
+# update method on their status_bar_operation. When there are multiple
+# operations, the status bar shows the combined status of all operations.
+#
+# When an overlapping operation completes, the progress bar is going to
+# abruptly have one fewer operation in the calculation, causing a discontinuity.
+# Therefore, whenever an operation completes, if it is not the last operation,
+# this counter is increased, and the progress bar is calculated as though there
+# were still another operation at 100%. When the last operation completes, this
+# is reset to 0.
+field completed_operation_count
constructor new {path} {
global use_ttk NS
@@ -18,12 +44,19 @@ constructor new {path} {
set w_l $w.l
set w_c $w.c
+ # Standard single-line status bar: Permit overlapping operations
+ set allow_multiple 1
+
+ set baseline_text ""
+ set operations [list]
+ set completed_operation_count 0
+
${NS}::frame $w
if {!$use_ttk} {
$w configure -borderwidth 1 -relief sunken
}
${NS}::label $w_l \
- -textvariable @status \
+ -textvariable @status_bar_text \
-anchor w \
-justify left
pack $w_l -side left
@@ -44,9 +77,16 @@ constructor two_line {path} {
set w_l $w.l
set w_c $w.c
+ # Two-line status bar: Only one ongoing operation permitted.
+ set allow_multiple 0
+
+ set baseline_text ""
+ set operations [list]
+ set completed_operation_count 0
+
${NS}::frame $w
${NS}::label $w_l \
- -textvariable @status \
+ -textvariable @status_bar_text \
-anchor w \
-justify left
pack $w_l -anchor w -fill x
@@ -56,7 +96,7 @@ constructor two_line {path} {
return $this
}
-method start {msg uds} {
+method ensure_canvas {} {
if {[winfo exists $w_c]} {
$w_c coords bar 0 0 0 20
} else {
@@ -68,31 +108,170 @@ method start {msg uds} {
$w_c create rectangle 0 0 0 20 -tags bar -fill navy
eval $c_pack
}
+}
+
+method show {msg} {
+ $this ensure_canvas
+ set baseline_text $msg
+ $this refresh
+}
+
+method start {msg {uds {}}} {
+ set baseline_text ""
+
+ if {!$allow_multiple && [llength $operations]} {
+ return [lindex $operations 0]
+ }
+
+ $this ensure_canvas
+
+ set operation [status_bar_operation::new $this $msg $uds]
+
+ lappend operations $operation
+
+ $this refresh
+
+ return $operation
+}
+
+method refresh {} {
+ set new_text ""
+
+ set total [expr $completed_operation_count * 100]
+ set have $total
+
+ foreach operation $operations {
+ if {$new_text != ""} {
+ append new_text " / "
+ }
+
+ append new_text [$operation get_status]
+
+ set total [expr $total + 100]
+ set have [expr $have + [$operation get_progress]]
+ }
+
+ if {$new_text == ""} {
+ set new_text $baseline_text
+ }
+
+ set status_bar_text $new_text
+
+ if {[winfo exists $w_c]} {
+ set pixel_width 0
+ if {$have > 0} {
+ set pixel_width [expr {[winfo width $w_c] * $have / $total}]
+ }
+
+ $w_c coords bar 0 0 $pixel_width 20
+ }
+}
+
+method stop {operation stop_msg} {
+ set idx [lsearch $operations $operation]
+
+ if {$idx >= 0} {
+ set operations [lreplace $operations $idx $idx]
+ set completed_operation_count [expr \
+ $completed_operation_count + 1]
+
+ if {[llength $operations] == 0} {
+ set completed_operation_count 0
+
+ destroy $w_c
+ if {$stop_msg ne {}} {
+ set baseline_text $stop_msg
+ }
+ }
+
+ $this refresh
+ }
+}
+
+method stop_all {{stop_msg {}}} {
+ # This makes the operation's call to stop a no-op.
+ set operations_copy $operations
+ set operations [list]
+
+ foreach operation $operations_copy {
+ $operation stop
+ }
+
+ if {$stop_msg ne {}} {
+ set baseline_text $stop_msg
+ }
+
+ $this refresh
+}
+
+method _delete {current} {
+ if {$current eq $w} {
+ delete_this
+ }
+}
+
+}
+
+# The status_bar_operation class tracks a single consumer's ongoing status bar
+# activity, with the context that there are a few situations where multiple
+# overlapping asynchronous operations might want to display status information
+# simultaneously. Instances of status_bar_operation are created by calling
+# start on the status_bar, and when the caller is done with its stauts bar
+# operation, it calls stop on the operation.
+
+class status_bar_operation {
+
+field status_bar; # reference back to the status_bar that owns this object
+
+field is_active;
+
+field status {}; # single line of text we show
+field progress {}; # current progress (0 to 100)
+field prefix {}; # text we format into status
+field units {}; # unit of progress
+field meter {}; # current core git progress meter (if active)
+
+constructor new {owner msg uds} {
+ set status_bar $owner
set status $msg
+ set progress 0
set prefix $msg
set units $uds
set meter {}
+
+ set is_active 1
+
+ return $this
}
+method get_is_active {} { return $is_active }
+method get_status {} { return $status }
+method get_progress {} { return $progress }
+
method update {have total} {
- set pdone 0
- set cdone 0
+ if {!$is_active} { return }
+
+ set progress 0
+
if {$total > 0} {
- set pdone [expr {100 * $have / $total}]
- set cdone [expr {[winfo width $w_c] * $have / $total}]
+ set progress [expr {100 * $have / $total}]
}
set prec [string length [format %i $total]]
+
set status [mc "%s ... %*i of %*i %s (%3i%%)" \
$prefix \
$prec $have \
$prec $total \
- $units $pdone]
- $w_c coords bar 0 0 $cdone 20
+ $units $progress]
+
+ $status_bar refresh
}
method update_meter {buf} {
+ if {!$is_active} { return }
+
append meter $buf
set r [string last "\r" $meter]
if {$r == -1} {
@@ -109,23 +288,25 @@ method update_meter {buf} {
}
}
-method stop {{msg {}}} {
- destroy $w_c
- if {$msg ne {}} {
- set status $msg
+method stop {{stop_msg {}}} {
+ if {$is_active} {
+ set is_active 0
+ $status_bar stop $this $stop_msg
}
}
-method show {msg {test {}}} {
- if {$test eq {} || $status eq $test} {
- set status $msg
- }
+method restart {msg} {
+ if {!$is_active} { return }
+
+ set status $msg
+ set prefix $msg
+ set meter {}
+ $status_bar refresh
}
-method _delete {current} {
- if {$current eq $w} {
- delete_this
- }
+method _delete {} {
+ stop
+ delete_this
}
}