From: Paul Mackerras Date: Wed, 29 Aug 2007 11:45:21 +0000 (+1000) Subject: gitk: Do only the parts of the layout that are needed X-Git-Url: https://privyetmir.co.uk/gitweb.cgi?a=commitdiff_plain;h=0380081c65c3e8a46caad9aebe8e97ff65510453;p=gitk gitk: Do only the parts of the layout that are needed This changes layoutrows and optimize_rows to make it possible to lay out only a little bit more of the graph than is visible, rather than having to lay out the whole graph from top to bottom. To lay out some of the graph without starting at the top, we use the new make_idlist procedure for the first row, then lay it out proceeding downwards as before. Empty list elements in rowidlist are used to denote rows that haven't been laid out yet. Optimizing happens much as before except that we don't try to optimize unless we have three consecutive rows laid out (or the top 2 rows). We have a new list, rowisopt, to record which rows have been optimized. If we change a row that has already been drawn, we set a flag which causes drawcommits to throw away everything drawn on the canvas and redraw the visible rows. Signed-off-by: Paul Mackerras --- diff --git a/gitk b/gitk index 7726c31..060c4c0 100755 --- a/gitk +++ b/gitk @@ -1949,13 +1949,13 @@ proc unflatten {var l} { proc showview {n} { global curview viewdata viewfiles - global displayorder parentlist rowidlist + global displayorder parentlist rowidlist rowisopt global colormap rowtextx commitrow nextcolor canvxmax global numcommits commitlisted global selectedline currentid canv canvy0 global treediffs global pending_select phase - global commitidx rowlaidout rowoptim + global commitidx global commfd global selectedview selectfirst global vparentlist vdisporder vcmitlisted @@ -1987,11 +1987,11 @@ proc showview {n} { set vcmitlisted($curview) $commitlisted if {$phase ne {}} { set viewdata($curview) \ - [list $phase $rowidlist $rowlaidout $rowoptim $numcommits] + [list $phase $rowidlist $rowisopt $numcommits] } elseif {![info exists viewdata($curview)] || [lindex $viewdata($curview) 0] ne {}} { set viewdata($curview) \ - [list {} $rowidlist] + [list {} $rowidlist $rowisopt] } } catch {unset treediffs} @@ -2021,12 +2021,11 @@ proc showview {n} { set parentlist $vparentlist($n) set commitlisted $vcmitlisted($n) set rowidlist [lindex $v 1] + set rowisopt [lindex $v 2] if {$phase eq {}} { set numcommits [llength $displayorder] } else { - set rowlaidout [lindex $v 2] - set rowoptim [lindex $v 3] - set numcommits [lindex $v 4] + set numcommits [lindex $v 3] } catch {unset colormap} @@ -2625,45 +2624,16 @@ proc shortids {ids} { return $res } -proc incrange {l x o} { - set n [llength $l] - while {$x < $n} { - set e [lindex $l $x] - if {$e ne {}} { - lset l $x [expr {$e + $o}] - } - incr x - } - return $l -} - proc ntimes {n o} { set ret {} - for {} {$n > 0} {incr n -1} { - lappend ret $o - } - return $ret -} - -proc usedinrange {id l1 l2} { - global children commitrow curview - - if {[info exists commitrow($curview,$id)]} { - set r $commitrow($curview,$id) - if {$l1 <= $r && $r <= $l2} { - return [expr {$r - $l1 + 1}] - } - } - set kids $children($curview,$id) - foreach c $kids { - if {[info exists commitrow($curview,$c)]} { - set r $commitrow($curview,$c) - if {$l1 <= $r && $r <= $l2} { - return [expr {$r - $l1 + 1}] - } + set o [list $o] + for {set mask 1} {$mask <= $n} {incr mask $mask} { + if {($n & $mask) != 0} { + set ret [concat $ret $o] } + set o [concat $o $o] } - return 0 + return $ret } # Work out where id should go in idlist so that order-token @@ -2689,20 +2659,8 @@ proc idcol {idlist id {i 0}} { return $i } -proc makeuparrow {oid y x} { - global rowidlist uparrowlen displayorder - - for {set i 0} {$i < $uparrowlen && $y > 1} {incr i} { - incr y -1 - set idl [lindex $rowidlist $y] - set x [idcol $idl $oid $x] - lset rowidlist $y [linsert $idl $x $oid] - } -} - proc initlayout {} { - global rowidlist displayorder commitlisted - global rowlaidout rowoptim + global rowidlist rowisopt displayorder commitlisted global numcommits canvxmax canv global nextcolor global parentlist @@ -2714,9 +2672,8 @@ proc initlayout {} { set commitlisted {} set parentlist {} set nextcolor 0 - set rowidlist {{}} - set rowlaidout 0 - set rowoptim 0 + set rowidlist {} + set rowisopt {} set canvxmax [$canv cget -width] catch {unset colormap} catch {unset rowtextx} @@ -2752,54 +2709,18 @@ proc visiblerows {} { } proc layoutmore {tmax allread} { - global rowlaidout rowoptim commitidx numcommits optim_delay - global uparrowlen curview rowidlist + global commitidx numcommits + global uparrowlen downarrowlen mingaplen curview - set showlast 0 - set showdelay $optim_delay - set optdelay [expr {$uparrowlen + 1}] - while {1} { - if {$rowoptim - $showdelay > $numcommits} { - showstuff [expr {$rowoptim - $showdelay}] $showlast - } elseif {$rowlaidout - $optdelay > $rowoptim} { - set nr [expr {$rowlaidout - $optdelay - $rowoptim}] - if {$nr > 100} { - set nr 100 - } - optimize_rows $rowoptim 0 [expr {$rowoptim + $nr}] - incr rowoptim $nr - } elseif {$commitidx($curview) > $rowlaidout} { - set nr [expr {$commitidx($curview) - $rowlaidout}] - # may need to increase this threshold if uparrowlen or - # mingaplen are increased... - if {$nr > 200} { - set nr 200 - } - set row $rowlaidout - set rowlaidout [layoutrows $row [expr {$row + $nr}] $allread] - if {$rowlaidout == $row} { - return 0 - } - } elseif {$allread} { - set optdelay 0 - set nrows $commitidx($curview) - if {[lindex $rowidlist $nrows] ne {}} { - layouttail - set rowlaidout $commitidx($curview) - } elseif {$rowoptim == $nrows} { - set showdelay 0 - set showlast 1 - if {$numcommits == $nrows} { - return 0 - } - } - } else { - return 0 - } - if {$tmax ne {} && [clock clicks -milliseconds] >= $tmax} { - return 1 - } + set show $commitidx($curview) + if {!$allread} { + set delay [expr {$uparrowlen + $mingaplen + $downarrowlen + 3}] + set show [expr {$show - $delay}] + } + if {$show > $numcommits} { + showstuff $show $allread } + return 0 } proc showstuff {canshow last} { @@ -2966,8 +2887,10 @@ proc nextuse {id row} { if {[info exists children($curview,$id)]} { foreach kid $children($curview,$id) { - if {[info exists commitrow($curview,$kid)] && - $commitrow($curview,$kid) > $row} { + if {![info exists commitrow($curview,$kid)]} { + return -1 + } + if {$commitrow($curview,$kid) > $row} { return $commitrow($curview,$kid) } } @@ -2978,97 +2901,171 @@ proc nextuse {id row} { return -1 } -proc layoutrows {row endrow last} { - global rowidlist displayorder - global uparrowlen downarrowlen maxwidth mingaplen - global children parentlist - global commitidx curview +proc make_idlist {row} { + global displayorder parentlist uparrowlen downarrowlen mingaplen + global commitidx curview ordertok children commitrow - set idlist [lindex $rowidlist $row] - if {!$last && $endrow + $uparrowlen + $mingaplen > $commitidx($curview)} { - set endrow [expr {$commitidx($curview) - $uparrowlen - $mingaplen}] + set r [expr {$row - $mingaplen - $downarrowlen - 1}] + if {$r < 0} { + set r 0 } - while {$row < $endrow} { - set id [lindex $displayorder $row] - if {$row > $downarrowlen} { - set termrow [expr {$row - $downarrowlen - 1}] - foreach p [lindex $parentlist $termrow] { - set i [lsearch -exact $idlist $p] - if {$i < 0} continue - set nr [nextuse $p $termrow] - if {$nr < 0 || $nr >= $row + $mingaplen + $uparrowlen} { - set idlist [lreplace $idlist $i $i] - } + set ra [expr {$row - $downarrowlen}] + if {$ra < 0} { + set ra 0 + } + set rb [expr {$row + $uparrowlen}] + if {$rb > $commitidx($curview)} { + set rb $commitidx($curview) + } + set ids {} + for {} {$r < $ra} {incr r} { + set nextid [lindex $displayorder [expr {$r + 1}]] + foreach p [lindex $parentlist $r] { + if {$p eq $nextid} continue + set rn [nextuse $p $r] + if {$rn >= $row && + $rn <= $r + $downarrowlen + $mingaplen + $uparrowlen} { + lappend ids [list $ordertok($curview,$p) $p] } - lset rowidlist $row $idlist } - set oldolds {} - set newolds {} - foreach p [lindex $parentlist $row] { - # is id the first child of this parent? - if {$id eq [lindex $children($curview,$p) 0]} { - lappend newolds $p - } elseif {[lsearch -exact $idlist $p] < 0} { - lappend oldolds $p + } + for {} {$r < $row} {incr r} { + set nextid [lindex $displayorder [expr {$r + 1}]] + foreach p [lindex $parentlist $r] { + if {$p eq $nextid} continue + set rn [nextuse $p $r] + if {$rn < 0 || $rn >= $row} { + lappend ids [list $ordertok($curview,$p) $p] } } - set col [lsearch -exact $idlist $id] - if {$col < 0} { - set col [idcol $idlist $id] - set idlist [linsert $idlist $col $id] - lset rowidlist $row $idlist - if {$children($curview,$id) ne {}} { - makeuparrow $id $row $col + } + set id [lindex $displayorder $row] + lappend ids [list $ordertok($curview,$id) $id] + while {$r < $rb} { + foreach p [lindex $parentlist $r] { + set firstkid [lindex $children($curview,$p) 0] + if {$commitrow($curview,$firstkid) < $row} { + lappend ids [list $ordertok($curview,$p) $p] } } - incr row - set idlist [lreplace $idlist $col $col] - set x $col - foreach i $newolds { - set x [idcol $idlist $i $x] - set idlist [linsert $idlist $x $i] - } - foreach oid $oldolds { - set x [idcol $idlist $oid $x] - set idlist [linsert $idlist $x $oid] - makeuparrow $oid $row $x + incr r + set id [lindex $displayorder $r] + if {$id ne {}} { + set firstkid [lindex $children($curview,$id) 0] + if {$firstkid ne {} && $commitrow($curview,$firstkid) < $row} { + lappend ids [list $ordertok($curview,$id) $id] + } } - lappend rowidlist $idlist } - return $row + set idlist {} + foreach idx [lsort -unique $ids] { + lappend idlist [lindex $idx 1] + } + return $idlist } -proc addextraid {id row} { - global displayorder commitrow commitinfo - global commitidx commitlisted - global parentlist children curview +proc layoutrows {row endrow} { + global rowidlist rowisopt displayorder + global uparrowlen downarrowlen maxwidth mingaplen + global children parentlist + global commitidx curview commitrow - incr commitidx($curview) - lappend displayorder $id - lappend commitlisted 0 - lappend parentlist {} - set commitrow($curview,$id) $row - readcommit $id - if {![info exists commitinfo($id)]} { - set commitinfo($id) {"No commit information available"} + set idlist {} + if {$row > 0} { + foreach id [lindex $rowidlist [expr {$row - 1}]] { + if {$id ne {}} { + lappend idlist $id + } + } } - if {![info exists children($curview,$id)]} { - set children($curview,$id) {} + for {} {$row < $endrow} {incr row} { + set rm1 [expr {$row - 1}] + if {$rm1 < 0 || [lindex $rowidlist $rm1] eq {}} { + set idlist [make_idlist $row] + } else { + set id [lindex $displayorder $rm1] + set col [lsearch -exact $idlist $id] + set idlist [lreplace $idlist $col $col] + foreach p [lindex $parentlist $rm1] { + if {[lsearch -exact $idlist $p] < 0} { + set col [idcol $idlist $p $col] + set idlist [linsert $idlist $col $p] + } + } + set id [lindex $displayorder $row] + if {$row > $downarrowlen} { + set termrow [expr {$row - $downarrowlen - 1}] + foreach p [lindex $parentlist $termrow] { + set i [lsearch -exact $idlist $p] + if {$i < 0} continue + set nr [nextuse $p $termrow] + if {$nr < 0 || $nr >= $row + $mingaplen + $uparrowlen} { + set idlist [lreplace $idlist $i $i] + } + } + } + set col [lsearch -exact $idlist $id] + if {$col < 0} { + set col [idcol $idlist $id] + set idlist [linsert $idlist $col $id] + } + set r [expr {$row + $uparrowlen - 1}] + if {$r < $commitidx($curview)} { + set x $col + foreach p [lindex $parentlist $r] { + if {[lsearch -exact $idlist $p] >= 0} continue + set fk [lindex $children($curview,$p) 0] + if {$commitrow($curview,$fk) < $row} { + set x [idcol $idlist $p $x] + set idlist [linsert $idlist $x $p] + } + } + if {[incr r] < $commitidx($curview)} { + set p [lindex $displayorder $r] + if {[lsearch -exact $idlist $p] < 0} { + set fk [lindex $children($curview,$p) 0] + if {$fk ne {} && $commitrow($curview,$fk) < $row} { + set x [idcol $idlist $p $x] + set idlist [linsert $idlist $x $p] + } + } + } + } + } + set l [llength $rowidlist] + if {$row == $l} { + lappend rowidlist $idlist + lappend rowisopt 0 + } elseif {$row < $l} { + if {$idlist ne [lindex $rowidlist $row]} { + lset rowidlist $row $idlist + changedrow $row + } + } else { + set rowidlist [concat $rowidlist [ntimes [expr {$row - $l}] {}]] + lappend rowidlist $idlist + set rowisopt [concat $rowisopt [ntimes [expr {$row - $l + 1}] 0]] + } } + return $row } -proc layouttail {} { - global rowidlist commitidx curview +proc changedrow {row} { + global displayorder iddrawn rowisopt need_redisplay - set row $commitidx($curview) - set idlist [lindex $rowidlist $row] - while {$idlist ne {}} { - set col [expr {[llength $idlist] - 1}] - set id [lindex $idlist $col] - addextraid $id $row - incr row - set idlist [lreplace $idlist $col $col] - lappend rowidlist $idlist + set l [llength $rowisopt] + if {$row < $l} { + lset rowisopt $row 0 + if {$row + 1 < $l} { + lset rowisopt [expr {$row + 1}] 0 + if {$row + 2 < $l} { + lset rowisopt [expr {$row + 2}] 0 + } + } + } + set id [lindex $displayorder $row] + if {[info exists iddrawn($id)]} { + set need_redisplay 1 } } @@ -3084,27 +3081,29 @@ proc insert_pad {row col npad} { set aft [lreplace $aft $i $i] } lset rowidlist $row [concat $bef $pad $aft] + changedrow $row } proc optimize_rows {row col endrow} { - global rowidlist displayorder curview children + global rowidlist rowisopt displayorder curview children if {$row < 1} { set row 1 } - set idlist [lindex $rowidlist [expr {$row - 1}]] - if {$row >= 2} { - set previdlist [lindex $rowidlist [expr {$row - 2}]] - } else { - set previdlist {} - } - for {} {$row < $endrow} {incr row} { - set pprevidlist $previdlist - set previdlist $idlist - set idlist [lindex $rowidlist $row] + for {} {$row < $endrow} {incr row; set col 0} { + if {[lindex $rowisopt $row]} continue set haspad 0 set y0 [expr {$row - 1}] set ym [expr {$row - 2}] + set idlist [lindex $rowidlist $row] + set previdlist [lindex $rowidlist $y0] + if {$idlist eq {} || $previdlist eq {}} continue + if {$ym >= 0} { + set pprevidlist [lindex $rowidlist $ym] + if {$pprevidlist eq {}} continue + } else { + set pprevidlist {} + } set x0 -1 set xm -1 for {} {$col < [llength $idlist]} {incr col} { @@ -3180,7 +3179,6 @@ proc optimize_rows {row col endrow} { incr x0 optimize_rows $y0 $x0 $row set previdlist [lindex $rowidlist $y0] - set pprevidlist [lindex $rowidlist $ym] } } if {!$haspad} { @@ -3203,10 +3201,10 @@ proc optimize_rows {row col endrow} { # isn't the last column if {$x0 >= 0 && [incr col] < [llength $idlist]} { set idlist [linsert $idlist $col {}] + lset rowidlist $row $idlist + changedrow $row } } - lset rowidlist $row $idlist - set col 0 } } @@ -3531,7 +3529,7 @@ proc drawcmittext {id row col} { global linespc canv canv2 canv3 canvy0 fgcolor curview global commitlisted commitinfo rowidlist parentlist global rowtextx idpos idtags idheads idotherrefs - global linehtag linentag linedtag + global linehtag linentag linedtag selectedline global mainfont canvxmax boldrows boldnamerows fgcolor nullid nullid2 # listed is 0 for boundary, 1 for normal, 2 for left, 3 for right @@ -3607,6 +3605,9 @@ proc drawcmittext {id row col} { -text $name -font $nfont -tags text] set linedtag($row) [$canv3 create text 3 $y -anchor w -fill $fgcolor \ -text $date -font $mainfont -tags text] + if {[info exists selectedline] && $selectedline == $row} { + make_secsel $row + } set xr [expr {$xt + [font measure $mainfont $headline]}] if {$xr > $canvxmax} { set canvxmax $xr @@ -3615,7 +3616,7 @@ proc drawcmittext {id row col} { } proc drawcmitrow {row} { - global displayorder rowidlist + global displayorder rowidlist nrows_drawn global iddrawn markingmatches global commitinfo parentlist numcommits global filehighlight fhighlights findstring nhighlights @@ -3649,6 +3650,7 @@ proc drawcmitrow {row} { assigncolor $id drawcmittext $id $row $col set iddrawn($id) 1 + incr nrows_drawn } if {$markingmatches} { markrowmatches $row $id @@ -3656,8 +3658,8 @@ proc drawcmitrow {row} { } proc drawcommits {row {endrow {}}} { - global numcommits iddrawn displayorder curview - global parentlist rowidlist + global numcommits iddrawn displayorder curview need_redisplay + global parentlist rowidlist uparrowlen downarrowlen nrows_drawn if {$row < 0} { set row 0 @@ -3669,6 +3671,35 @@ proc drawcommits {row {endrow {}}} { set endrow [expr {$numcommits - 1}] } + set rl1 [expr {$row - $downarrowlen - 3}] + if {$rl1 < 0} { + set rl1 0 + } + set ro1 [expr {$row - 3}] + if {$ro1 < 0} { + set ro1 0 + } + set r2 [expr {$endrow + $uparrowlen + 3}] + if {$r2 > $numcommits} { + set r2 $numcommits + } + for {set r $rl1} {$r < $r2} {incr r} { + if {[lindex $rowidlist $r] ne {}} { + if {$rl1 < $r} { + layoutrows $rl1 $r + } + set rl1 [expr {$r + 1}] + } + } + if {$rl1 < $r} { + layoutrows $rl1 $r + } + optimize_rows $ro1 0 $r2 + if {$need_redisplay || $nrows_drawn > 2000} { + clear_display + drawvisible + } + # make the lines join to already-drawn rows either side set r [expr {$row - 1}] if {$r < 0 || ![info exists iddrawn([lindex $displayorder $r])]} { @@ -3736,7 +3767,7 @@ proc drawvisible {} { } proc clear_display {} { - global iddrawn linesegs + global iddrawn linesegs need_redisplay nrows_drawn global vhighlights fhighlights nhighlights rhighlights allcanvs delete all @@ -3746,6 +3777,8 @@ proc clear_display {} { catch {unset fhighlights} catch {unset nhighlights} catch {unset rhighlights} + set need_redisplay 0 + set nrows_drawn 0 } proc findcrossings {id} { @@ -3967,9 +4000,9 @@ proc show_status {msg} { # on that row and below will move down one row. proc insertrow {row newcmit} { global displayorder parentlist commitlisted children - global commitrow curview rowidlist numcommits - global rowlaidout rowoptim numcommits - global selectedline commitidx + global commitrow curview rowidlist rowisopt numcommits + global numcommits + global selectedline commitidx ordertok if {$row >= $numcommits} { puts "oops, inserting new row $row but only have $numcommits rows" @@ -3989,6 +4022,7 @@ proc insertrow {row newcmit} { set commitrow($curview,$id) $r } incr commitidx($curview) + set ordertok($curview,$newcmit) $ordertok($curview,$p) set idlist [lindex $rowidlist $row] if {[llength $kids] == 1} { @@ -3999,9 +4033,8 @@ proc insertrow {row newcmit} { lappend idlist $newcmit } set rowidlist [linsert $rowidlist $row $idlist] + set rowisopt [linsert $rowisopt $row 0] - incr rowlaidout - incr rowoptim incr numcommits if {[info exists selectedline] && $selectedline >= $row} { @@ -4013,8 +4046,8 @@ proc insertrow {row newcmit} { # Remove a commit that was inserted with insertrow on row $row. proc removerow {row} { global displayorder parentlist commitlisted children - global commitrow curview rowidlist numcommits - global rowlaidout rowoptim numcommits + global commitrow curview rowidlist rowisopt numcommits + global numcommits global linesegends selectedline commitidx if {$row >= $numcommits} { @@ -4041,9 +4074,8 @@ proc removerow {row} { incr commitidx($curview) -1 set rowidlist [lreplace $rowidlist $row $row] + set rowisopt [lreplace $rowisopt $row $row] - incr rowlaidout -1 - incr rowoptim -1 incr numcommits -1 if {[info exists selectedline] && $selectedline > $row} { @@ -4485,9 +4517,27 @@ proc dispnexttag {} { } } +proc make_secsel {l} { + global linehtag linentag linedtag canv canv2 canv3 + + if {![info exists linehtag($l)]} return + $canv delete secsel + set t [eval $canv create rect [$canv bbox $linehtag($l)] -outline {{}} \ + -tags secsel -fill [$canv cget -selectbackground]] + $canv lower $t + $canv2 delete secsel + set t [eval $canv2 create rect [$canv2 bbox $linentag($l)] -outline {{}} \ + -tags secsel -fill [$canv2 cget -selectbackground]] + $canv2 lower $t + $canv3 delete secsel + set t [eval $canv3 create rect [$canv3 bbox $linedtag($l)] -outline {{}} \ + -tags secsel -fill [$canv3 cget -selectbackground]] + $canv3 lower $t +} + proc selectline {l isnew} { - global canv canv2 canv3 ctext commitinfo selectedline - global displayorder linehtag linentag linedtag + global canv ctext commitinfo selectedline + global displayorder global canvy0 linespc parentlist children curview global currentid sha1entry global commentend idtags linknum @@ -4536,19 +4586,7 @@ proc selectline {l isnew} { drawvisible } - if {![info exists linehtag($l)]} return - $canv delete secsel - set t [eval $canv create rect [$canv bbox $linehtag($l)] -outline {{}} \ - -tags secsel -fill [$canv cget -selectbackground]] - $canv lower $t - $canv2 delete secsel - set t [eval $canv2 create rect [$canv2 bbox $linentag($l)] -outline {{}} \ - -tags secsel -fill [$canv2 cget -selectbackground]] - $canv2 lower $t - $canv3 delete secsel - set t [eval $canv3 create rect [$canv3 bbox $linedtag($l)] -outline {{}} \ - -tags secsel -fill [$canv3 cget -selectbackground]] - $canv3 lower $t + make_secsel $l if {$isnew} { addtohistory [list selectline $l 0] @@ -5616,7 +5654,7 @@ proc arrowjump {id n y} { } proc lineclick {x y id isnew} { - global ctext commitinfo children canv thickerline curview + global ctext commitinfo children canv thickerline curview commitrow if {![info exists commitinfo($id)] && ![getcommit $id]} return unmarkmatches @@ -7922,8 +7960,8 @@ set boldnamerows {} set diffelide {0 0} set markingmatches 0 set linkentercount 0 - -set optim_delay 16 +set need_redisplay 0 +set nrows_drawn 0 set nextviewnum 1 set curview 0