Thread from comp.lang.tcl (4 replies)

Operate only on the visible lines in a text window
Posted by Shaun Deacon <sdeacon@us.socionext.com> 2 months 3 weeks ago

My application uses a text widget to display chip 'test vectors' from a 
loaded file. Each vector occupies a line - for example :

0011010XXLLLHH
0100110XXLHHLH
....
0110110XXHHHHH

A highlighting operation colors specified values (for example all 1's) 
for all lines of text in the widget. For small and medium sized files 
this is fine. However, test files can often be large (over 500,000 
vectors). The highlight operation applied to all lines is too slow in 
this case - the vectors are much longer strings in real life too.

The obvious solution to me is to just highlight the currently visible 
lines (or a range of lines spanning the current view - say 1000 or so) 
and when the user scrolls the window, highlight the new set of lines.

Suggestions on the best way to find the indexes for the currently 
visible lines when the widget has been scrolled would be great.

Can someone please point me in the right direction ?

For some reason, I can't seem to find what I'm looking for in CLT, the 
wiki or the man pages.

thanks
Shaun

Click on article to view all threads in comp.lang.tcl
Re: Operate only on the visible lines in a text window
Posted by et99 <et99@rocketship1.me> 2 months 3 weeks ago

On 7/9/2024 5:57 PM, Shaun Deacon wrote:
> My application uses a text widget to display chip 'test vectors' from a loaded file. Each vector occupies a line - for example :
> 
> 0011010XXLLLHH
> 0100110XXLHHLH
> ...
> 0110110XXHHHHH
> 
> A highlighting operation colors specified values (for example all 1's) for all lines of text in the widget. For small and medium sized files this is fine. However, test files can often be large (over 500,000 vectors). The highlight operation applied to all lines is too slow in this case - the vectors are much longer strings in real life too.
> 
> The obvious solution to me is to just highlight the currently visible lines (or a range of lines spanning the current view - say 1000 or so) and when the user scrolls the window, highlight the new set of lines.
> 
> Suggestions on the best way to find the indexes for the currently visible lines when the widget has been scrolled would be great.
> 
> Can someone please point me in the right direction ?
> 
> For some reason, I can't seem to find what I'm looking for in CLT, the wiki or the man pages.
> 
> thanks
> Shaun
> 

Can't you use the current cursor position? How is it scrolled, mouse wheel? scroll bar? The current cursor is at,

..textwidget index insert

You could likely estimate it using scrollbar info. But if there are 500k lines, how might someone get to the middle, by some sort of search?

The only way I know to find what lines in a text widget are on screen without any other info is using the bbox method. You can test if any particular $line is visible by using

..textwidget bbox $line.0

which will return a null list if not on screen, otherwise a list of numbers.

This could involve a large search to find the first and last line on-screen. I don't know how fast or slow that would be. You could likely test every Nth line if you know how many lines fit on screen.

et


Click on article to view all threads in comp.lang.tcl
Operate only on the visible lines in a text window
Posted by clt.to.davebr@dfgh.net 2 months 3 weeks ago

>
>Suggestions on the best way to find the indexes for the currently 
>visible lines when the widget has been scrolled would be great.

Try using the @x,y indices (see INDICES in the man page) and the text box index subcommand

For a text box named .t

..t index @0,0

returns the line number and column number of the character in the top left corner.

lindex [split [.t index @0,0] .] 0

returns just the line number of the top left character (droping the column number)

use winfo height .t to get the last line in the text box. perhaps using:

lindex [split [.t index @0,[winfo height .t]] .] 0


Dave B



Click on article to view all threads in comp.lang.tcl
Re: Operate only on the visible lines in a text window
Posted by Ralf Fassel <ralfixx@gmx.de> 2 months 3 weeks ago

* Shaun Deacon <sdeacon@us.socionext.com>
| The obvious solution to me is to just highlight the currently visible
| lines (or a range of lines spanning the current view - say 1000 or so)
| and when the user scrolls the window, highlight the new set of lines.
>
| Suggestions on the best way to find the indexes for the currently
| visible lines when the widget has been scrolled would be great.
>
| Can someone please point me in the right direction ?

You could try 'text yview' and derive the displayed lines from that:

    grid [text .t -yscrollcommand {recalc {.s set}}] -sticky ewns -row 0 -column 0
    grid [scrollbar .s -command {recalc {.t yview}} -orient vertical] -sticky ns -row 0 -column 1
    grid [label .l] - -sticky ewns
    grid rowconfigure . 0 -weight 1
    grid columnconfigure . 0 -weight 1
    for {set l 1} {$l < 1000} {incr l} {
        .t insert end "Line $l\n"
    }

    proc recalc {cmd args} {
        # scroll if required
        if {$cmd ne ""} {
            {*}$cmd {*}$args
        }
        # Determine the visible range
        lassign [.t yview] start end
        # Get line count
        set lines [lindex [split [.t index end] "."] 0]
        # Get first and last line displayed.
        # Here you need to determine what to do with the partially displayed lines
        set first [format %.1f [expr {$start*$lines+1}]]
        set last [format %.1f [expr {$end*$lines}]]
        
        .l configure -text "visible Lines $first ... $last"
    }
    bind . <Configure> [list recalc ""]

HTH
R'

Click on article to view all threads in comp.lang.tcl
Re: Operate only on the visible lines in a text window
Posted by Shaun Deacon <sdeacon@us.socionext.com> 2 months 3 weeks ago

Ralf Fassel wrote:
> * Shaun Deacon <sdeacon@us.socionext.com>
> | The obvious solution to me is to just highlight the currently visible
> | lines (or a range of lines spanning the current view - say 1000 or so)
> | and when the user scrolls the window, highlight the new set of lines.
>>
> | Suggestions on the best way to find the indexes for the currently
> | visible lines when the widget has been scrolled would be great.
>>
> | Can someone please point me in the right direction ?
> 
> You could try 'text yview' and derive the displayed lines from that:
> 
>      grid [text .t -yscrollcommand {recalc {.s set}}] -sticky ewns -row 0 -column 0
>      grid [scrollbar .s -command {recalc {.t yview}} -orient vertical] -sticky ns -row 0 -column 1
>      grid [label .l] - -sticky ewns
>      grid rowconfigure . 0 -weight 1
>      grid columnconfigure . 0 -weight 1
>      for {set l 1} {$l < 1000} {incr l} {
>          .t insert end "Line $l\n"
>      }
> 
>      proc recalc {cmd args} {
>          # scroll if required
>          if {$cmd ne ""} {
>              {*}$cmd {*}$args
>          }
>          # Determine the visible range
>          lassign [.t yview] start end
>          # Get line count
>          set lines [lindex [split [.t index end] "."] 0]
>          # Get first and last line displayed.
>          # Here you need to determine what to do with the partially displayed lines
>          set first [format %.1f [expr {$start*$lines+1}]]
>          set last [format %.1f [expr {$end*$lines}]]
>          
>          .l configure -text "visible Lines $first ... $last"
>      }
>      bind . <Configure> [list recalc ""]
> 
> HTH
> R'
> 

Thanks Ralf, this looks promising to me.
Shaun

Click on article to view all threads in comp.lang.tcl