summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: a37eee4)
raw | patch | inline | side by side (parent: a37eee4)
author | Shawn O. Pearce <spearce@spearce.org> | |
Mon, 13 Nov 2006 21:06:38 +0000 (16:06 -0500) | ||
committer | Shawn O. Pearce <spearce@spearce.org> | |
Mon, 13 Nov 2006 21:06:38 +0000 (16:06 -0500) |
Because I want to let users apply actions to more than one file at
a time we really needed a concept of "the current selection" from
the two file lists.
Since I'm abusing a Tk text widget for the file displays I can't
really use the Tk selection to track which files are picked and
which aren't. So instead we keep this in an array to tell us
which paths are currently selected and we use an inverse fg/bg
for the selected file display. This is common most operating
systems as a selection indicator.
The selection works like most users would expect; single click will
clear the selection and pick only that file, M1-click (aka Ctrl-click
or Cmd-click) will toggle the one file in/out of the selection, and
Shift-click will select the range between the last clicked file and
the currently clicked file.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
a time we really needed a concept of "the current selection" from
the two file lists.
Since I'm abusing a Tk text widget for the file displays I can't
really use the Tk selection to track which files are picked and
which aren't. So instead we keep this in an array to tell us
which paths are currently selected and we use an inverse fg/bg
for the selected file display. This is common most operating
systems as a selection indicator.
The selection works like most users would expect; single click will
clear the selection and pick only that file, M1-click (aka Ctrl-click
or Cmd-click) will toggle the one file in/out of the selection, and
Shift-click will select the range between the last clicked file and
the currently clicked file.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
git-gui | patch | blob | history |
index 6b8d25e9aabccb4430857ac3eb446fc8363ba30f..a60bf1c8a33f274cc5404cd71d7265554527b8d7 100755 (executable)
--- a/git-gui
+++ b/git-gui
set status_active 0
set diff_active 0
+set last_clicked {}
set disable_on_lock [list]
set index_lock_type none
incr z2 -1
display_file \
[string range $buf_rdi $z1 $z2] \
- [string index $buf_rdi [expr $z1 - 2]]_
+ [string index $buf_rdi [expr {$z1 - 2}]]_
incr c
}
if {$c < $n} {
incr z2 -1
display_file \
[string range $buf_rdf $z1 $z2] \
- _[string index $buf_rdf [expr $z1 - 2]]
+ _[string index $buf_rdf [expr {$z1 - 2}]]
incr c
}
if {$c < $n} {
close $fd
if {[incr status_active -1] > 0} return
+ prune_selection
unlock_index
display_all_files
set ui_status_value $final
}
+proc prune_selection {} {
+ global file_states selected_paths
+
+ foreach path [array names selected_paths] {
+ if {[catch {set still_here $file_states($path)}]} {
+ unset selected_paths($path)
+ }
+ }
+}
+
######################################################################
##
## diff
[lreplace $file_lists($old_w) $lno $lno]
incr lno
$old_w conf -state normal
- $old_w delete $lno.0 [expr $lno + 1].0
+ $old_w delete $lno.0 [expr {$lno + 1}].0
$old_w conf -state disabled
}
}
}
}
if {$w ne {} && $lno >= 1} {
- $w tag add in_diff $lno.0 [expr $lno + 1].0
+ $w tag add in_diff $lno.0 [expr {$lno + 1}].0
}
set s $file_states($path)
proc commit_stage3 {fd_wt curHEAD msg} {
global single_commit gitdir HEAD PARENT commit_type tcl_platform
global ui_status_value ui_comm
- global file_states
+ global file_states selected_paths
gets $fd_wt tree_id
if {$tree_id eq {} || [catch {close $fd_wt} err]} {
}
set i [string first "\n" $msg]
if {$i >= 0} {
- append reflogm {: } [string range $msg 0 [expr $i - 1]]
+ append reflogm {: } [string range $msg 0 [expr {$i - 1}]]
} else {
append reflogm {: } $msg
}
if {$m eq {__}} {
unset file_states($path)
+ catch {unset selected_paths($path)}
} else {
lset file_states($path) 0 $m
}
}
proc display_file {path state} {
- global file_states file_lists status_active
+ global file_states file_lists selected_paths status_active
set old_m [merge_state $path $state]
if {$status_active} return
if {$lno >= 0} {
incr lno
$old_w conf -state normal
- $old_w delete $lno.0 [expr $lno + 1].0
+ $old_w delete $lno.0 [expr {$lno + 1}].0
$old_w conf -state disabled
}
-name [lindex $s 1] \
-image $new_icon
$new_w insert $lno.1 "[escape_path $path]\n"
+ if {[catch {set in_sel $selected_paths($path)}]} {
+ set in_sel 0
+ }
+ if {$in_sel} {
+ $new_w tag add in_sel $lno.0 [expr {$lno + 1}].0
+ }
$new_w conf -state disabled
} elseif {$new_icon ne [mapicon $old_m $path]} {
$new_w conf -state normal
}
proc display_all_files {} {
- global ui_index ui_other file_states file_lists
+ global ui_index ui_other
+ global file_states file_lists
+ global last_clicked selected_paths
$ui_index conf -state normal
$ui_other conf -state normal
$ui_index delete 0.0 end
$ui_other delete 0.0 end
+ set last_clicked {}
set file_lists($ui_index) [list]
set file_lists($ui_other) [list]
set m [lindex $s 0]
set w [mapcol $m $path]
lappend file_lists($w) $path
+ set lno [expr {[lindex [split [$w index end] .] 0] - 1}]
$w image create end \
-align center -padx 5 -pady 1 \
-name [lindex $s 1] \
-image [mapicon $m $path]
$w insert end "[escape_path $path]\n"
+ if {[catch {set in_sel $selected_paths($path)}]} {
+ set in_sel 0
+ }
+ if {$in_sel} {
+ $w tag add in_sel $lno.0 [expr {$lno + 1}].0
+ }
}
$ui_index conf -state disabled
while {$c < $n} {
set cr [string first "\r" $buf $c]
set lf [string first "\n" $buf $c]
- if {$cr < 0} {set cr [expr $n + 1]}
- if {$lf < 0} {set lf [expr $n + 1]}
+ if {$cr < 0} {set cr [expr {$n + 1}]}
+ if {$lf < 0} {set lf [expr {$n + 1}]}
if {$lf < $cr} {
$w.m.t insert end [string range $buf $c $lf]
destroy $w
}
-proc file_left_click {w x y} {
- global file_lists
+proc toggle_or_diff {w x y} {
+ global file_lists ui_index ui_other
+ global last_clicked selected_paths
set pos [split [$w index @$x,$y] .]
set lno [lindex $pos 0]
set col [lindex $pos 1]
- set path [lindex $file_lists($w) [expr $lno - 1]]
- if {$path eq {}} return
+ set path [lindex $file_lists($w) [expr {$lno - 1}]]
+ if {$path eq {}} {
+ set last_clicked {}
+ return
+ }
+
+ set last_clicked [list $w $lno]
+ array unset selected_paths
+ $ui_index tag remove in_sel 0.0 end
+ $ui_other tag remove in_sel 0.0 end
- if {$col > 0} {
+ if {$col == 0} {
+ update_index [list $path]
+ } else {
show_diff $path $w $lno
}
}
-proc file_left_unclick {w x y} {
+proc add_one_to_selection {w x y} {
global file_lists
+ global last_clicked selected_paths
set pos [split [$w index @$x,$y] .]
set lno [lindex $pos 0]
set col [lindex $pos 1]
- set path [lindex $file_lists($w) [expr $lno - 1]]
- if {$path eq {}} return
+ set path [lindex $file_lists($w) [expr {$lno - 1}]]
+ if {$path eq {}} {
+ set last_clicked {}
+ return
+ }
- if {$col == 0} {
- update_index [list $path]
+ set last_clicked [list $w $lno]
+ if {[catch {set in_sel $selected_paths($path)}]} {
+ set in_sel 0
+ }
+ if {$in_sel} {
+ unset selected_paths($path)
+ $w tag remove in_sel $lno.0 [expr {$lno + 1}].0
+ } else {
+ set selected_paths($path) 1
+ $w tag add in_sel $lno.0 [expr {$lno + 1}].0
+ }
+}
+
+proc add_range_to_selection {w x y} {
+ global file_lists
+ global last_clicked selected_paths
+
+ if {[lindex $last_clicked 0] ne $w} {
+ toggle_or_diff $w $x $y
+ return
}
+
+ set pos [split [$w index @$x,$y] .]
+ set lno [lindex $pos 0]
+ set lc [lindex $last_clicked 1]
+ if {$lc < $lno} {
+ set begin $lc
+ set end $lno
+ } else {
+ set begin $lno
+ set end $lc
+ }
+
+ foreach path [lrange $file_lists($w) \
+ [expr {$begin - 1}] \
+ [expr {$end - 1}]] {
+ set selected_paths($path) 1
+ }
+ $w tag add in_sel $begin.0 [expr {$end + 1}].0
}
######################################################################
pack $ui_other -side left -fill both -expand 1
.vpane.files add .vpane.files.other -sticky nsew
-$ui_index tag conf in_diff -font font_uibold
-$ui_other tag conf in_diff -font font_uibold
+foreach i [list $ui_index $ui_other] {
+ $i tag conf in_diff -font font_uibold
+ $i tag conf in_sel \
+ -background [$i cget -foreground] \
+ -foreground [$i cget -background]
+}
+unset i
# -- Diff and Commit Area
frame .vpane.lower -height 300 -width 400
bind all <$M1B-Key-w> {destroy [winfo toplevel %W]}
bind all <$M1B-Key-W> {destroy [winfo toplevel %W]}
foreach i [list $ui_index $ui_other] {
- bind $i <Button-1> {file_left_click %W %x %y; break}
- bind $i <ButtonRelease-1> {file_left_unclick %W %x %y; break}
+ bind $i <Button-1> "toggle_or_diff $i %x %y; break"
+ bind $i <$M1B-Button-1> "add_one_to_selection $i %x %y; break"
+ bind $i <Shift-Button-1> "add_range_to_selection $i %x %y; break"
}
unset i